Compare commits

...

99 Commits

Author SHA1 Message Date
Sathish Kumar
1bb905b640 [APPS-3129] Reverting changes MNT-24137 2024-12-17 13:47:21 +05:30
Sathish Kumar
d0c6f0a920 fix for apps-3129 2024-12-12 10:03:09 +05:30
Sathish Kumar
21e37b9ed6 fix for apps-3129 2024-12-12 09:29:10 +05:30
Sathish Kumar
131f6e67da fix for the apps-3129 2024-12-12 09:08:17 +05:30
Aleksandra Onych
4b549bf474 [ACS-8862] Bump Keycloak to 25.0.6 (#2993) 2024-10-11 15:05:39 +02:00
alfresco-build
e7a8cc2b2b [maven-release-plugin][skip ci] prepare for next development iteration 2024-10-07 12:33:27 +00:00
alfresco-build
386c33c3c0 [maven-release-plugin][skip ci] prepare release 23.3.1.4 2024-10-07 12:33:24 +00:00
Tom Page
45d6a114c6 Merge pull request #2970 from Alfresco/feature/PrecommitChecks_23.3
Add precommit for secret scanning, formatting and license header checking.
2024-10-07 12:51:36 +01:00
Tom Page
3f2f654ac9 Add precommit for secret scanning, formatting and license header checking. (#2938)
* Add precommit for secret scanning, formatting and license header checking.

* Turn off bash debug logging.

* Skip precommit checks that apply to all files.

There are too many violations to run against all files.

(cherry picked from commit b00e11cb6f)
2024-10-07 11:53:26 +01:00
alfresco-build
27e955e947 [maven-release-plugin][skip ci] prepare for next development iteration 2024-09-24 12:43:18 +00:00
alfresco-build
91a8d6deb2 [maven-release-plugin][skip ci] prepare release 23.3.1.3 2024-09-24 12:43:16 +00:00
Tiago Salvado
c9b0389533 [MNT-24590] Bump spring-webscripts to 9.3 (#2922) (#2930)
* [MNT-24590] Bump spring-webscripts to 9.3

* Removed duplicated property: dependency.webscripts.version

(cherry picked from commit d17c11b8ad)
2024-09-24 13:04:13 +01:00
alfresco-build
27177f6ea3 [maven-release-plugin][skip ci] prepare for next development iteration 2024-09-03 14:25:27 +00:00
alfresco-build
1c7fb4fa32 [maven-release-plugin][skip ci] prepare release 23.3.1.2 2024-09-03 14:25:25 +00:00
Aleksandra Onych
ae63f29c1f ACS-8670 Deal with upcoming GitHub Actions deprecations (#2877)
Co-authored-by: Domenico Sibilio <domenicosibilio@gmail.com>
2024-09-03 15:48:03 +02:00
alfresco-build
252f177d8e [maven-release-plugin][skip ci] prepare for next development iteration 2024-08-28 11:00:17 +00:00
alfresco-build
5df64264ed [maven-release-plugin][skip ci] prepare release 23.3.1.1 2024-08-28 11:00:15 +00:00
Domenico Sibilio
656f5e29a5 PRODDEL-8304 Bump API Explorer to 23.3.0 (#2882) 2024-08-28 12:12:29 +02:00
mpichura
58cb8bf389 Creating hotfix branch release/23.3 for 23.3.0 ACS release [skip ci] 2024-08-23 17:07:54 +02:00
alfresco-build
1f3e08f439 [maven-release-plugin][skip ci] prepare release 23.3.0.98 2024-08-22 10:03:30 +00:00
Kacper Magdziarz
5efa236cfe [ACS-8521] Bump ATS 4.1.4 (#2867) 2024-08-22 11:26:57 +02:00
alfresco-build
df658371cd [maven-release-plugin][skip ci] prepare for next development iteration 2024-08-22 08:36:50 +00:00
alfresco-build
65f6d0ee45 [maven-release-plugin][skip ci] prepare release 23.3.0.97 2024-08-22 08:36:48 +00:00
rrajoria
275c42014e Bump AOS Version 3.1.0 2024-08-22 13:27:20 +05:30
alfresco-build
d0135e4b76 [maven-release-plugin][skip ci] prepare for next development iteration 2024-08-19 12:27:22 +00:00
alfresco-build
d405be6273 [maven-release-plugin][skip ci] prepare release 23.3.0.96 2024-08-19 12:27:20 +00:00
Paweł Rainer
b7862932e6 MNT-24126: add support for rendition service 2 (#2853) 2024-08-19 13:46:09 +02:00
alfresco-build
970bca464f [maven-release-plugin][skip ci] prepare for next development iteration 2024-08-18 00:07:10 +00:00
alfresco-build
f76d43eced [maven-release-plugin][skip ci] prepare release 23.3.0.95 2024-08-18 00:07:08 +00:00
Alfresco CI User
e07c452cf0 [force] Force release for 2024-08-18. 2024-08-18 00:04:14 +00:00
alfresco-build
64899ca358 [maven-release-plugin][skip ci] prepare for next development iteration 2024-08-13 08:28:39 +00:00
alfresco-build
de498664b6 [maven-release-plugin][skip ci] prepare release 23.3.0.94 2024-08-13 08:28:35 +00:00
Marcin Strankowski
46031feb52 [skip tests] Retry push 2024-08-13 10:24:15 +02:00
dependabot[bot]
a93686acd5 Bump org.postgresql:postgresql from 42.6.0 to 42.7.3 (#2512) 2024-08-13 07:29:49 +00:00
alfresco-build
aa86d07738 [maven-release-plugin][skip ci] prepare for next development iteration 2024-08-08 10:47:46 +00:00
alfresco-build
553a8aae1c [maven-release-plugin][skip ci] prepare release 23.3.0.93 2024-08-08 10:47:43 +00:00
rrajoria
f1bf73c269 Update AOS Alpha version 2024-08-08 13:38:53 +05:30
alfresco-build
64fa671f33 [maven-release-plugin][skip ci] prepare for next development iteration 2024-08-07 17:58:45 +00:00
alfresco-build
70c1da0213 [maven-release-plugin][skip ci] prepare release 23.3.0.92 2024-08-07 17:58:42 +00:00
Sara
283fffef00 ACS-8520 Bump t-core to 5.1.4-A3, ATS 4.1.4-A2 (#2843) 2024-08-07 18:09:42 +01:00
alfresco-build
e99e3d69ba [maven-release-plugin][skip ci] prepare for next development iteration 2024-08-07 10:57:05 +00:00
alfresco-build
f826b08b2b [maven-release-plugin][skip ci] prepare release 23.3.0.91 2024-08-07 10:57:03 +00:00
Damian Ujma
3bd57adeef ACS-8370 Switch to new tags for tomcat base images in Dockerfiles (#2841)
* ACS-8370 Switch to new tags for tomcat base images in Dockerfiles

* ACS-8370 Update fontconfig package

* ACS-8370 Update tomcat image SHA
2024-08-07 12:15:29 +02:00
alfresco-build
a4f8b8d4b9 [maven-release-plugin][skip ci] prepare for next development iteration 2024-08-06 07:36:20 +00:00
alfresco-build
6363c9e17a [maven-release-plugin][skip ci] prepare release 23.3.0.90 2024-08-06 07:36:18 +00:00
dependabot[bot]
b8a94ff310 Bump io.fabric8:docker-maven-plugin from 0.43.4 to 0.45.0 (#2831)
Bumps [io.fabric8:docker-maven-plugin](https://github.com/fabric8io/docker-maven-plugin) from 0.43.4 to 0.45.0.
- [Release notes](https://github.com/fabric8io/docker-maven-plugin/releases)
- [Changelog](https://github.com/fabric8io/docker-maven-plugin/blob/master/doc/changelog.md)
- [Commits](https://github.com/fabric8io/docker-maven-plugin/compare/v0.43.4...v0.45.0)

---
updated-dependencies:
- dependency-name: io.fabric8:docker-maven-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-06 08:57:54 +02:00
alfresco-build
fd9e279715 [maven-release-plugin][skip ci] prepare for next development iteration 2024-08-05 14:21:04 +00:00
alfresco-build
6210ca95f9 [maven-release-plugin][skip ci] prepare release 23.3.0.89 2024-08-05 14:21:01 +00:00
Igor Białas
7edba79f69 Improve README (#2834) 2024-08-05 15:41:41 +02:00
alfresco-build
1eb24d2d85 [maven-release-plugin][skip ci] prepare for next development iteration 2024-08-04 00:06:56 +00:00
alfresco-build
3305eb91e5 [maven-release-plugin][skip ci] prepare release 23.3.0.88 2024-08-04 00:06:55 +00:00
Alfresco CI User
0994545c65 [force] Force release for 2024-08-04. 2024-08-04 00:04:06 +00:00
alfresco-build
94377f1e30 [maven-release-plugin][skip ci] prepare for next development iteration 2024-08-02 14:09:28 +00:00
alfresco-build
9c9d3dbbd5 [maven-release-plugin][skip ci] prepare release 23.3.0.87 2024-08-02 14:09:26 +00:00
Domenico Sibilio
7b4c210773 ACS-8421 Bump Transform Core to 5.1.4-A1 + Service to 4.1.4-A1 (#2839) 2024-08-02 15:30:46 +02:00
alfresco-build
06d500311c [maven-release-plugin][skip ci] prepare for next development iteration 2024-07-31 07:05:57 +00:00
alfresco-build
8d95ffc9ff [maven-release-plugin][skip ci] prepare release 23.3.0.86 2024-07-31 07:05:54 +00:00
varapathijanakiram
6e05d5d157 Merge pull request #2832 from Alfresco/feature/MNT-24400-Suggester-feature
Suggester feature in Share
2024-07-31 11:54:20 +05:30
vjanakiram
dfff72849d I have added bean 2024-07-29 21:17:30 +05:30
alfresco-build
d60172e860 [maven-release-plugin][skip ci] prepare for next development iteration 2024-07-28 00:07:08 +00:00
alfresco-build
3cac4e8206 [maven-release-plugin][skip ci] prepare release 23.3.0.85 2024-07-28 00:07:05 +00:00
Alfresco CI User
b35a64d14f [force] Force release for 2024-07-28. 2024-07-28 00:04:10 +00:00
alfresco-build
10e78191dd [maven-release-plugin][skip ci] prepare for next development iteration 2024-07-25 21:03:12 +00:00
alfresco-build
6290c46d62 [maven-release-plugin][skip ci] prepare release 23.3.0.84 2024-07-25 21:03:09 +00:00
Tiago Salvado
8a61badabc [MNT-24513] Immutable user (IDS): allow to change enabled status (#2789)
* [MNT-24513] Immutable user: allow enabled status change

* [MNT-24513] Created 'allow.immutable.user.enabled.status.update' to control whether an immutabled user enabled status can be changed or not

* [MNT-24513] Regardless user details enabled status, the person nodeRef enabled status is also checked

* [MNT-24513] Prevent LDAP users from being disabled. Changed variable name.
2024-07-25 21:23:51 +01:00
alfresco-build
f9946827c4 [maven-release-plugin][skip ci] prepare for next development iteration 2024-07-24 13:18:42 +00:00
alfresco-build
b812c7856e [maven-release-plugin][skip ci] prepare release 23.3.0.83 2024-07-24 13:18:40 +00:00
Eva Vasques
a3f6e13a7c MNT-24503 - FixedAclUpdater Job - Skip count if maxSize is set (#2809) 2024-07-24 13:40:50 +01:00
alfresco-build
afffc7e870 [maven-release-plugin][skip ci] prepare for next development iteration 2024-07-24 05:54:22 +00:00
alfresco-build
fe5a01e2bd [maven-release-plugin][skip ci] prepare release 23.3.0.82 2024-07-24 05:54:20 +00:00
purusothaman-mm
03625565e9 [MNT-24292] fix for delete vulnerability (#2806) 2024-07-24 10:45:14 +05:30
alfresco-build
8d1d2b4f1b [maven-release-plugin][skip ci] prepare for next development iteration 2024-07-23 11:55:48 +00:00
alfresco-build
1342c6a7bb [maven-release-plugin][skip ci] prepare release 23.3.0.81 2024-07-23 11:55:45 +00:00
Tom Page
17152b69fc Merge pull request #2807 from Alfresco/feature/PMD730
[skip tests] Upgrade ya-pmd-scan.
2024-07-23 12:43:50 +01:00
Tom Page
1a7027327e [skip tests] PRODENG-291 Upgrade ya-pmd-scan. 2024-07-23 12:17:46 +01:00
alfresco-build
7921969222 [maven-release-plugin][skip ci] prepare for next development iteration 2024-07-21 00:07:02 +00:00
alfresco-build
9cc93de7b2 [maven-release-plugin][skip ci] prepare release 23.3.0.80 2024-07-21 00:07:00 +00:00
Alfresco CI User
55c9cf3407 [force] Force release for 2024-07-21. 2024-07-21 00:04:10 +00:00
alfresco-build
120f45ba92 [maven-release-plugin][skip ci] prepare for next development iteration 2024-07-19 09:04:23 +00:00
alfresco-build
eacdbd3770 [maven-release-plugin][skip ci] prepare release 23.3.0.79 2024-07-19 09:04:21 +00:00
dependabot[bot]
93d4701d80 Bump dependency.cxf.version from 4.0.4 to 4.0.5 (#2794)
Bumps `dependency.cxf.version` from 4.0.4 to 4.0.5.

Updates `org.apache.cxf:cxf-rt-frontend-jaxws` from 4.0.4 to 4.0.5

Updates `org.apache.cxf:cxf-rt-frontend-jaxrs` from 4.0.4 to 4.0.5

Updates `org.apache.cxf:cxf-rt-rs-client` from 4.0.4 to 4.0.5

Updates `org.apache.cxf:cxf-rt-transports-http` from 4.0.4 to 4.0.5

Updates `org.apache.cxf:cxf-rt-ws-policy` from 4.0.4 to 4.0.5

---
updated-dependencies:
- dependency-name: org.apache.cxf:cxf-rt-frontend-jaxws
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.apache.cxf:cxf-rt-frontend-jaxrs
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.apache.cxf:cxf-rt-rs-client
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.apache.cxf:cxf-rt-transports-http
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.apache.cxf:cxf-rt-ws-policy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-19 10:22:28 +02:00
alfresco-build
64baf03818 [maven-release-plugin][skip ci] prepare for next development iteration 2024-07-18 08:49:23 +00:00
alfresco-build
e39606aec5 [maven-release-plugin][skip ci] prepare release 23.3.0.78 2024-07-18 08:49:21 +00:00
Manish Kumar
7581e07c3c Merge pull request #2790 from Alfresco/fix/PRODSEC-8922-XSS
[PRODSEC-8922] fix xss vulnerability
2024-07-18 13:41:30 +05:30
alfresco-build
a01d375e6f [maven-release-plugin][skip ci] prepare for next development iteration 2024-07-17 11:25:21 +00:00
alfresco-build
a98f44803a [maven-release-plugin][skip ci] prepare release 23.3.0.77 2024-07-17 11:25:19 +00:00
SathishK-T
cabc38b386 [MNT-24137] Audit Issue Internal Server Error fix (#2786)
* [MNT-24137][ags][tas] Audit Bug Fix

* [MNT-24137][ags][tas] Audit Bug Fix

* [MNT-24137][ags][tas] Audit Bug Fix

* [MNT-24137][ags][tas] Audit Bug Fix

* [MNT-24137][ags][tas] Audit Bug Fix

* [MNT-24137][ags][tas] Audit Bug Fix

* [MNT-24137][ags][tas] Audit Bug Fix

---------

Co-authored-by: Sathish Kumar <ST28@ford.com>
2024-07-17 16:19:19 +05:30
Eva Vasques
9ed29967b7 MNT-24503 - Limits on FixedAclUpdater (#2788)
* Limit the job execution to a configurable amount of nodes (system.fixedACLsUpdater.maxItems)
    * Add query template select_NodesWithAspectIds_Limited that does a left join with alf_store and limits the results
    * Query executions by the job are now limited to maxItemBatchSize
    * Imposing the order by in the query is now configurable (system.fixedACLsUpdater.orderNodes)
2024-07-17 11:47:06 +01:00
alfresco-build
b63a3eae9b [maven-release-plugin][skip ci] prepare for next development iteration 2024-07-17 10:20:52 +00:00
alfresco-build
1ce46c2039 [maven-release-plugin][skip ci] prepare release 23.3.0.76 2024-07-17 10:20:50 +00:00
Suneet Gupta
278aa59302 [MNT-24310] Fix AGS Rest API returning non RM objects (#2787)
* [MNT-24310] Fix AGS Rest API returning non RM objects

* [MNT-24310] Fix AGS Rest API returning non RM objects

* [MNT-24310] Fix AGS Rest API returning non RM objects

* [MNT-24310] Fix AGS Rest API returning non RM objects

* [MNT-24310] Fix AGS Rest API returning non RM objects
2024-07-17 15:14:57 +05:30
Manish Kumar
51a51ecd6b [PRODSEC-8922] fix xss vulnerability 2024-07-17 13:52:19 +05:30
alfresco-build
10f4b10ae8 [maven-release-plugin][skip ci] prepare for next development iteration 2024-07-15 16:37:35 +00:00
alfresco-build
24575c436e [maven-release-plugin][skip ci] prepare release 23.3.0.75 2024-07-15 16:37:33 +00:00
Manish Kumar
25c4b677de [PRODSEC-9364] added java-uuid-generator (#2778)
* [PRODSEC-9364] added java-uuid-generator

* [PRODSEC-9364] addressed formatting issues

* [PRODSEC-9364] removed unnecessary qualifier java.util

* [PRODSEC-9364] removed addition import and change year in header
2024-07-15 21:29:09 +05:30
alfresco-build
6f13f36c5a [maven-release-plugin][skip ci] prepare for next development iteration 2024-07-15 09:02:19 +00:00
alfresco-build
db8b353fb1 [maven-release-plugin][skip ci] prepare release 23.3.0.74 2024-07-15 09:02:17 +00:00
Wojtek Świętoń
2ccdee122a ACS-8394 ReportPortal Integration run only on master, as an optional step 2024-07-15 10:22:29 +02:00
alfresco-build
14c1b91a9b [maven-release-plugin][skip ci] prepare for next development iteration 2024-07-14 00:06:55 +00:00
70 changed files with 5928 additions and 2821 deletions

View File

@@ -42,9 +42,17 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- uses: actions/checkout@v4
with:
fetch-depth: 0
- id: changed-files
uses: Alfresco/alfresco-build-tools/.github/actions/github-list-changes@v6.1.0
with:
write-list-to-env: true
- uses: Alfresco/alfresco-build-tools/.github/actions/pre-commit@v6.1.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Prepare maven cache and check compilation"
@@ -62,12 +70,12 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- uses: Alfresco/alfresco-build-tools/.github/actions/veracode@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/veracode@v7.0.0
continue-on-error: true
with:
srcclr-api-token: ${{ secrets.SRCCLR_API_TOKEN }}
@@ -85,10 +93,10 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/github-download-file@v5.6.0
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/github-download-file@v7.0.0
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
repository: "Alfresco/veracode-baseline-archive"
@@ -118,7 +126,7 @@ jobs:
run: zip readable_output.zip results.json
- name: Upload Artifact
if: success() || failure()
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Veracode Pipeline-Scan Results (Human Readable)
path: readable_output.zip
@@ -135,10 +143,10 @@ 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@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/ya-pmd-scan@v3.0.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- uses: Alfresco/ya-pmd-scan@v4.0.0
with:
classpath-build-command: "mvn test-compile -ntp -Pags -pl \"-:alfresco-community-repo-docker\""
@@ -168,44 +176,52 @@ jobs:
testAttributes: "-Dtest=AllMmtUnitTestSuite"
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Prepare Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v7.0.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} - ${{ matrix.testModule }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
rp-project: ${{ env.RP_PROJECT }}
rp-use-static-launch-name: true
continue-on-error: true
- name: "Add GitHub Step Summary"
if: github.ref_name == 'master'
env:
RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }}
RP_KEY: ${{ steps.rp-prepare.outputs.key }}
RP_URL: ${{ steps.rp-prepare.outputs.url }}
run: bash scripts/ci/add_step_summary.sh
continue-on-error: true
- name: "Run tests"
id: run-tests
env:
RP_OPTS: ${{ steps.rp-prepare.outputs.mvn-opts }}
RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }}
run: |
eval "args=($RP_OPTS)"
mvn -B test -pl ${{ matrix.testModule }} -am ${{ matrix.testAttributes }} -DfailIfNoTests=false "${args[@]}"
continue-on-error: true
- name: "Update GitHub Step Summary"
if: github.ref_name == 'master'
run: |
echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY
continue-on-error: true
- name: "Summarize Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v7.0.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
rp-launch-key: ${{ steps.rp-prepare.outputs.key }}
rp-project: ${{ env.RP_PROJECT }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
continue-on-error: true
- name: "Exit on failure"
if: steps.run-tests.outcome != 'success'
run: |
@@ -240,9 +256,9 @@ jobs:
REQUIRES_INSTALLED_ARTIFACTS: true
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Build"
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
run: |
@@ -253,38 +269,46 @@ jobs:
- name: "Set up the environment"
run: docker compose -f ./scripts/ci/docker-compose/docker-compose.yaml --profile ${{ matrix.compose-profile }} up -d
- name: "Prepare Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v7.0.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} - ${{ matrix.testSuite }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
rp-project: ${{ env.RP_PROJECT }}
rp-use-static-launch-name: true
continue-on-error: true
- name: "Add GitHub Step Summary"
if: github.ref_name == 'master'
env:
RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }}
RP_KEY: ${{ steps.rp-prepare.outputs.key }}
RP_URL: ${{ steps.rp-prepare.outputs.url }}
run: bash scripts/ci/add_step_summary.sh
continue-on-error: true
- name: "Run tests"
id: run-tests
env:
RP_OPTS: ${{ steps.rp-prepare.outputs.mvn-opts }}
RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }}
run: |
eval "args=($RP_OPTS)"
eval "args=($RP_OPTS)"
mvn -B test -pl remote-api -Dtest=${{ matrix.testSuite }} -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco "${args[@]}"
continue-on-error: true
- name: "Update GitHub Step Summary"
if: github.ref_name == 'master'
run: |
echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY
continue-on-error: true
- name: "Summarize Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v7.0.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
rp-launch-key: ${{ steps.rp-prepare.outputs.key }}
rp-project: ${{ env.RP_PROJECT }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
continue-on-error: true
- name: "Exit on failure"
if: steps.run-tests.outcome != 'success'
run: |
@@ -310,9 +334,9 @@ jobs:
version: ['10.2.18', '10.4', '10.5']
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: Run MariaDB ${{ matrix.version }} database
@@ -320,38 +344,46 @@ jobs:
env:
MARIADB_VERSION: ${{ matrix.version }}
- name: "Prepare Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v7.0.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} - ${{ matrix.version }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
rp-project: ${{ env.RP_PROJECT }}
rp-use-static-launch-name: true
continue-on-error: true
- name: "Add GitHub Step Summary"
if: github.ref_name == 'master'
env:
RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }}
RP_KEY: ${{ steps.rp-prepare.outputs.key }}
RP_URL: ${{ steps.rp-prepare.outputs.url }}
run: bash scripts/ci/add_step_summary.sh
continue-on-error: true
- name: "Run tests"
id: run-tests
env:
RP_OPTS: ${{ steps.rp-prepare.outputs.mvn-opts }}
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.name=alfresco -Ddb.url=jdbc:mariadb://localhost:3307/alfresco?useUnicode=yes\&characterEncoding=UTF-8 -Ddb.username=alfresco -Ddb.password=alfresco -Ddb.driver=org.mariadb.jdbc.Driver "${args[@]}"
continue-on-error: true
- name: "Update GitHub Step Summary"
if: github.ref_name == 'master'
run: |
echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY
continue-on-error: true
- name: "Summarize Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v7.0.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
rp-launch-key: ${{ steps.rp-prepare.outputs.key }}
rp-project: ${{ env.RP_PROJECT }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
continue-on-error: true
- name: "Exit on failure"
if: steps.run-tests.outcome != 'success'
run: |
@@ -373,9 +405,9 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Run MariaDB 10.6 database"
@@ -383,38 +415,46 @@ jobs:
env:
MARIADB_VERSION: 10.6
- name: "Prepare Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v7.0.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
rp-project: ${{ env.RP_PROJECT }}
rp-use-static-launch-name: true
continue-on-error: true
- name: "Add GitHub Step Summary"
if: github.ref_name == 'master'
env:
RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }}
RP_KEY: ${{ steps.rp-prepare.outputs.key }}
RP_URL: ${{ steps.rp-prepare.outputs.url }}
run: bash scripts/ci/add_step_summary.sh
continue-on-error: true
- name: "Run tests"
id: run-tests
env:
RP_OPTS: ${{ steps.rp-prepare.outputs.mvn-opts }}
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.name=alfresco -Ddb.url=jdbc:mariadb://localhost:3307/alfresco?useUnicode=yes\&characterEncoding=UTF-8 -Ddb.username=alfresco -Ddb.password=alfresco -Ddb.driver=org.mariadb.jdbc.Driver "${args[@]}"
continue-on-error: true
- name: "Update GitHub Step Summary"
if: github.ref_name == 'master'
run: |
echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY
continue-on-error: true
- name: "Summarize Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v7.0.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
rp-launch-key: ${{ steps.rp-prepare.outputs.key }}
rp-project: ${{ env.RP_PROJECT }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
continue-on-error: true
- name: "Exit on failure"
if: steps.run-tests.outcome != 'success'
run: |
@@ -436,9 +476,9 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Run MySQL 8 database"
@@ -446,38 +486,46 @@ jobs:
env:
MYSQL_VERSION: 8
- name: "Prepare Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v7.0.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
rp-project: ${{ env.RP_PROJECT }}
rp-use-static-launch-name: true
continue-on-error: true
- name: "Add GitHub Step Summary"
if: github.ref_name == 'master'
env:
RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }}
RP_KEY: ${{ steps.rp-prepare.outputs.key }}
RP_URL: ${{ steps.rp-prepare.outputs.url }}
run: bash scripts/ci/add_step_summary.sh
continue-on-error: true
- name: "Run tests"
id: run-tests
env:
RP_OPTS: ${{ steps.rp-prepare.outputs.mvn-opts }}
RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }}
run: |
eval "args=($RP_OPTS)"
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[@]}"
continue-on-error: true
- name: "Update GitHub Step Summary"
if: github.ref_name == 'master'
run: |
echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY
continue-on-error: true
- name: "Summarize Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v7.0.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
rp-launch-key: ${{ steps.rp-prepare.outputs.key }}
rp-project: ${{ env.RP_PROJECT }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
continue-on-error: true
- name: "Exit on failure"
if: steps.run-tests.outcome != 'success'
run: |
@@ -498,9 +546,9 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Run PostgreSQL 13.12 database"
@@ -508,38 +556,46 @@ jobs:
env:
POSTGRES_VERSION: 13.12
- name: "Prepare Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v7.0.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
rp-project: ${{ env.RP_PROJECT }}
rp-use-static-launch-name: true
continue-on-error: true
- name: "Add GitHub Step Summary"
if: github.ref_name == 'master'
env:
RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }}
RP_KEY: ${{ steps.rp-prepare.outputs.key }}
RP_URL: ${{ steps.rp-prepare.outputs.url }}
run: bash scripts/ci/add_step_summary.sh
continue-on-error: true
- name: "Run tests"
id: run-tests
env:
RP_OPTS: ${{ steps.rp-prepare.outputs.mvn-opts }}
RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }}
run: |
eval "args=($RP_OPTS)"
eval "args=($RP_OPTS)"
mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco "${args[@]}"
continue-on-error: true
- name: "Update GitHub Step Summary"
if: github.ref_name == 'master'
run: |
echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY
continue-on-error: true
- name: "Summarize Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v7.0.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
rp-launch-key: ${{ steps.rp-prepare.outputs.key }}
rp-project: ${{ env.RP_PROJECT }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
continue-on-error: true
- name: "Exit on failure"
if: steps.run-tests.outcome != 'success'
run: |
@@ -560,9 +616,9 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Run PostgreSQL 14.9 database"
@@ -570,38 +626,46 @@ jobs:
env:
POSTGRES_VERSION: 14.9
- name: "Prepare Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v7.0.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
rp-project: ${{ env.RP_PROJECT }}
rp-use-static-launch-name: true
continue-on-error: true
- name: "Add GitHub Step Summary"
if: github.ref_name == 'master'
env:
RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }}
RP_KEY: ${{ steps.rp-prepare.outputs.key }}
RP_URL: ${{ steps.rp-prepare.outputs.url }}
run: bash scripts/ci/add_step_summary.sh
continue-on-error: true
- name: "Run tests"
id: run-tests
env:
RP_OPTS: ${{ steps.rp-prepare.outputs.mvn-opts }}
RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }}
run: |
eval "args=($RP_OPTS)"
eval "args=($RP_OPTS)"
mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco "${args[@]}"
continue-on-error: true
- name: "Update GitHub Step Summary"
if: github.ref_name == 'master'
run: |
echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY
continue-on-error: true
- name: "Summarize Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v7.0.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
rp-launch-key: ${{ steps.rp-prepare.outputs.key }}
rp-project: ${{ env.RP_PROJECT }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
continue-on-error: true
- name: "Exit on failure"
if: steps.run-tests.outcome != 'success'
run: |
@@ -622,9 +686,9 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Run PostgreSQL 15.4 database"
@@ -632,38 +696,46 @@ jobs:
env:
POSTGRES_VERSION: 15.4
- name: "Prepare Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v7.0.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
rp-project: ${{ env.RP_PROJECT }}
rp-use-static-launch-name: true
continue-on-error: true
- name: "Add GitHub Step Summary"
if: github.ref_name == 'master'
env:
RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }}
RP_KEY: ${{ steps.rp-prepare.outputs.key }}
RP_URL: ${{ steps.rp-prepare.outputs.url }}
run: bash scripts/ci/add_step_summary.sh
continue-on-error: true
- name: "Run tests"
id: run-tests
env:
RP_OPTS: ${{ steps.rp-prepare.outputs.mvn-opts }}
RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }}
run: |
eval "args=($RP_OPTS)"
eval "args=($RP_OPTS)"
mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco "${args[@]}"
continue-on-error: true
- name: "Update GitHub Step Summary"
if: github.ref_name == 'master'
run: |
echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY
continue-on-error: true
- name: "Summarize Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v7.0.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
rp-launch-key: ${{ steps.rp-prepare.outputs.key }}
rp-project: ${{ env.RP_PROJECT }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
continue-on-error: true
- name: "Exit on failure"
if: steps.run-tests.outcome != 'success'
run: |
@@ -682,46 +754,54 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.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"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v5.13.1
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v7.0.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
rp-project: ${{ env.RP_PROJECT }}
rp-use-static-launch-name: true
continue-on-error: true
- name: "Add GitHub Step Summary"
if: github.ref_name == 'master'
env:
RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }}
RP_KEY: ${{ steps.rp-prepare.outputs.key }}
RP_URL: ${{ steps.rp-prepare.outputs.url }}
run: bash scripts/ci/add_step_summary.sh
continue-on-error: true
- name: "Run tests"
id: run-tests
env:
RP_OPTS: ${{ steps.rp-prepare.outputs.mvn-opts }}
RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }}
run: |
eval "args=($RP_OPTS)"
mvn -B test -pl repository -am -Dtest=MessagingUnitTestSuite -DfailIfNoTests=false "${args[@]}"
continue-on-error: true
- name: "Update GitHub Step Summary"
if: github.ref_name == 'master'
run: |
echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY
continue-on-error: true
- name: "Summarize Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v5.13.1
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v7.0.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
rp-launch-key: ${{ steps.rp-prepare.outputs.key }}
rp-project: ${{ env.RP_PROJECT }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
continue-on-error: true
- name: "Exit on failure"
if: steps.run-tests.outcome != 'success'
run: |
@@ -774,9 +854,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@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Set transformers tag"
@@ -797,38 +877,46 @@ jobs:
- name: "Set up the environment"
run: docker compose -f ./scripts/ci/docker-compose/docker-compose.yaml --profile ${{ matrix.compose-profile }} up -d
- name: "Prepare Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v7.0.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} - ${{ matrix.testSuite }} ${{ matrix.idp }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
rp-project: ${{ env.RP_PROJECT }}
rp-use-static-launch-name: true
continue-on-error: true
- name: "Add GitHub Step Summary"
if: github.ref_name == 'master'
env:
RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }}
RP_KEY: ${{ steps.rp-prepare.outputs.key }}
RP_URL: ${{ steps.rp-prepare.outputs.url }}
run: bash scripts/ci/add_step_summary.sh
continue-on-error: true
- name: "Run tests"
id: run-tests
env:
RP_OPTS: ${{ steps.rp-prepare.outputs.mvn-opts }}
RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }}
run: |
eval "args=($RP_OPTS)"
mvn -B test -pl repository -am -Dtest=${{ matrix.testSuite }} -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco ${{ matrix.mvn-options }} "${args[@]}"
continue-on-error: true
- name: "Update GitHub Step Summary"
if: github.ref_name == 'master'
run: |
echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY
continue-on-error: true
- name: "Summarize Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v7.0.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
rp-launch-key: ${{ steps.rp-prepare.outputs.key }}
rp-project: ${{ env.RP_PROJECT }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
continue-on-error: true
- name: "Exit on failure"
if: steps.run-tests.outcome != 'success'
run: |
@@ -879,9 +967,9 @@ jobs:
REQUIRES_LOCAL_IMAGES: true
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Build"
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
run: |
@@ -895,23 +983,27 @@ jobs:
if: ${{ matrix.test-name }} == 'Integration TAS tests'
run: mvn install -pl :alfresco-community-repo-integration-test -am -DskipTests -Pall-tas-tests
- name: "Prepare Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v7.0.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} - ${{ matrix.test-name }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
rp-project: ${{ env.RP_PROJECT }}
rp-use-static-launch-name: true
continue-on-error: true
- name: "Add GitHub Step Summary"
if: github.ref_name == 'master'
env:
RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }}
RP_KEY: ${{ steps.rp-prepare.outputs.key }}
RP_URL: ${{ steps.rp-prepare.outputs.url }}
run: bash scripts/ci/add_step_summary.sh
continue-on-error: true
- name: "Run tests"
id: tests
env:
RP_OPTS: ${{ steps.rp-prepare.outputs.mvn-opts }}
RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }}
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
run: |
eval "args=($RP_OPTS)"
@@ -924,16 +1016,20 @@ jobs:
if: ${{ always() && steps.tests.outcome == 'failure' }}
run: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/${{ matrix.pom-dir }}"
- name: "Update GitHub Step Summary"
if: github.ref_name == 'master'
run: |
echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY
continue-on-error: true
- name: "Summarize Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v7.0.0
id: rp-summarize
with:
tests-outcome: ${{ steps.tests.outcome }}
rp-launch-key: ${{ steps.rp-prepare.outputs.key }}
rp-project: ${{ env.RP_PROJECT }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
continue-on-error: true
- name: "Exit on failure"
if: steps.tests.outcome != 'success'
run: |
@@ -952,46 +1048,54 @@ jobs:
!contains(github.event.head_commit.message, '[force')
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- name: "Run Postgres 15.4 database"
run: docker compose -f ./scripts/ci/docker-compose/docker-compose.yaml --profile postgres up -d
- name: "Prepare Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v7.0.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
rp-project: ${{ env.RP_PROJECT }}
rp-use-static-launch-name: true
continue-on-error: true
- name: "Add GitHub Step Summary"
if: github.ref_name == 'master'
env:
RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }}
RP_KEY: ${{ steps.rp-prepare.outputs.key }}
RP_URL: ${{ steps.rp-prepare.outputs.url }}
run: bash scripts/ci/add_step_summary.sh
continue-on-error: true
- name: "Run tests"
id: run-tests
env:
RP_OPTS: ${{ steps.rp-prepare.outputs.mvn-opts }}
RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }}
run: |
eval "args=($RP_OPTS)"
mvn -B test -pl :alfresco-share-services -am -Dtest=ShareServicesTestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco "${args[@]}"
continue-on-error: true
- name: "Update GitHub Step Summary"
if: github.ref_name == 'master'
run: |
echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY
continue-on-error: true
- name: "Summarize Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v7.0.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
rp-launch-key: ${{ steps.rp-prepare.outputs.key }}
rp-project: ${{ env.RP_PROJECT }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
continue-on-error: true
- name: "Exit on failure"
if: steps.run-tests.outcome != 'success'
run: |
@@ -1018,26 +1122,28 @@ jobs:
REQUIRES_INSTALLED_ARTIFACTS: true
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Build"
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
run: |
bash ./scripts/ci/init.sh
bash ./scripts/ci/build.sh
- name: "Prepare Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v7.0.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} 0${{ matrix.part }} - (PostgreSQL) ${{ matrix.test-name }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
rp-project: ${{ env.RP_PROJECT }}
rp-use-static-launch-name: true
continue-on-error: true
- name: "Verify"
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
env:
RP_OPTS: ${{ steps.rp-prepare.outputs.mvn-opts }}
RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }}
run: |
eval "args=($RP_OPTS)"
mvn --file amps/ags/pom.xml -B verify -Dmaven.javadoc.skip=true -Dmaven.source.skip=true -Pags -Pstart-postgres -PagsAllTestSuitePt${{ matrix.part }} ${{ env.LOG_WARN }} "${args[@]}"
@@ -1062,26 +1168,28 @@ jobs:
REQUIRES_INSTALLED_ARTIFACTS: true
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Build"
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
run: |
bash ./scripts/ci/init.sh
bash ./scripts/ci/build.sh
- name: "Prepare Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v7.0.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} 0${{ matrix.part }} - (MySQL) ${{ matrix.test-name }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
rp-project: ${{ env.RP_PROJECT }}
rp-use-static-launch-name: true
continue-on-error: true
- name: "Verify"
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
env:
RP_OPTS: ${{ steps.rp-prepare.outputs.mvn-opts }}
RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }}
run: |
eval "args=($RP_OPTS)"
mvn --file amps/ags/pom.xml -B verify -Dmaven.javadoc.skip=true -Dmaven.source.skip=true -Pags -Pstart-mysql -PagsAllTestSuitePt${{ matrix.part }} ${{ env.LOG_WARN }} "${args[@]}"
@@ -1102,9 +1210,9 @@ jobs:
REQUIRES_LOCAL_IMAGES: true
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Build"
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
run: |
@@ -1117,39 +1225,47 @@ jobs:
${{ env.TAS_SCRIPTS }}/wait-for-alfresco-start.sh "http://localhost:8080/alfresco"
mvn -B install -pl :alfresco-governance-services-automation-community-rest-api -am -Pags -Pall-tas-tests -DskipTests
- name: "Prepare Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v7.0.0
id: rp-prepare
with:
rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
rp-project: ${{ env.RP_PROJECT }}
rp-use-static-launch-name: true
continue-on-error: true
- name: "Add GitHub Step Summary"
if: github.ref_name == 'master'
env:
RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }}
RP_KEY: ${{ steps.rp-prepare.outputs.key }}
RP_URL: ${{ steps.rp-prepare.outputs.url }}
run: bash scripts/ci/add_step_summary.sh
continue-on-error: true
- name: "Test"
id: run-tests
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
env:
RP_OPTS: ${{ steps.rp-prepare.outputs.mvn-opts }}
RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }}
run: |
eval "args=($RP_OPTS)"
mvn -B test -pl :alfresco-governance-services-automation-community-rest-api -Dskip.automationtests=false -Pags -Pall-tas-tests "${args[@]}"
continue-on-error: true
- name: "Update GitHub Step Summary"
if: github.ref_name == 'master'
run: |
echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY
continue-on-error: true
- name: "Summarize Report Portal"
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v5.1.0
if: github.ref_name == 'master'
uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v7.0.0
id: rp-summarize
with:
tests-outcome: ${{ steps.run-tests.outcome }}
rp-launch-key: ${{ steps.rp-prepare.outputs.key }}
rp-project: ${{ env.RP_PROJECT }}
rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }}
continue-on-error: true
- name: "Exit on failure"
if: steps.run-tests.outcome != 'success'
run: |
@@ -1157,7 +1273,7 @@ jobs:
exit 1
- name: "Configure AWS credentials"
if: ${{ always() }}
uses: aws-actions/configure-aws-credentials@v1
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AGS_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AGS_AWS_SECRET_ACCESS_KEY }}
@@ -1184,9 +1300,9 @@ jobs:
!contains(github.event.head_commit.message, '[force]')
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Build"
timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }}
run: |

View File

@@ -34,12 +34,12 @@ jobs:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v7.0.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@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
- name: "Init"
run: bash ./scripts/ci/init.sh
- uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v1.35.2
- uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v7.0.0
with:
username: ${{ env.GIT_USERNAME }}
email: ${{ env.GIT_EMAIL }}

14
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,14 @@
repos:
- repo: https://github.com/Yelp/detect-secrets
rev: v1.5.0
hooks:
- id: detect-secrets
args: ["--baseline", ".secrets.baseline"]
- repo: local
hooks:
- id: check-format-and-headers
name: Check format and headers and fix if necessary
entry: ./scripts/hooks/check-format-and-headers.sh
language: script
files: ".*.java"
pass_filenames: false

1892
.secrets.baseline Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,52 @@ Thanks for your interest in contributing to this project!
The following is a set of guidelines for contributing to this library. Most of them will make the life of the reviewer easier and therefore decrease the time required for the patch be included in the next version.
The project uses [pre-commit](https://pre-commit.com/) to format code (with [Spotless](https://github.com/diffplug/spotless)), validate license headers and check for secrets (with [detect-secrets](https://github.com/Yelp/detect-secrets)). To install the pre-commit hooks then first install pre-commit and then run:
```shell
pre-commit install
```
When you make a commit then these hooks will run and check the modified files. If it makes changes then you can review them and then `git commit` again to accept the changes.
#### Code Quality
This project uses `spotless` that enforces `alfresco-formatter.xml` to ensure code quality.
To check code-style violations you can use:
```bash
mvn spotless:check
```
To reformat files you can use:
```bash
mvn spotless:apply
```
#### Secret Detection
We are using [detect-secrets](https://github.com/Yelp/detect-secrets) to try to avoid accidentally publishing secret keys.
If you have pre-commit installed then this should run automatically when making a commit. Usually there should be no issues,
but if it finds a potential issue (e.g. a high entropy string) then you will see the following:
```shell
Detect secrets...........................................................Failed
- hook id: detect-secrets
- exit code: 1
ERROR: Potential secrets about to be committed to git repo!
Secret Type: Secret Keyword
Location: test.txt:1
```
If this is a false positive and you actually want to commit the string then run these two commands:
```shell
detect-secrets scan --baseline .secrets.baseline
detect-secrets audit .secrets.baseline
```
This will update the baseline file to include your new code and then allow you to review the detected secret and mark it as a false positive.
Once you are finished then you can add `.secrets.baseline` to the staged changes and you should be able to create a commit.
Because this project forms a part of Alfresco Content Services, the guidelines are hosted in the [Alfresco Social Community](https://hub.alfresco.com/t5/alfresco-content-services-ecm/ct-p/ECM-software) where they can be referenced from multiple projects.
You can report an issue in the ALF project of the [Alfresco issue tracker](http://issues.alfresco.com).

View File

@@ -2,38 +2,57 @@
[![Build Status](https://github.com/Alfresco/alfresco-community-repo/actions/workflows/master_release.yml/badge.svg?branch=master)](https://github.com/Alfresco/alfresco-community-repo/actions/workflows/master_release.yml)
#### Alfresco Core
## Table of Contents
1. [Content](#content)
2. [Artifacts](#artifacts)
3. [Setup](#setting-up-and-building-your-development-environment)
4. [Branches](#branches)
5. [Contributing](#contributing-guide)
6. [Helpful links](#helpful-links)
## Content
Alfresco Community Repository contains following libraries:
### Alfresco Core
Core is a library packaged as a jar file which contains the following:
Alfresco Core is a library packaged as a jar file which contains the following:
* Various helpers and utils
* Canned queries interface and supporting classes
* Generic encryption supporting classes
#### Alfresco Data Model
Data model is a library packaged as a jar file which contains the following:
### Alfresco Data Model
Data Model is a library packaged as a jar file which contains the following:
* Dictionary, Repository and Search Services interfaces
* Models for data types and Dictionary implementation
* Parsers
#### Alfresco Repository
### Alfresco Repository
Repository is a library packaged as a jar file which contains the following:
* DAOs and SQL scripts
* Various Service implementations
* Utility classes
#### Alfresco Remote API
### Alfresco Remote API
Remote API is a library packaged as a jar file which contains the following:
* REST API framework
* WebScript implementations including [V1 REST APIs](https://hub.alfresco.com/t5/alfresco-content-services-blog/v1-rest-api-10-things-you-should-know/ba-p/287692)
* [OpenCMIS](https://chemistry.apache.org/java/opencmis.html) implementations
#### Artifacts
## Artifacts
The artifacts can be obtained by:
* downloading from [Alfresco maven repository](https://artifacts.alfresco.com/nexus/content/groups/public)
* downloading from [Alfresco maven repository](https://artifacts.alfresco.com/nexus/#browse/browse:public)
* as Maven dependency by adding the dependency to your pom file:
~~~
~~~xml
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-core</artifactId>
@@ -64,34 +83,46 @@ The artifacts can be obtained by:
<version>version</version>
<type>war</type>
</dependency>
~~~
and Alfresco maven repository:
~~~
~~~xml
<repository>
<id>alfresco-maven-repo</id>
<url>https://artifacts.alfresco.com/nexus/content/groups/public</url>
</repository>
~~~
The SNAPSHOT versions of the artifact are not published.
## Setting up and building your development environment
See the [Development Tomcat Environment](https://github.com/Alfresco/acs-community-packaging/tree/master/dev/README.md)
page which will show you how to try out your repository changes in a local tomcat instance.
If you wish to use Docker images, take a look at the aliases ending in `D` and the docker-compose files in this
project's test modules.
See the [**Development Tomcat Environment**](https://github.com/Alfresco/acs-community-packaging/tree/master/dev/README.md)
page which will show you how to try out your repository changes in a local Tomcat instance or using Docker containers.
## Branches
This project has a branch for each ACS release. For example the code in ACS 6.2.1 is a
branch called `releases/6.2.2`. In addition to the original 6.2.2 release it will also contain Hot Fixes
added later. The latest unreleased code is on the `master` branch. There are also `.N` branches, such as
`releases/7.1.N` on which we gather unreleased fixes for future service pack releases. They do not indicate
This project has a branch for each ACS release. For example the code in ACS 6.2.2 is a
branch called **`release/6.2.2`**. In addition to the original 6.2.2 release it will also contain Hot Fixes
added later. The latest unreleased code is on the **`master`** branch. There are also **`.N`** branches, such as
**`release/7.1.N`** on which we gather unreleased fixes for future service pack releases. They do not indicate
that one is planned.
For historic reasons the version of artifacts created on each branch do not match the ACS version.
For example artifact in ACS 7.2.0 will be `14.<something>`.
For example artifact in ACS 7.2.0 will be **`14.<something>`**.
The enterprise projects which extend the `alfresco-community-repo` use the same branch names and leading
The enterprise projects which extend the **`alfresco-community-repo`** use the same branch names and leading
artifact version number.
### Contributing guide
Please use [this guide](CONTRIBUTING.md) to make a contribution to the project.
## Contributing guide
Please use [**this guide**](CONTRIBUTING.md) to make a contribution to the project.
## Helpful links
- [Alfresco Content Services Documentation](https://docs.alfresco.com/content-services/latest/)
- [Alfresco Platform](https://www.hyland.com/en/products/alfresco-platform)

401
alfresco-formatter.xml Normal file
View File

@@ -0,0 +1,401 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="23">
<profile kind="CodeFormatterProfile" name="Spotless" version="23">
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_switch_case_arrow_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_permitted_types" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_permitted_types_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.javadoc_do_not_separate_block_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.keep_switch_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_arrow" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="999"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_switch_case_with_arrow_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_colon" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_switch_case_with_arrow" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_permitted_types" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="999"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
</profile>
</profiles>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-amps</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<modules>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<modules>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<build>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<modules>

View File

@@ -125,7 +125,7 @@
parent="declarativeCapability">
<property name="name" value="DeleteRecordFolder"/>
<property name="private" value="true"/>
<property name="permission" value="CreateModifyDestroyFolders"/>
<property name="permission" value="DeleteRecords"/>
<property name="kinds">
<list>
<value>RECORD_FOLDER</value>

View File

@@ -8,7 +8,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<properties>

View File

@@ -92,7 +92,7 @@ public class SearchTypesFactory
boolean includeRecords = false;
boolean includeSubTypes = false;
if (q != null)
if (q != null && q.getTree() != null)
{
// filtering via "where" clause
MapBasedQueryWalker propertyWalker = new MapBasedQueryWalker(listFolderChildrenEqualsQueryProperties, null);
@@ -101,11 +101,11 @@ public class SearchTypesFactory
Boolean isUnfiledRecordFolder = propertyWalker.getProperty(UnfiledChild.PARAM_IS_UNFILED_RECORD_FOLDER,
WhereClauseParser.EQUALS, Boolean.class);
Boolean isRecord = propertyWalker.getProperty(UnfiledChild.PARAM_IS_RECORD, WhereClauseParser.EQUALS, Boolean.class);
if ((isUnfiledRecordFolder != null && isUnfiledRecordFolder.booleanValue()) || (isRecord != null && !isRecord.booleanValue()))
if (checkIncludeUnfiledRecordFolders(isUnfiledRecordFolder, isRecord))
{
includeUnfiledRecordFolders = true;
}
else if ((isUnfiledRecordFolder != null && !isUnfiledRecordFolder.booleanValue()) || (isRecord != null && isRecord.booleanValue()))
else if (checkIncludeRecords(isUnfiledRecordFolder, isRecord))
{
includeRecords = true;
}
@@ -199,11 +199,11 @@ public class SearchTypesFactory
WhereClauseParser.EQUALS, Boolean.class);
Boolean isRecordCategory = propertyWalker.getProperty(RecordCategoryChild.PARAM_IS_RECORD_CATEGORY, WhereClauseParser.EQUALS, Boolean.class);
if ((isRecordFolder != null && isRecordFolder.booleanValue()) || (isRecordCategory != null && !isRecordCategory.booleanValue()))
if (checkIncludeUnfiledRecordFolders(isRecordFolder, isRecordCategory))
{
includeRecordFolders = true;
}
else if ((isRecordFolder != null && !isRecordFolder.booleanValue()) || (isRecordCategory != null && isRecordCategory.booleanValue()))
else if (checkIncludeRecords(isRecordFolder, isRecordCategory))
{
includeRecordCategories = true;
}
@@ -291,4 +291,16 @@ public class SearchTypesFactory
return new Pair<>(filterNodeTypeQName, filterIncludeSubTypes);
}
private static boolean checkIncludeRecords(Boolean isUnfiledRecordFolder, Boolean isRecord)
{
return (isUnfiledRecordFolder != null && !isUnfiledRecordFolder.booleanValue()) || (isRecord != null
&& isRecord.booleanValue());
}
private static boolean checkIncludeUnfiledRecordFolders(Boolean isUnfiledRecordFolder, Boolean isRecord)
{
return (isUnfiledRecordFolder != null && isUnfiledRecordFolder.booleanValue()) || (isRecord != null
&& !isRecord.booleanValue());
}
}

View File

@@ -5,7 +5,7 @@
# Version label
version.major=23
version.minor=3
version.revision=0
version.revision=1
version.label=
# Edition label

View File

@@ -33,14 +33,15 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO;
import org.alfresco.repo.domain.propval.PropertyStringValueEntity;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO;
import org.alfresco.repo.domain.propval.PropertyStringValueEntity;
/**
* RM V3.3 Hold audit entries values patch unit test
*
@@ -55,7 +56,6 @@ public class RMv33HoldAuditEntryValuesPatchUnitTest
@InjectMocks
private RMv33HoldAuditEntryValuesPatch patch;
@Before
public void setUp()
{
@@ -89,6 +89,7 @@ public class RMv33HoldAuditEntryValuesPatchUnitTest
verify(mockedRecordsManagementQueryDAO, times(1)).updatePropertyStringValueEntity(addToHoldPropertyStringValueEntity);
verify(mockedRecordsManagementQueryDAO, times(1)).getPropertyStringValueEntity("removeFromHold");
verify(mockedRecordsManagementQueryDAO, times(1)).updatePropertyStringValueEntity(removeFromHoldPropertyStringValueEntity);
verify(mockedRecordsManagementQueryDAO, times(1)).getPropertyStringValueEntity("deleteHold");
verify(mockedRecordsManagementQueryDAO, times(1)).updatePropertyStringValueEntity(deleteHoldPropertyStringValueEntity);
@@ -123,5 +124,3 @@ public class RMv33HoldAuditEntryValuesPatchUnitTest
verify(mockedRecordsManagementQueryDAO, times(0)).updatePropertyStringValueEntity(any());
}
}

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<build>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<modules>

View File

@@ -8,7 +8,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-amps</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<properties>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<dependencies>
@@ -47,11 +47,11 @@
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.uuid/java-uuid-generator -->
<dependency>
<groupId>org.safehaus.jug</groupId>
<artifactId>jug</artifactId>
<version>2.0.0</version>
<classifier>asl</classifier>
<groupId>com.fasterxml.uuid</groupId>
<artifactId>java-uuid-generator</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>

View File

@@ -21,7 +21,7 @@ package org.alfresco.util;
import java.security.SecureRandom;
import java.util.Random;
import org.safehaus.uuid.UUIDGenerator;
import com.fasterxml.uuid.Generators;
import org.alfresco.api.AlfrescoPublicApi;
/**
@@ -69,7 +69,7 @@ public final class GUID
public static String generate()
{
int randomInt = RANDOM.nextInt(SECURE_RANDOM_POOL_MAX_ITEMS);
return UUIDGenerator.getInstance().generateRandomBasedUUID(SECURE_RANDOM_POOL[randomInt]).toString();
return Generators.randomBasedGenerator(SECURE_RANDOM_POOL[randomInt]).generate().toString();
}
// == Not sure if we need this functionality again (derekh) ==

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<properties>

View File

@@ -33,13 +33,13 @@ import java.util.HashSet;
import java.util.Set;
import java.util.zip.CRC32;
import com.fasterxml.uuid.Generators;
import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.service.cmr.repository.datatype.Duration;
import org.alfresco.util.GUID;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.safehaus.uuid.UUIDGenerator;
import org.alfresco.util.ParameterCheck;
/**
@@ -497,7 +497,7 @@ public class InMemoryTicketComponentImpl implements TicketComponent
this.userName = userName;
this.validDuration = validDuration;
this.testDuration = validDuration.divide(2);
final String guid = UUIDGenerator.getInstance().generateRandomBasedUUID().toString();
final String guid = Generators.randomBasedGenerator().generate().toString();
this.ticketId = computeTicketId(expires, expiryDate, userName, guid);

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<dependencies>
@@ -84,7 +84,7 @@
<include>org.alfresco:alfresco-core</include>
<include>org.alfresco:alfresco-repository</include>
<include>org.apache.commons:commons-compress</include>
<include>org.safehaus.jug:jug</include>
<include>com.fasterxml.uuid:java-uuid-generator</include>
<include>org.alfresco.surf:spring-surf-core</include>
<include>org.tukaani:xz</include>
<include>org.apache.maven:maven-artifact</include>

View File

@@ -25,6 +25,7 @@
*/
package org.alfresco.repo.module.tool;
import com.fasterxml.uuid.Generators;
import de.schlichtherle.truezip.file.*;
import de.schlichtherle.truezip.fs.FsSyncException;
import de.schlichtherle.truezip.fs.archive.zip.JarDriver;
@@ -34,7 +35,6 @@ import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.module.ModuleVersionNumber;
import org.alfresco.service.cmr.module.ModuleDetails;
import org.alfresco.service.cmr.module.ModuleInstallState;
import org.safehaus.uuid.UUIDGenerator;
import java.io.BufferedInputStream;
import java.io.IOException;
@@ -916,7 +916,7 @@ public class ModuleManagementTool implements LogOutput
*/
private static String generateGuid()
{
return UUIDGenerator.getInstance().generateTimeBasedUUID().toString();
return Generators.timeBasedGenerator().generate().toString();
}
/**

View File

@@ -9,6 +9,6 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
</project>

View File

@@ -1,6 +1,5 @@
# Fetch image based on Tomcat 9.0, Java 17 and Rocky Linux 8
# More infos about this image: https://github.com/Alfresco/alfresco-docker-base-tomcat
FROM alfresco/alfresco-base-tomcat:tomcat10-jre17-rockylinux8-202306291245
FROM alfresco/alfresco-base-tomcat:tomcat10-jre17-rockylinux9@sha256:395664f9d9be0c9f73d3b722a58fd559ee7231609b263dfe19502617652740e3
# Set default docker_context.
ARG resource_path=target
@@ -14,6 +13,9 @@ ARG USERID=33000
# Set default environment args
ARG TOMCAT_DIR=/usr/local/tomcat
# Needed for installation but make sure another USER directive is added after
# this with a non-root user
USER root
# Create prerequisite to store tools and properties
RUN mkdir -p ${TOMCAT_DIR}/shared/classes/alfresco/extension/mimetypes && \
@@ -61,13 +63,7 @@ RUN sed -i -e "s_appender.rolling.fileName\=alfresco.log_appender.rolling.fileNa
sed -i -e "\$a\grant\ codeBase\ \"file:\$\{catalina.base\}\/webapps\/alfresco\/-\" \{\n\ permission\ java.security.AllPermission\;\n\};\ngrant\ codeBase\ \"file:\$\{catalina.base\}\/webapps\/_vti_bin\/-\" \{\n\ permission\ java.security.AllPermission\;\n\};\ngrant\ codeBase\ \"file:\$\{catalina.base\}\/webapps\/ROOT\/-\" \{\n\ permission org.apache.catalina.security.DeployXmlPermission \"ROOT\";\n\};" ${TOMCAT_DIR}/conf/catalina.policy
# fontconfig is required by Activiti worflow diagram generator
# installing pinned dependencies as well
RUN yum install -y fontconfig-2.13.1-4.el8 \
dejavu-fonts-common-2.35-7.el8 \
fontpackages-filesystem-1.44-22.el8 \
freetype-2.9.1-9.el8 \
libpng-1.6.34-5.el8 \
dejavu-sans-fonts-2.35-7.el8 && \
RUN yum install -y fontconfig-2.14.0-2.el9_1 && \
yum clean all
# The standard configuration is to have all Tomcat files owned by root with group GROUPNAME and whilst owner has read/write privileges,

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<properties>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<modules>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<modules>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<organization>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<developers>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<developers>

View File

@@ -8,7 +8,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<properties>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<developers>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<properties>
@@ -110,6 +110,11 @@
<artifactId>mysql-connector-java</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.owasp.encoder</groupId>
<artifactId>encoder</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
<build>

View File

@@ -34,6 +34,7 @@
<%@ page import="org.alfresco.service.cmr.module.ModuleDetails" %>
<%@ page import="org.alfresco.service.cmr.module.ModuleInstallState" %>
<%@ page import="java.util.Calendar" %>
<%@ page import="org.owasp.encoder.Encode" %>
<!-- Enterprise index-jsp placeholder -->
<%
@@ -88,7 +89,7 @@ ModuleDetails shareServicesModule = moduleService.getModule("alfresco-share-serv
<p></p>
<p><a href="./s/index">Alfresco WebScripts Home</a> (admin only - INTERNAL)</p>
<p></p>
<p><a href="<%=UrlUtil.getApiExplorerUrl(sysAdminParams, request.getRequestURL().toString(), request.getRequestURI())%>">Alfresco API Explorer</a></p>
<p><a href="<%=Encode.forHtmlAttribute(UrlUtil.getApiExplorerUrl(sysAdminParams, request.getRequestURL().toString(), request.getRequestURI()))%>">Alfresco API Explorer</a></p>
<%
if (descriptorService.getLicenseDescriptor() == null && transactionService.isReadOnly())
{

49
pom.xml
View File

@@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>alfresco-community-repo</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Alfresco Community Repo Parent</name>
@@ -25,7 +25,7 @@
<properties>
<acs.version.major>23</acs.version.major>
<acs.version.minor>3</acs.version.minor>
<acs.version.revision>0</acs.version.revision>
<acs.version.revision>1</acs.version.revision>
<acs.version.label />
<amp.min.version>${acs.version.major}.0.0</amp.min.version>
@@ -51,8 +51,8 @@
<dependency.alfresco-server-root.version>7.0.1</dependency.alfresco-server-root.version>
<dependency.activiti-engine.version>5.23.0</dependency.activiti-engine.version>
<dependency.activiti.version>5.23.0</dependency.activiti.version>
<dependency.alfresco-transform-core.version>5.1.3</dependency.alfresco-transform-core.version>
<dependency.alfresco-transform-service.version>4.1.3</dependency.alfresco-transform-service.version>
<dependency.alfresco-transform-core.version>5.1.4</dependency.alfresco-transform-core.version>
<dependency.alfresco-transform-service.version>4.1.4</dependency.alfresco-transform-service.version>
<dependency.alfresco-greenmail.version>7.0</dependency.alfresco-greenmail.version>
<dependency.acs-event-model.version>0.0.27</dependency.acs-event-model.version>
@@ -61,9 +61,9 @@
<dependency.spring-security.version>6.3.1</dependency.spring-security.version>
<dependency.antlr.version>3.5.3</dependency.antlr.version>
<dependency.jackson.version>2.15.2</dependency.jackson.version>
<dependency.cxf.version>4.0.4</dependency.cxf.version>
<dependency.cxf.version>4.0.5</dependency.cxf.version>
<dependency.opencmis.version>1.0.0-jakarta-1</dependency.opencmis.version>
<dependency.webscripts.version>9.0</dependency.webscripts.version>
<dependency.webscripts.version>9.3</dependency.webscripts.version>
<dependency.bouncycastle.version>1.78.1</dependency.bouncycastle.version>
<dependency.mockito-core.version>5.12.0</dependency.mockito-core.version>
<dependency.assertj.version>3.26.3</dependency.assertj.version>
@@ -113,13 +113,16 @@
<dependency.jakarta-json-path.version>2.9.0</dependency.jakarta-json-path.version>
<dependency.json-smart.version>2.5.1</dependency.json-smart.version>
<alfresco.googledrive.version>4.1.0</alfresco.googledrive.version>
<alfresco.aos-module.version>3.1.0-A1</alfresco.aos-module.version>
<alfresco.api-explorer.version>23.2.0</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
<alfresco.aos-module.version>3.1.0</alfresco.aos-module.version>
<alfresco.api-explorer.version>23.3.0</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
<alfresco.maven-plugin.version>2.2.0</alfresco.maven-plugin.version>
<license-maven-plugin.version>2.0.1</license-maven-plugin.version>
<spotless-plugin.version>2.43.0</spotless-plugin.version>
<!-- Do not match any files by default, but this can be overridden from the command line. -->
<spotless-include-list>NO_AUTOMATED_FORMATTING</spotless-include-list>
<dependency.postgresql.version>42.6.0</dependency.postgresql.version>
<dependency.postgresql.version>42.7.3</dependency.postgresql.version>
<dependency.mysql.version>8.0.30</dependency.mysql.version>
<dependency.mysql-image.version>8</dependency.mysql-image.version>
<dependency.mariadb.version>2.7.4</dependency.mariadb.version>
@@ -151,7 +154,7 @@
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
<url>https://github.com/Alfresco/alfresco-community-repo</url>
<tag>23.3.0.73</tag>
<tag>HEAD</tag>
</scm>
<distributionManagement>
@@ -1004,7 +1007,7 @@
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.43.4</version>
<version>0.45.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
@@ -1146,6 +1149,26 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>${spotless-plugin.version}</version>
<configuration>
<java>
<includes>
${spotless-include-list}
</includes>
<eclipse>
<file>alfresco-formatter.xml</file>
</eclipse>
<importOrder>
<order>\#java|\#javax|\#jakarta,\#,\#org.alfresco,java|javax|jakarta,,org.alfresco</order>
</importOrder>
<removeUnusedImports />
<formatAnnotations />
</java>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
@@ -1157,6 +1180,10 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<dependencies>

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -85,7 +85,7 @@ public class AuditImpl implements Audit
// list of equals filter's auditEntry (via where clause)
private final static Set<String> LIST_AUDIT_ENTRY_EQUALS_QUERY_PROPERTIES = new HashSet<>(
Arrays.asList(new String[] { CREATED_BY_USER, VALUES_KEY, VALUES_VALUE }));
Arrays.asList(new String[]{CREATED_BY_USER, VALUES_KEY, VALUES_VALUE}));
// map of sort parameters for the moment one createdAt
private final static Map<String, String> SORT_PARAMS_TO_NAMES;
@@ -295,23 +295,29 @@ public class AuditImpl implements Audit
}
else
{
if (hasMoreItems) {
if (q != null) {
if (hasMoreItems)
{
if (q != null)
{
// filtering via "where" clause
AuditEntryQueryWalker propertyWalker = new AuditEntryQueryWalker();
QueryHelper.walk(q, propertyWalker);
totalItems = getAuditEntriesCountByAppAndProperties(auditApplication, propertyWalker);
} else {
}
else
{
totalItems = getAuditEntriesCountByApp(auditApplication);
}
} else {
}
else
{
totalItems = totalRetrievedItems;
}
}
entriesAudit = (skipCount >= totalRetrievedItems)
? Collections.emptyList()
: entriesAudit.subList(skipCount, end);
? Collections.emptyList()
: entriesAudit.subList(skipCount, end);
return CollectionWithPagingInfo.asPaged(paging, entriesAudit, hasMoreItems, totalItems);
}
@@ -475,8 +481,7 @@ public class AuditImpl implements Audit
final Map<String, UserInfo> mapUserInfo = new HashMap<>(10);
// create the callback for auditQuery method
final AuditQueryCallback callback = new AuditQueryCallback()
{
final AuditQueryCallback callback = new AuditQueryCallback() {
public boolean valuesRequired()
{
return ((includeParam != null) && (includeParam.contains(PARAM_INCLUDE_VALUES)));
@@ -532,7 +537,7 @@ public class AuditImpl implements Audit
params.setApplicationName(auditApplication.getName());
params.setFromId(auditEntryId);
params.setToId(auditEntryId + 1);
List<String> includeParam = new ArrayList<>();
if (parameters != null)
{
@@ -545,8 +550,7 @@ public class AuditImpl implements Audit
final List<AuditEntry> results = new ArrayList<>();
// create the callback for auditQuery method
final AuditQueryCallback callback = new AuditQueryCallback()
{
final AuditQueryCallback callback = new AuditQueryCallback() {
public boolean valuesRequired()
{
return ((includeParam != null) && (includeParam.contains(PARAM_INCLUDE_VALUES)));
@@ -710,8 +714,7 @@ public class AuditImpl implements Audit
@Override
public CollectionWithPagingInfo<AuditEntry> listAuditEntriesByNodeId(String nodeId, Parameters parameters)
{
AuthenticationUtil.runAs(new RunAsWork<Void>()
{
AuthenticationUtil.runAs(new RunAsWork<Void>() {
public Void doWork() throws Exception
{
checkEnabled();
@@ -772,8 +775,7 @@ public class AuditImpl implements Audit
final List<AuditEntry> results = new ArrayList<>();
String auditAppId = "alfresco-access";
String auditApplicationName = AuthenticationUtil.runAs(new RunAsWork<String>()
{
String auditApplicationName = AuthenticationUtil.runAs(new RunAsWork<String>() {
public String doWork() throws Exception
{
return findAuditAppByIdOr404(auditAppId).getName();
@@ -781,8 +783,7 @@ public class AuditImpl implements Audit
}, AuthenticationUtil.getSystemUserName());
// create the callback for auditQuery method
final AuditQueryCallback callback = new AuditQueryCallback()
{
final AuditQueryCallback callback = new AuditQueryCallback() {
public boolean valuesRequired()
{
return ((includeParam != null) && (includeParam.contains(PARAM_INCLUDE_VALUES)));
@@ -808,8 +809,7 @@ public class AuditImpl implements Audit
Long toTime = propertyWalker.getToTime();
validateWhereBetween(nodeRef.getId(), fromTime, toTime);
AuthenticationUtil.runAs(new RunAsWork<Object>()
{
AuthenticationUtil.runAs(new RunAsWork<Object>() {
public Object doWork() throws Exception
{
// QueryParameters
@@ -820,7 +820,7 @@ public class AuditImpl implements Audit
pathParams.setFromTime(fromTime);
pathParams.setToTime(toTime);
pathParams.setApplicationName(auditApplicationName);
pathParams.addSearchKey("/"+auditAppId+"/transaction/path", nodePath);
pathParams.addSearchKey("/" + auditAppId + "/transaction/path", nodePath);
auditService.auditQuery(callback, pathParams, limit);
AuditQueryParameters copyFromPathParams = new AuditQueryParameters();
@@ -830,7 +830,7 @@ public class AuditImpl implements Audit
copyFromPathParams.setFromTime(fromTime);
copyFromPathParams.setToTime(toTime);
copyFromPathParams.setApplicationName(auditApplicationName);
copyFromPathParams.addSearchKey("/"+auditAppId+"/transaction/copy/from/path", nodePath);
copyFromPathParams.addSearchKey("/" + auditAppId + "/transaction/copy/from/path", nodePath);
auditService.auditQuery(callback, copyFromPathParams, limit);
AuditQueryParameters moveFromPathParams = new AuditQueryParameters();
@@ -840,7 +840,7 @@ public class AuditImpl implements Audit
moveFromPathParams.setFromTime(fromTime);
moveFromPathParams.setToTime(toTime);
moveFromPathParams.setApplicationName(auditApplicationName);
moveFromPathParams.addSearchKey("/"+auditAppId+"/transaction/move/from/path", nodePath);
moveFromPathParams.addSearchKey("/" + auditAppId + "/transaction/move/from/path", nodePath);
auditService.auditQuery(callback, moveFromPathParams, limit);
return null;
@@ -857,7 +857,7 @@ public class AuditImpl implements Audit
public AuditEntriesByNodeIdQueryWalker()
{
super(new HashSet<>(Arrays.asList(new String[] { CREATED_BY_USER })), null);
super(new HashSet<>(Arrays.asList(new String[]{CREATED_BY_USER})), null);
}
@Override
@@ -910,13 +910,13 @@ public class AuditImpl implements Audit
public int getAuditEntriesCountByAppAndProperties(AuditService.AuditApplication auditApplication, AuditEntryQueryWalker propertyWalker)
{
final String applicationName = auditApplication.getKey().substring(1);
AuditQueryParameters parameters = new AuditQueryParameters();
parameters.setApplicationName(applicationName);
parameters.setFromTime(propertyWalker.getFromTime());
parameters.setToTime(propertyWalker.getToTime());
parameters.setFromId(propertyWalker.getFromId());
parameters.setToId(propertyWalker.getToId());
parameters.setUser(propertyWalker.getCreatedByUser());
return auditService.getAuditEntriesCountByAppAndProperties(applicationName, parameters);

View File

@@ -125,7 +125,7 @@ public class PeopleImpl implements People
protected ResetPasswordService resetPasswordService;
protected UserRegistrySynchronizer userRegistrySynchronizer;
protected Renditions renditions;
private Boolean allowImmutableEnabledUpdate;
private final static Map<String, QName> sort_params_to_qnames;
static
@@ -202,6 +202,11 @@ public class PeopleImpl implements People
this.userRegistrySynchronizer = userRegistrySynchronizer;
}
public void setAllowImmutableEnabledUpdate(Boolean allowImmutableEnabledUpdate)
{
this.allowImmutableEnabledUpdate = allowImmutableEnabledUpdate;
}
/**
* Validate, perform -me- substitution and canonicalize the person ID.
*
@@ -708,16 +713,26 @@ public class PeopleImpl implements People
// if requested, update password
updatePassword(isAdmin, personIdToUpdate, person);
if (person.isEnabled() != null)
Set<QName> immutableProperties = userRegistrySynchronizer.getPersonMappedProperties(personIdToUpdate);
Boolean isEnabled = person.isEnabled();
if (isEnabled != null)
{
if (isAdminAuthority(personIdToUpdate))
{
throw new PermissionDeniedException("Admin authority cannot be disabled.");
}
// note: if current user is not an admin then permission denied exception is thrown
MutableAuthenticationService mutableAuthenticationService = (MutableAuthenticationService) authenticationService;
mutableAuthenticationService.setAuthenticationEnabled(personIdToUpdate, person.isEnabled());
if (allowImmutableEnabledStatusUpdate(personIdToUpdate, isAdmin, immutableProperties))
{
LOGGER.info("User " + personIdToUpdate + " is immutable but enabled status will be set to: " + isEnabled);
}
else
{
// note: if current user is not an admin then permission denied exception is thrown
MutableAuthenticationService mutableAuthenticationService = (MutableAuthenticationService) authenticationService;
mutableAuthenticationService.setAuthenticationEnabled(personIdToUpdate, person.isEnabled());
}
}
NodeRef personNodeRef = personService.getPerson(personIdToUpdate, false);
@@ -742,9 +757,7 @@ public class PeopleImpl implements People
properties.putAll(nodes.mapToNodeProperties(customProps));
}
// MNT-21150 LDAP synced attributes can be changed using REST API
Set<QName> immutableProperties = userRegistrySynchronizer.getPersonMappedProperties(personIdToUpdate);
// MNT-21150 LDAP synced attributes can't be changed using REST API
immutableProperties.forEach(immutableProperty -> {
if (properties.containsKey(immutableProperty))
{
@@ -768,6 +781,28 @@ public class PeopleImpl implements People
return getPerson(personId);
}
private boolean allowImmutableEnabledStatusUpdate(String userId, boolean isAdmin, Set<QName> immutableProperties)
{
if (allowImmutableEnabledUpdate)
{
boolean containLdapUserAccountStatus = false;
QName propertyNameToCheck = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "userAccountStatusProperty");
for (QName immutableProperty : immutableProperties)
{
if (immutableProperty.equals(propertyNameToCheck))
{
containLdapUserAccountStatus = true;
break;
}
}
return isAdmin && !containLdapUserAccountStatus && !isMutableAuthority(userId);
}
return false;
}
private boolean checkCurrentUserOrAdmin(String personId)
{
boolean isAdmin = isAdminAuthority();

View File

@@ -764,6 +764,7 @@
<property name="thumbnailService" ref="ThumbnailService" />
<property name="resetPasswordService" ref="resetPasswordService" />
<property name="userRegistrySynchronizer" ref="userRegistrySynchronizer" />
<property name="allowImmutableEnabledUpdate" value="${allow.immutable.user.enabled.status.update}" />
</bean>
<bean id="People" class="org.springframework.aop.framework.ProxyFactoryBean">

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>23.3.0.73</version>
<version>23.3.1.5-SNAPSHOT</version>
</parent>
<dependencies>

View File

@@ -41,6 +41,8 @@ public class IdsEntity
private Long idFour;
private List<Long> ids;
private boolean ordered;
private Integer maxResults;
public Long getIdOne()
{
return idOne;
@@ -89,4 +91,12 @@ public class IdsEntity
{
this.ordered = ordered;
}
public int getMaxResults()
{
return maxResults;
}
public void setMaxResults(Integer maxResults)
{
this.maxResults = maxResults;
}
}

View File

@@ -1,287 +1,283 @@
/*
* #%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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.audit;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.audit.model.AuditApplication;
import org.alfresco.repo.audit.model.AuditModelRegistry;
import org.alfresco.repo.audit.model._3.AuditPath;
import org.alfresco.service.cmr.audit.AuditQueryParameters;
import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback;
/**
* The audit component. Used by the AuditService and AuditMethodInterceptor to insert audit entries.
*
* @author Derek Hulley
*/
public interface AuditComponent
{
/**
* Determines whether audit is globally enabled or disabled.
*
* @return Returns <code>true</code> if audit is enabled
*
* @since 3.3
*/
public boolean isAuditEnabled();
/**
* Switch auditing on or off
*
* @param enable <tt>true</tt> to enable auditing or <tt>false</tt> to disable
*
* @since 3.4
*/
public void setAuditEnabled(boolean enable);
/**
* @param userAuditFilter UserAuditFilter
*
* @since 4.2
*/
public void setUserAuditFilter(UserAuditFilter userAuditFilter);
/**
* Get all registered audit applications, whether active or not.
*
* @return Returns a map of registered audit applications keyed by name
*
* @since 3.4
*/
public Map<String, AuditApplication> getAuditApplications();
/**
* Determine whether the audit infrastructure expects audit values to be passed in.
* This is a helper method to allow optimizations in the client code. Reasons why
* this method might return <tt>false</tt> are: auditing is disabled; no audit applications
* have been registered. Sometimes, depending on the log level, this method may always
* return <tt>true</tt>.
*
*
* @return Returns <code>true</code> if the calling code (data producers)
* should go ahead and generate the data for
* {@link #recordAuditValues(String, Map) recording}.
*
* @since 3.3
*/
public boolean areAuditValuesRequired();
/**
* Determines if audit values are required based on whether there are any audit applications
* registered to record data for the given path. This helper method gives data producers a
* shortcut in the event that nothing would be recorded in any event.
*
* @param path the audit path
* @return Returns <tt>true</tt> if there is at least one audit application
* registered to handle the given path.
*
* @since 3.4
*/
public boolean areAuditValuesRequired(String path);
/**
* Delete audit entries for the given application and time range
*
* @param applicationName the name of the application
* @param fromTime the start time of entries to remove (inclusive and optional)
* @param toTime the end time of entries to remove (exclusive and optional)
* @return Returns the number of entries deleted
*
* @since 3.2
*/
int deleteAuditEntries(String applicationName, Long fromTime, Long toTime);
/**
* Delete audit entries for the given application and id range
*
* @param applicationName the name of the application
* @param fromId the start time of entries to remove (inclusive and optional)
* @param toId the end time of entries to remove (exclusive and optional)
* @return Returns the number of entries deleted
*
* @since 5.2.2
*/
int deleteAuditEntriesByIdRange(String applicationName, Long fromId, Long toId);
/**
* Delete a discrete list of audit entries based on ID
*
* @param auditEntryIds the audit entry IDs to delete
* @return Returns the number of entries deleted
*/
int deleteAuditEntries(List<Long> auditEntryIds);
/**
* Check if an audit path is enabled. The path will be disabled if it or any higher
* path has been explicitly disabled. Any disabled path will not be processed when
* data is audited.
*
* @param applicationName the name of the application being logged to
* @param path the audit path to check or <tt>null</tt> to assume the
* application's root path
* @return Returns <tt>true</tt> if the audit path has been disabled
*
* @since 3.2
*/
boolean isAuditPathEnabled(String applicationName, String path);
/**
* Enable auditing (if it is not already enabled) for all paths that contain the given path.
* The path is the path as originally logged and
* not the path that the generated data may contain - although this would be similarly
* enabled.
* <p>
* If the enabled
*
* @param applicationName the name of the application being logged to
* @param path the audit path to check or <tt>null</tt> to assume the
* application's root path
*
* @since 3.2
*/
void enableAudit(String applicationName, String path);
/**
* Disable auditing (if it is not already disabled) for all paths that contain the given path.
* The path is the path as originally logged and
* not the path that the generated data may contain - although this would be similarly
* disabled.
* <p>
* If the path is <b>/x/y</b> then any data paths that start with <b>/x/y</b> will be stripped
* out <u>before</u> data generators and data recorders are applied. If the path represents
* the root path of the application, then auditing for that application is effectively disabled.
*
* @param applicationName the name of the application being logged to
* @param path the audit path to check or <tt>null</tt> to assume the
* application's root path
*
* @since 3.2
*/
void disableAudit(String applicationName, String path);
/**
* Remove all disabled paths i.e. enable all per-path based auditing. Auditing may still be
* disabled globally. This is primarily for test purposes; applications should know which
* paths need {@link #enableAudit(String, String) enabling} or
* {@link #disableAudit(String, String) disabled}.
*
* @param applicationName the name of the application
*
* @since 3.2
*/
void resetDisabledPaths(String applicationName);
/**
* Create an audit entry for the given map of values. The map key is a path - starting with '/'
* ({@link AuditApplication#AUDIT_PATH_SEPARATOR}) - relative to the root path provided.
* <p/>
* The root path and value keys are combined to produce a map of data keyed by full path. This
* fully-pathed map is then passed through the
* {@link AuditModelRegistry#getAuditPathMapper() audit path mapper}. The result may yield data
* destined for several different
* {@link AuditModelRegistry#getAuditApplicationByKey(String) audit applications}. depending on
* the data extraction and generation defined in the applications, values (or derived values) may
* be recorded against several audit entries (one per application represented).
* <p/>
* The return values reflect what was actually persisted and is controlled by the data extractors
* defined in the audit configuration.
* <p/>
* A new read-write transaction is started if there are values to write that there is not a viable
* transaction present.
*
* @param rootPath a base path of {@link AuditPath} key entries concatenated with the path separator
* '/' ({@link AuditApplication#AUDIT_PATH_SEPARATOR})
* @param values the values to audit mapped by {@link AuditPath} key relative to root path
* (may be <tt>null</tt>)
* @return Returns the values that were actually persisted, keyed by their full path.
* @throws IllegalStateException if the transaction state could not be determined
*
* @since 3.2
*/
Map<String, Serializable> recordAuditValues(String rootPath, Map<String, Serializable> values);
/**
* The same as {@link AuditComponent#recordAuditValues(String, Map)}, but with controlled usage of userFilter
*
* @param rootPath a base path of {@link AuditPath} key entries concatenated with the path separator
* '/' ({@link AuditApplication#AUDIT_PATH_SEPARATOR})
* @param values the values to audit mapped by {@link AuditPath} key relative to root path
* (may be <tt>null</tt>)
* @param useUserFilter if <tt>false</tt> the user filter is disabled.
* @return Returns the values that were actually persisted, keyed by their full path.
* @throws IllegalStateException if the transaction state could not be determined
*/
Map<String, Serializable> recordAuditValuesWithUserFilter(String rootPath, Map<String, Serializable> values, boolean useUserFilter);
/**
* Find audit entries using the given parameters
*
* @param callback the data callback per entry
* @param parameters the parameters for the query (may not be <tt>null</tt>)
* @param maxResults the maximum number of results to retrieve (must be greater than 0)
*
* @throws IllegalArgumentException if maxResults less or equal to zero
*
* @since 3.2
*/
void auditQuery(AuditQueryCallback callback, AuditQueryParameters parameters, int maxResults);
/**
* Issue an audit query to retrieve min / max audit record id for a given application.
*
* @param applicationName the name of the application
* @param extremes a list containing min/max or both
* @return a map containing min/max and the associated value
*/
HashMap<String, Long> getAuditMinMaxByApp(String applicationName, List<String> extremes);
/**
* Issue an audit query to retrieve count of records for a given application.
*
* @param applicationName the name of the application
* @return a map containing min/max and the associated value
*/
default int getAuditEntriesCountByApp(String applicationName)
{
return -1;
}
/**
* Issue an audit query to retrieve count of records for a given application and properties
*
* @param applicationName the name of the application
* @param parameters audit parameters provided by the <code>where</code> clause on the ReST API
* @return a map containing min/max and the associated value
*/
default int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
{
return -1;
}
}
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2024 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.audit;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.audit.model.AuditApplication;
import org.alfresco.repo.audit.model.AuditModelRegistry;
import org.alfresco.repo.audit.model._3.AuditPath;
import org.alfresco.service.cmr.audit.AuditQueryParameters;
import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback;
/**
* The audit component. Used by the AuditService and AuditMethodInterceptor to insert audit entries.
*
* @author Derek Hulley
*/
public interface AuditComponent
{
/**
* Determines whether audit is globally enabled or disabled.
*
* @return Returns <code>true</code> if audit is enabled
*
* @since 3.3
*/
public boolean isAuditEnabled();
/**
* Switch auditing on or off
*
* @param enable
* <tt>true</tt> to enable auditing or <tt>false</tt> to disable
*
* @since 3.4
*/
public void setAuditEnabled(boolean enable);
/**
* @param userAuditFilter
* UserAuditFilter
*
* @since 4.2
*/
public void setUserAuditFilter(UserAuditFilter userAuditFilter);
/**
* Get all registered audit applications, whether active or not.
*
* @return Returns a map of registered audit applications keyed by name
*
* @since 3.4
*/
public Map<String, AuditApplication> getAuditApplications();
/**
* Determine whether the audit infrastructure expects audit values to be passed in. This is a helper method to allow optimizations in the client code. Reasons why this method might return <tt>false</tt> are: auditing is disabled; no audit applications have been registered. Sometimes, depending on the log level, this method may always return <tt>true</tt>.
*
*
* @return Returns <code>true</code> if the calling code (data producers) should go ahead and generate the data for {@link #recordAuditValues(String, Map) recording}.
*
* @since 3.3
*/
public boolean areAuditValuesRequired();
/**
* Determines if audit values are required based on whether there are any audit applications registered to record data for the given path. This helper method gives data producers a shortcut in the event that nothing would be recorded in any event.
*
* @param path
* the audit path
* @return Returns <tt>true</tt> if there is at least one audit application registered to handle the given path.
*
* @since 3.4
*/
public boolean areAuditValuesRequired(String path);
/**
* Delete audit entries for the given application and time range
*
* @param applicationName
* the name of the application
* @param fromTime
* the start time of entries to remove (inclusive and optional)
* @param toTime
* the end time of entries to remove (exclusive and optional)
* @return Returns the number of entries deleted
*
* @since 3.2
*/
int deleteAuditEntries(String applicationName, Long fromTime, Long toTime);
/**
* Delete audit entries for the given application and id range
*
* @param applicationName
* the name of the application
* @param fromId
* the start time of entries to remove (inclusive and optional)
* @param toId
* the end time of entries to remove (exclusive and optional)
* @return Returns the number of entries deleted
*
* @since 5.2.2
*/
int deleteAuditEntriesByIdRange(String applicationName, Long fromId, Long toId);
/**
* Delete a discrete list of audit entries based on ID
*
* @param auditEntryIds
* the audit entry IDs to delete
* @return Returns the number of entries deleted
*/
int deleteAuditEntries(List<Long> auditEntryIds);
/**
* Check if an audit path is enabled. The path will be disabled if it or any higher path has been explicitly disabled. Any disabled path will not be processed when data is audited.
*
* @param applicationName
* the name of the application being logged to
* @param path
* the audit path to check or <tt>null</tt> to assume the application's root path
* @return Returns <tt>true</tt> if the audit path has been disabled
*
* @since 3.2
*/
boolean isAuditPathEnabled(String applicationName, String path);
/**
* Enable auditing (if it is not already enabled) for all paths that contain the given path. The path is the path as originally logged and not the path that the generated data may contain - although this would be similarly enabled.
* <p>
* If the enabled
*
* @param applicationName
* the name of the application being logged to
* @param path
* the audit path to check or <tt>null</tt> to assume the application's root path
*
* @since 3.2
*/
void enableAudit(String applicationName, String path);
/**
* Disable auditing (if it is not already disabled) for all paths that contain the given path. The path is the path as originally logged and not the path that the generated data may contain - although this would be similarly disabled.
* <p>
* If the path is <b>/x/y</b> then any data paths that start with <b>/x/y</b> will be stripped out <u>before</u> data generators and data recorders are applied. If the path represents the root path of the application, then auditing for that application is effectively disabled.
*
* @param applicationName
* the name of the application being logged to
* @param path
* the audit path to check or <tt>null</tt> to assume the application's root path
*
* @since 3.2
*/
void disableAudit(String applicationName, String path);
/**
* Remove all disabled paths i.e. enable all per-path based auditing. Auditing may still be disabled globally. This is primarily for test purposes; applications should know which paths need {@link #enableAudit(String, String) enabling} or {@link #disableAudit(String, String) disabled}.
*
* @param applicationName
* the name of the application
*
* @since 3.2
*/
void resetDisabledPaths(String applicationName);
/**
* Create an audit entry for the given map of values. The map key is a path - starting with '/' ({@link AuditApplication#AUDIT_PATH_SEPARATOR}) - relative to the root path provided.
* <p/>
* The root path and value keys are combined to produce a map of data keyed by full path. This fully-pathed map is then passed through the {@link AuditModelRegistry#getAuditPathMapper() audit path mapper}. The result may yield data destined for several different {@link AuditModelRegistry#getAuditApplicationByKey(String) audit applications}. depending on the data extraction and generation defined in the applications, values (or derived values) may be recorded against several audit entries (one per application represented).
* <p/>
* The return values reflect what was actually persisted and is controlled by the data extractors defined in the audit configuration.
* <p/>
* A new read-write transaction is started if there are values to write that there is not a viable transaction present.
*
* @param rootPath
* a base path of {@link AuditPath} key entries concatenated with the path separator '/' ({@link AuditApplication#AUDIT_PATH_SEPARATOR})
* @param values
* the values to audit mapped by {@link AuditPath} key relative to root path (may be <tt>null</tt>)
* @return Returns the values that were actually persisted, keyed by their full path.
* @throws IllegalStateException
* if the transaction state could not be determined
*
* @since 3.2
*/
Map<String, Serializable> recordAuditValues(String rootPath, Map<String, Serializable> values);
/**
* The same as {@link AuditComponent#recordAuditValues(String, Map)}, but with controlled usage of userFilter
*
* @param rootPath
* a base path of {@link AuditPath} key entries concatenated with the path separator '/' ({@link AuditApplication#AUDIT_PATH_SEPARATOR})
* @param values
* the values to audit mapped by {@link AuditPath} key relative to root path (may be <tt>null</tt>)
* @param useUserFilter
* if <tt>false</tt> the user filter is disabled.
* @return Returns the values that were actually persisted, keyed by their full path.
* @throws IllegalStateException
* if the transaction state could not be determined
*/
Map<String, Serializable> recordAuditValuesWithUserFilter(String rootPath, Map<String, Serializable> values, boolean useUserFilter);
/**
* Find audit entries using the given parameters
*
* @param callback
* the data callback per entry
* @param parameters
* the parameters for the query (may not be <tt>null</tt>)
* @param maxResults
* the maximum number of results to retrieve (must be greater than 0)
*
* @throws IllegalArgumentException
* if maxResults less or equal to zero
*
* @since 3.2
*/
void auditQuery(AuditQueryCallback callback, AuditQueryParameters parameters, int maxResults);
/**
* Issue an audit query to retrieve min / max audit record id for a given application.
*
* @param applicationName
* the name of the application
* @param extremes
* a list containing min/max or both
* @return a map containing min/max and the associated value
*/
HashMap<String, Long> getAuditMinMaxByApp(String applicationName, List<String> extremes);
/**
* Issue an audit query to retrieve count of records for a given application.
*
* @param applicationName
* the name of the application
* @return a map containing min/max and the associated value
*/
default int getAuditEntriesCountByApp(String applicationName)
{
return -1;
}
/**
* Issue an audit query to retrieve count of records for a given application and properties
*
* @param applicationName
* the name of the application
* @param parameters
* audit parameters provided by the <code>where</code> clause on the ReST API
* @return a map containing min/max and the associated value
*/
default int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
{
return -1;
}
}

View File

@@ -1,197 +1,210 @@
/*
* #%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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.audit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.alfresco.service.cmr.audit.AuditQueryParameters;
import org.alfresco.service.cmr.audit.AuditService;
/**
* The implementation of the AuditService for application auditing.
*
* @author Derek Hulley
* @since 3.2
*/
public class AuditServiceImpl implements AuditService
{
private AuditComponent auditComponent;
public AuditServiceImpl()
{
super();
}
public void setAuditComponent(AuditComponent auditComponent)
{
this.auditComponent = auditComponent;
}
/**
* {@inheritDoc}
* @since 3.4
*/
public boolean isAuditEnabled()
{
return auditComponent.isAuditEnabled();
}
/**
* {@inheritDoc}
* @since 3.4
*/
@Override
public void setAuditEnabled(boolean enable)
{
auditComponent.setAuditEnabled(enable);
}
/**
* {@inheritDoc}
* @since 3.4
*/
@Override
public Map<String, AuditApplication> getAuditApplications()
{
Map<String, org.alfresco.repo.audit.model.AuditApplication> apps = auditComponent.getAuditApplications();
Map<String, AuditApplication> ret = new TreeMap<String, AuditApplication>();
for (String app : apps.keySet())
{
String name = app;
String key = org.alfresco.repo.audit.model.AuditApplication.AUDIT_PATH_SEPARATOR + apps.get(app).getApplicationKey();
boolean enabled = auditComponent.isAuditPathEnabled(app, key);
AuditApplication auditApplication = new AuditApplication(name, key, enabled);
ret.put(name, auditApplication);
}
return ret;
}
/**
* {@inheritDoc}
* @since 3.2
*/
public boolean isAuditEnabled(String applicationName, String path)
{
return auditComponent.isAuditPathEnabled(applicationName, path);
}
/**
* {@inheritDoc}
* @since 3.2
*/
public void enableAudit(String applicationName, String path)
{
auditComponent.enableAudit(applicationName, path);
}
/**
* {@inheritDoc}
* @since 3.2
*/
public void disableAudit(String applicationName, String path)
{
auditComponent.disableAudit(applicationName, path);
}
/**
* {@inheritDoc}
* @since 3.2
*/
public int clearAudit(String applicationName)
{
Long now = Long.valueOf(System.currentTimeMillis());
return auditComponent.deleteAuditEntries(applicationName, null, now);
}
/**
* {@inheritDoc}
* @since 3.4
*/
@Override
public int clearAudit(String applicationName, Long fromTime, Long toTime)
{
toTime = (toTime == null) ? Long.valueOf(System.currentTimeMillis()) : toTime;
return auditComponent.deleteAuditEntries(applicationName, fromTime, toTime);
}
/**
* {@inheritDoc}
* @since 5.2.2
*/
@Override
public int clearAuditByIdRange(String applicationName, Long fromId, Long toId)
{
return auditComponent.deleteAuditEntriesByIdRange(applicationName, fromId, toId);
}
/**
* {@inheritDoc}
* @since 3.4
*/
@Override
public int clearAudit(List<Long> auditEntryIds)
{
return auditComponent.deleteAuditEntries(auditEntryIds);
}
/**
* {@inheritDoc}
* @since 3.3
*/
public void auditQuery(AuditQueryCallback callback, AuditQueryParameters parameters, int maxResults)
{
auditComponent.auditQuery(callback, parameters, maxResults);
}
/**
* {@inheritDoc}
*/
public HashMap<String, Long> getAuditMinMaxByApp(String applicationName, List<String> extremes)
{
return auditComponent.getAuditMinMaxByApp(applicationName, extremes);
}
/**
* {@inheritDoc}
*/
@Override
public int getAuditEntriesCountByApp(String applicationName)
{
return auditComponent.getAuditEntriesCountByApp(applicationName);
}
/**
* {@inheritDoc}
*/
@Override public int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
{
return auditComponent.getAuditEntriesCountByAppAndProperties(applicationName, parameters);
}
}
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2024 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.audit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.alfresco.service.cmr.audit.AuditQueryParameters;
import org.alfresco.service.cmr.audit.AuditService;
/**
* The implementation of the AuditService for application auditing.
*
* @author Derek Hulley
* @since 3.2
*/
public class AuditServiceImpl implements AuditService
{
private AuditComponent auditComponent;
public AuditServiceImpl()
{
super();
}
public void setAuditComponent(AuditComponent auditComponent)
{
this.auditComponent = auditComponent;
}
/**
* {@inheritDoc}
*
* @since 3.4
*/
public boolean isAuditEnabled()
{
return auditComponent.isAuditEnabled();
}
/**
* {@inheritDoc}
*
* @since 3.4
*/
@Override
public void setAuditEnabled(boolean enable)
{
auditComponent.setAuditEnabled(enable);
}
/**
* {@inheritDoc}
*
* @since 3.4
*/
@Override
public Map<String, AuditApplication> getAuditApplications()
{
Map<String, org.alfresco.repo.audit.model.AuditApplication> apps = auditComponent.getAuditApplications();
Map<String, AuditApplication> ret = new TreeMap<String, AuditApplication>();
for (String app : apps.keySet())
{
String name = app;
String key = org.alfresco.repo.audit.model.AuditApplication.AUDIT_PATH_SEPARATOR + apps.get(app).getApplicationKey();
boolean enabled = auditComponent.isAuditPathEnabled(app, key);
AuditApplication auditApplication = new AuditApplication(name, key, enabled);
ret.put(name, auditApplication);
}
return ret;
}
/**
* {@inheritDoc}
*
* @since 3.2
*/
public boolean isAuditEnabled(String applicationName, String path)
{
return auditComponent.isAuditPathEnabled(applicationName, path);
}
/**
* {@inheritDoc}
*
* @since 3.2
*/
public void enableAudit(String applicationName, String path)
{
auditComponent.enableAudit(applicationName, path);
}
/**
* {@inheritDoc}
*
* @since 3.2
*/
public void disableAudit(String applicationName, String path)
{
auditComponent.disableAudit(applicationName, path);
}
/**
* {@inheritDoc}
*
* @since 3.2
*/
public int clearAudit(String applicationName)
{
Long now = Long.valueOf(System.currentTimeMillis());
return auditComponent.deleteAuditEntries(applicationName, null, now);
}
/**
* {@inheritDoc}
*
* @since 3.4
*/
@Override
public int clearAudit(String applicationName, Long fromTime, Long toTime)
{
toTime = (toTime == null) ? Long.valueOf(System.currentTimeMillis()) : toTime;
return auditComponent.deleteAuditEntries(applicationName, fromTime, toTime);
}
/**
* {@inheritDoc}
*
* @since 5.2.2
*/
@Override
public int clearAuditByIdRange(String applicationName, Long fromId, Long toId)
{
return auditComponent.deleteAuditEntriesByIdRange(applicationName, fromId, toId);
}
/**
* {@inheritDoc}
*
* @since 3.4
*/
@Override
public int clearAudit(List<Long> auditEntryIds)
{
return auditComponent.deleteAuditEntries(auditEntryIds);
}
/**
* {@inheritDoc}
*
* @since 3.3
*/
public void auditQuery(AuditQueryCallback callback, AuditQueryParameters parameters, int maxResults)
{
auditComponent.auditQuery(callback, parameters, maxResults);
}
/**
* {@inheritDoc}
*/
public HashMap<String, Long> getAuditMinMaxByApp(String applicationName, List<String> extremes)
{
return auditComponent.getAuditMinMaxByApp(applicationName, extremes);
}
/**
* {@inheritDoc}
*/
@Override
public int getAuditEntriesCountByApp(String applicationName)
{
return auditComponent.getAuditEntriesCountByApp(applicationName);
}
/**
* {@inheritDoc}
*/
@Override
public int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
{
return auditComponent.getAuditEntriesCountByAppAndProperties(applicationName, parameters);
}
}

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -23,100 +23,95 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.domain;
import java.io.UnsupportedEncodingException;
import java.util.zip.CRC32;
import org.alfresco.util.Pair;
/**
* Helper class to calculate CRC values for string persistence.
*
* @author Derek Hulley
* @since 3.2
*/
public class CrcHelper
{
public static final String EMPTY_STRING = ".empty";
/**
* Calculate a persistable, unique pair of values that can be persisted in a database unique
* key and guarantee correct case-sensitivity.
* <p>
* While the short-string version of the value is always lowercase, the CRC is
* calculated from the virgin string if case-sensitivity is enforced; in the case-insensitive
* case, the CRC is calculated from a lowercase version of the string.
* <p>
* If the value is an empty string, then {@link #EMPTY_STRING} is used instead. This ensures
* that persisted values don't fall foul of the Oracle empty string comparison "behaviour" i.e
* you should never persist an empty string in Oracle as it equates to a SQL <b>NULL</b>.
*
* @param value the raw value that will be persisted
* @param dataLength the maximum number of characters that can be persisted
* @param useCharsFromStart <tt>true</tt> if the shortened string value must be made from
* the first characters of the string or <tt>false</tt> to use
* characters from the end of the string.
* @param caseSensitive <tt>true</tt> if the resulting pair must be case-sensitive or
* <tt>false</tt> if the pair must be case-insensitive.
* @return Return the persistable pair. The result will never be <tt>null</tt>,
* but the individual pair values will be <tt>null</tt> if the
* value given is <tt>null</tt>
*/
public static Pair<String, Long> getStringCrcPair(
String value,
int dataLength,
boolean useCharsFromStart,
boolean caseSensitive)
{
String valueLowerCase;
if (value == null)
{
return new Pair<String, Long>(null, null);
}
else if (value.length() == 0)
{
value = CrcHelper.EMPTY_STRING;
valueLowerCase = value;
}
else
{
valueLowerCase = value.toLowerCase();
}
Long valueCrc;
try
{
CRC32 crc = new CRC32();
if (caseSensitive)
{
crc.update(value.getBytes("UTF-8"));
}
else
{
crc.update(valueLowerCase.getBytes("UTF-8"));
}
valueCrc = crc.getValue();
}
catch (UnsupportedEncodingException e)
{
throw new RuntimeException("UTF-8 encoding is not supported");
}
// Get the short value (case-sensitive or not)
String valueShort = null;
int valueLen = valueLowerCase.length();
if (valueLen < dataLength)
{
valueShort = valueLowerCase;
}
else if (useCharsFromStart)
{
valueShort = valueLowerCase.substring(0, dataLength - 1);
}
else
{
valueShort = valueLowerCase.substring(valueLen - dataLength);
}
return new Pair<String, Long>(valueShort, valueCrc);
}
}
package org.alfresco.repo.domain;
import java.io.UnsupportedEncodingException;
import java.util.zip.CRC32;
import org.alfresco.util.Pair;
/**
* Helper class to calculate CRC values for string persistence.
*
* @author Derek Hulley
* @since 3.2
*/
public class CrcHelper
{
public static final String EMPTY_STRING = ".empty";
/**
* Calculate a persistable, unique pair of values that can be persisted in a database unique key and guarantee correct case-sensitivity.
* <p>
* While the short-string version of the value is always lowercase, the CRC is calculated from the virgin string if case-sensitivity is enforced; in the case-insensitive case, the CRC is calculated from a lowercase version of the string.
* <p>
* If the value is an empty string, then {@link #EMPTY_STRING} is used instead. This ensures that persisted values don't fall foul of the Oracle empty string comparison "behaviour" i.e you should never persist an empty string in Oracle as it equates to a SQL <b>NULL</b>.
*
* @param value
* the raw value that will be persisted
* @param dataLength
* the maximum number of characters that can be persisted
* @param useCharsFromStart
* <tt>true</tt> if the shortened string value must be made from the first characters of the string or <tt>false</tt> to use characters from the end of the string.
* @param caseSensitive
* <tt>true</tt> if the resulting pair must be case-sensitive or <tt>false</tt> if the pair must be case-insensitive.
* @return Return the persistable pair. The result will never be <tt>null</tt>, but the individual pair values will be <tt>null</tt> if the value given is <tt>null</tt>
*/
public static Pair<String, Long> getStringCrcPair(
String value,
int dataLength,
boolean useCharsFromStart,
boolean caseSensitive)
{
String valueLowerCase;
if (value == null)
{
return new Pair<String, Long>(null, null);
}
else if (value.length() == 0)
{
value = CrcHelper.EMPTY_STRING;
valueLowerCase = value;
}
else
{
valueLowerCase = value.toLowerCase();
}
Long valueCrc;
try
{
CRC32 crc = new CRC32();
if (caseSensitive)
{
crc.update(value.getBytes("UTF-8"));
}
else
{
crc.update(valueLowerCase.getBytes("UTF-8"));
}
valueCrc = crc.getValue();
}
catch (UnsupportedEncodingException e)
{
throw new RuntimeException("UTF-8 encoding is not supported");
}
// Get the short value (case-sensitive or not)
String valueShort = null;
int valueLen = valueLowerCase.length();
if (valueLen < dataLength)
{
valueShort = valueLowerCase;
}
else if (useCharsFromStart)
{
valueShort = valueLowerCase.substring(0, dataLength - 1);
}
else
{
valueShort = valueLowerCase.substring(valueLen - dataLength);
}
return new Pair<String, Long>(valueShort, valueCrc);
}
}

View File

@@ -1,259 +1,286 @@
/*
* #%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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.domain.audit;
import java.io.Serializable;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.util.Pair;
/**
* DAO services for <b>alf_audit_XXX</b> tables.
* <p>
* The older methods are supported by a different implementation and will eventually
* be deprecated and phased out.
*
* @author Derek Hulley
* @since 3.2
*/
public interface AuditDAO
{
/*
* V3.2 methods after here only, please
*/
/**
* Information about the audit application to be passed in an out of the interface.
*
* @author Derek Hulley
* @since 3.2
*/
public static class AuditApplicationInfo
{
private Long id;
private String name;
private Long modelId;
private Long disabledPathsId;
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("AuditApplicationInfo ")
.append("[ id=").append(id)
.append(", name=").append(name)
.append(", modelId=").append(modelId)
.append(", disabledPathsId=").append(disabledPathsId)
.append("]");
return sb.toString();
}
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setname(String name)
{
this.name = name;
}
public Long getModelId()
{
return modelId;
}
public void setModelId(Long modelId)
{
this.modelId = modelId;
}
public Long getDisabledPathsId()
{
return disabledPathsId;
}
public void setDisabledPathsId(Long disabledPathsId)
{
this.disabledPathsId = disabledPathsId;
}
}
/**
* Creates a new audit model entry or finds an existing one
*
* @param url the URL of the configuration
* @return Returns the ID of the config matching the input stream and the
* content storage details
* @since 3.2
*/
Pair<Long, ContentData> getOrCreateAuditModel(URL url);
/**
* Get the audit application details.
*
* @param applicationName the name of the application
* @return Returns details of an existing application or <tt>null</tt> if it doesn't exist
*
* @since 3.2
*/
AuditApplicationInfo getAuditApplication(String applicationName);
/**
* Creates a new audit application. The application name must be unique.
*
* @param application the name of the application
* @param modelId the ID of the model configuration
*
* @since 3.2
*/
AuditApplicationInfo createAuditApplication(String application, Long modelId);
/**
* Update the audit application to refer to a new model.
* If the model did not change, then nothing will be done.
*
* @param id the ID of the audit application
* @param modelId the ID of the new model
*
* @since 3.2
*/
void updateAuditApplicationModel(Long id, Long modelId);
/**
* Update the audit application to hold a new set of disabled paths.
* If the value did not change, then nothing will be done.
*
* @param id the ID of the audit application
* @param disabledPaths the new disabled paths
*
* @since 3.2
*/
void updateAuditApplicationDisabledPaths(Long id, Set<String> disabledPaths);
/**
* Delete audit entries for the application, possibly limiting the time range.
*
* @param applicationId an existing audit application ID
* @param fromTime the minimum entry time (inclusive, optional)
* @param toTime the maximum entry time (exclusive, optional)
* @return Returns the number of entries deleted
*
* @since 3.2
*/
int deleteAuditEntries(Long applicationId, Long fromTime, Long toTime);
/**
* Delete audit entries for the application for given id range.
*
* @param applicationId an existing audit application ID
* @param fromId the minimum fromId (inclusive, optional)
* @param toId the maximum toId (exclusive, optional)
* @return Returns the number of entries deleted
*
* @since 5.2.2
*/
int deleteAuditEntriesByIdRange(Long applicationId, Long fromId, Long toId);
/**
* Delete a discrete list of audit entries. Duplicate entries are collapsed
* and the number of entries deleted will match the count of unique IDs in
* the list; otherwise a concurrency condition has occured and an exception
* will be generated.
*
* @param auditEntryIds the IDs of all audit entries to delete
* @return Returns the number of entries deleted
*/
int deleteAuditEntries(List<Long> auditEntryIds);
/**
* Create a new audit entry with the given map of values.
*
* @param applicationId an existing audit application ID
* @param time the time (ms since epoch) to log the entry against
* @param username the authenticated user (<tt>null</tt> if not present)
* @param values the values to record
* @return Returns the unique entry ID
*
* @since 3.2
*/
Long createAuditEntry(Long applicationId, long time, String username, Map<String, Serializable> values);
/**
* Find audit entries using the given parameters, any of which may be null
*
* @param callback the data callback per entry
* @param parameters the parameters for the query (may not be <tt>null</tt>)
* @param maxResults the maximum number of results to retrieve (must be greater than 0)
*
* @throws IllegalArgumentException if maxResults less or equal to zero
*/
void findAuditEntries(
AuditQueryCallback callback,
org.alfresco.service.cmr.audit.AuditQueryParameters parameters,
int maxResults);
/**
* Issue an audit query to retrieve min / max audit record id for a given application.
*
* @param appId the database id of the application
* @param extremes a list containing min/max or both
* @return a map containing min/max and the associated value
*/
HashMap<String, Long> getAuditMinMaxByApp(long appId, List<String> extremes);
/**
* Issue an audit query to retrieve count of records for a given application.
*
* @param applicationId the database id of the application
* @return a map containing min/max and the associated value
*/
default int getAuditEntriesCountByApp(long applicationId)
{
return -1;
}
/**
* Issue an audit query to retrieve count of records for a given application and properties
*
* @param applicationName name of the application to be queried
* @param parameters audit parameters provided by the <code>where</code> clause on the ReST API
* @return a map containing min/max and the associated value
*/
default int getAuditEntriesCountByAppAndProperties(String applicationName, org.alfresco.service.cmr.audit.AuditQueryParameters parameters)
{
return -1;
}
}
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2024 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.domain.audit;
import java.io.Serializable;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.util.Pair;
/**
* DAO services for <b>alf_audit_XXX</b> tables.
* <p>
* The older methods are supported by a different implementation and will eventually be deprecated and phased out.
*
* @author Derek Hulley
* @since 3.2
*/
public interface AuditDAO
{
/* V3.2 methods after here only, please */
/**
* Information about the audit application to be passed in an out of the interface.
*
* @author Derek Hulley
* @since 3.2
*/
public static class AuditApplicationInfo
{
private Long id;
private String name;
private Long modelId;
private Long disabledPathsId;
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("AuditApplicationInfo ")
.append("[ id=").append(id)
.append(", name=").append(name)
.append(", modelId=").append(modelId)
.append(", disabledPathsId=").append(disabledPathsId)
.append("]");
return sb.toString();
}
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setname(String name)
{
this.name = name;
}
public Long getModelId()
{
return modelId;
}
public void setModelId(Long modelId)
{
this.modelId = modelId;
}
public Long getDisabledPathsId()
{
return disabledPathsId;
}
public void setDisabledPathsId(Long disabledPathsId)
{
this.disabledPathsId = disabledPathsId;
}
}
/**
* Creates a new audit model entry or finds an existing one
*
* @param url
* the URL of the configuration
* @return Returns the ID of the config matching the input stream and the content storage details
* @since 3.2
*/
Pair<Long, ContentData> getOrCreateAuditModel(URL url);
/**
* Get the audit application details.
*
* @param applicationName
* the name of the application
* @return Returns details of an existing application or <tt>null</tt> if it doesn't exist
*
* @since 3.2
*/
AuditApplicationInfo getAuditApplication(String applicationName);
/**
* Creates a new audit application. The application name must be unique.
*
* @param application
* the name of the application
* @param modelId
* the ID of the model configuration
*
* @since 3.2
*/
AuditApplicationInfo createAuditApplication(String application, Long modelId);
/**
* Update the audit application to refer to a new model. If the model did not change, then nothing will be done.
*
* @param id
* the ID of the audit application
* @param modelId
* the ID of the new model
*
* @since 3.2
*/
void updateAuditApplicationModel(Long id, Long modelId);
/**
* Update the audit application to hold a new set of disabled paths. If the value did not change, then nothing will be done.
*
* @param id
* the ID of the audit application
* @param disabledPaths
* the new disabled paths
*
* @since 3.2
*/
void updateAuditApplicationDisabledPaths(Long id, Set<String> disabledPaths);
/**
* Delete audit entries for the application, possibly limiting the time range.
*
* @param applicationId
* an existing audit application ID
* @param fromTime
* the minimum entry time (inclusive, optional)
* @param toTime
* the maximum entry time (exclusive, optional)
* @return Returns the number of entries deleted
*
* @since 3.2
*/
int deleteAuditEntries(Long applicationId, Long fromTime, Long toTime);
/**
* Delete audit entries for the application for given id range.
*
* @param applicationId
* an existing audit application ID
* @param fromId
* the minimum fromId (inclusive, optional)
* @param toId
* the maximum toId (exclusive, optional)
* @return Returns the number of entries deleted
*
* @since 5.2.2
*/
int deleteAuditEntriesByIdRange(Long applicationId, Long fromId, Long toId);
/**
* Delete a discrete list of audit entries. Duplicate entries are collapsed and the number of entries deleted will match the count of unique IDs in the list; otherwise a concurrency condition has occured and an exception will be generated.
*
* @param auditEntryIds
* the IDs of all audit entries to delete
* @return Returns the number of entries deleted
*/
int deleteAuditEntries(List<Long> auditEntryIds);
/**
* Create a new audit entry with the given map of values.
*
* @param applicationId
* an existing audit application ID
* @param time
* the time (ms since epoch) to log the entry against
* @param username
* the authenticated user (<tt>null</tt> if not present)
* @param values
* the values to record
* @return Returns the unique entry ID
*
* @since 3.2
*/
Long createAuditEntry(Long applicationId, long time, String username, Map<String, Serializable> values);
/**
* Find audit entries using the given parameters, any of which may be null
*
* @param callback
* the data callback per entry
* @param parameters
* the parameters for the query (may not be <tt>null</tt>)
* @param maxResults
* the maximum number of results to retrieve (must be greater than 0)
*
* @throws IllegalArgumentException
* if maxResults less or equal to zero
*/
void findAuditEntries(
AuditQueryCallback callback,
org.alfresco.service.cmr.audit.AuditQueryParameters parameters,
int maxResults);
/**
* Issue an audit query to retrieve min / max audit record id for a given application.
*
* @param appId
* the database id of the application
* @param extremes
* a list containing min/max or both
* @return a map containing min/max and the associated value
*/
HashMap<String, Long> getAuditMinMaxByApp(long appId, List<String> extremes);
/**
* Issue an audit query to retrieve count of records for a given application.
*
* @param applicationId
* the database id of the application
* @return a map containing min/max and the associated value
*/
default int getAuditEntriesCountByApp(long applicationId)
{
return -1;
}
/**
* Issue an audit query to retrieve count of records for a given application and properties
*
* @param applicationName
* name of the application to be queried
* @param parameters
* audit parameters provided by the <code>where</code> clause on the ReST API
* @return a map containing min/max and the associated value
*/
default int getAuditEntriesCountByAppAndProperties(String applicationName, org.alfresco.service.cmr.audit.AuditQueryParameters parameters)
{
return -1;
}
}

View File

@@ -1,316 +1,315 @@
/*
* #%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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.domain.audit.ibatis;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.alfresco.repo.domain.audit.AbstractAuditDAOImpl;
import org.alfresco.repo.domain.audit.AuditApplicationEntity;
import org.alfresco.repo.domain.audit.AuditDeleteParameters;
import org.alfresco.repo.domain.audit.AuditEntryEntity;
import org.alfresco.repo.domain.audit.AuditModelEntity;
import org.alfresco.repo.domain.audit.AuditQueryParameters;
import org.alfresco.repo.domain.audit.AuditQueryResult;
import org.alfresco.repo.domain.propval.PropertyValueDAO.PropertyFinderCallback;
import org.alfresco.util.Pair;
import org.apache.ibatis.session.RowBounds;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.dao.ConcurrencyFailureException;
/**
* iBatis-specific implementation of the DAO for <b>alf_audit_XXX</b> tables.
*
* @author Derek Hulley
* @since 3.2
*/
public class AuditDAOImpl extends AbstractAuditDAOImpl
{
private static final String SELECT_MODEL_BY_CRC = "alfresco.audit.select_AuditModelByCrc";
private static final String INSERT_MODEL = "alfresco.audit.insert.insert_AuditModel";
private static final String SELECT_APPLICATION_BY_ID = "alfresco.audit.select_AuditApplicationById";
private static final String SELECT_APPLICATION_BY_NAME_ID = "alfresco.audit.select_AuditApplicationByNameId";
private static final String INSERT_APPLICATION = "alfresco.audit.insert.insert_AuditApplication";
private static final String UPDATE_APPLICATION = "alfresco.audit.update_AuditApplication";
private static final String DELETE_ENTRIES = "alfresco.audit.delete_AuditEntries";
private static final String DELETE_ENTRIES_BY_ID = "alfresco.audit.delete_AuditEntriesById";
private static final String INSERT_ENTRY = "alfresco.audit.insert.insert_AuditEntry";
private static final String SELECT_MINMAX_ENTRY_FOR_APP = "alfresco.audit.select_MinMaxAuditEntryId";
private static final String SELECT_COUNT_ENTRIES_FOR_APP = "alfresco.audit.select_CountAuditEntryId";
private static final String SELECT_COUNT_ENTRIES_FOR_APP_WITH_PROPERTIES = "select_CountAuditEntryIdWithWhereClause";
@SuppressWarnings("unused")
private static final String SELECT_ENTRIES_SIMPLE = "alfresco.audit.select_AuditEntriesSimple";
private static final String SELECT_ENTRIES_WITH_VALUES = "alfresco.audit.select_AuditEntriesWithValues";
private static final String SELECT_ENTRIES_WITHOUT_VALUES = "alfresco.audit.select_AuditEntriesWithoutValues";
private SqlSessionTemplate template;
public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate)
{
this.template = sqlSessionTemplate;
}
@Override
protected AuditModelEntity getAuditModelByCrc(long crc)
{
AuditModelEntity entity = new AuditModelEntity();
entity.setContentCrc(crc);
entity = template.selectOne(
SELECT_MODEL_BY_CRC,
entity);
// Done
return entity;
}
@Override
protected AuditModelEntity createAuditModel(Long contentDataId, long crc)
{
AuditModelEntity entity = new AuditModelEntity();
entity.setContentDataId(contentDataId);
entity.setContentCrc(crc);
template.insert(INSERT_MODEL, entity);
return entity;
}
@Override
protected AuditApplicationEntity getAuditApplicationById(Long id)
{
Map<String, Object> params = new HashMap<String, Object>(11);
params.put("id", id);
AuditApplicationEntity entity = template.selectOne(
SELECT_APPLICATION_BY_ID,
params);
// Done
if (logger.isDebugEnabled())
{
logger.debug("Searched for audit application ID " + id + " and found: " + entity);
}
return entity;
}
@Override
protected AuditApplicationEntity getAuditApplicationByName(String appName)
{
// Resolve the name as a property ID
Pair<Long, Serializable> appNamePair = propertyValueDAO.getPropertyValue(appName);
if (appNamePair == null)
{
// There will be no results
return null;
}
Map<String, Object> params = new HashMap<String, Object>(11);
params.put("id", appNamePair.getFirst());
AuditApplicationEntity entity = template.selectOne(
SELECT_APPLICATION_BY_NAME_ID,
params);
// Done
if (logger.isDebugEnabled())
{
logger.debug("Searched for audit application '" + appName + "' and found: " + entity);
}
return entity;
}
@Override
protected AuditApplicationEntity createAuditApplication(Long appNameId, Long modelId, Long disabledPathsId)
{
AuditApplicationEntity entity = new AuditApplicationEntity();
entity.setVersion((short)0);
entity.setApplicationNameId(appNameId);
entity.setAuditModelId(modelId);
entity.setDisabledPathsId(disabledPathsId);
template.insert(INSERT_APPLICATION, entity);
return entity;
}
@Override
protected AuditApplicationEntity updateAuditApplication(AuditApplicationEntity entity)
{
AuditApplicationEntity updateEntity = new AuditApplicationEntity();
updateEntity.setId(entity.getId());
updateEntity.setVersion(entity.getVersion());
updateEntity.incrementVersion();
updateEntity.setApplicationNameId(entity.getApplicationNameId());
updateEntity.setAuditModelId(entity.getAuditModelId());
updateEntity.setDisabledPathsId(entity.getDisabledPathsId());
int updated = template.update(UPDATE_APPLICATION, updateEntity);
if (updated != 1)
{
// unexpected number of rows affected
throw new ConcurrencyFailureException("Incorrect number of rows affected for updateAuditApplication: " + updateEntity + ": expected 1, actual " + updated);
}
// Done
return updateEntity;
}
public int deleteAuditEntries(Long applicationId, Long from, Long to)
{
AuditDeleteParameters params = new AuditDeleteParameters();
params.setAuditApplicationId(applicationId);
params.setAuditFromTime(from);
params.setAuditToTime(to);
return template.delete(DELETE_ENTRIES, params);
}
public int deleteAuditEntriesByIdRange(Long applicationId, Long fromId, Long toId)
{
AuditDeleteParameters params = new AuditDeleteParameters();
params.setAuditApplicationId(applicationId);
params.setAuditFromId(fromId);
params.setAuditToId(toId);
return template.delete(DELETE_ENTRIES, params);
}
@Override
protected int deleteAuditEntriesImpl(List<Long> auditEntryIds)
{
AuditDeleteParameters params = new AuditDeleteParameters();
params.setAuditEntryIds(auditEntryIds);
return template.delete(DELETE_ENTRIES_BY_ID, params);
}
@Override
protected AuditEntryEntity createAuditEntry(Long applicationId, long time, Long usernameId, Long valuesId)
{
AuditEntryEntity entity = new AuditEntryEntity();
entity.setAuditApplicationId(applicationId);
entity.setAuditTime(time);
entity.setAuditUserId(usernameId);
entity.setAuditValuesId(valuesId);
template.insert(INSERT_ENTRY, entity);
return entity;
}
public HashMap<String, Long> getAuditMinMaxByApp(long appId, List<String> extremes)
{
// Build parameters to be used in the query. Filter the duplicates when inserting into map
Map<String, Object> params = extremes.stream().collect(Collectors.toMap(s -> s, s -> Boolean.TRUE, (s1, s2) -> s1));
params.put("auditAppId", appId);
HashMap<String, Long> result = template.selectOne(SELECT_MINMAX_ENTRY_FOR_APP, params);
return result;
}
@Override
public int getAuditEntriesCountByApp(long applicationId)
{
Map<String, Object> params = new HashMap<>();
params.put("auditAppId", applicationId);
int result = template.selectOne(SELECT_COUNT_ENTRIES_FOR_APP, params);
return result;
}
@Override
public int getAuditEntriesCountByAppAndProperties(String applicationName, org.alfresco.service.cmr.audit.AuditQueryParameters parameters)
{
AuditQueryParameters dbParameters = convertFromRestAuditQueryParameters(parameters);
int result = template.selectOne(SELECT_COUNT_ENTRIES_FOR_APP_WITH_PROPERTIES, dbParameters);
return result;
}
@SuppressWarnings("unchecked")
@Override
protected void findAuditEntries(
final AuditQueryRowHandler rowHandler,
int maxResults,
org.alfresco.service.cmr.audit.AuditQueryParameters restParameters)
{
AuditQueryParameters params = convertFromRestAuditQueryParameters(restParameters);
if (params==null)
{
return;
}
if (maxResults > 0)
{
// Query without getting the values. We gather all the results and batch-fetch the audited
// values afterwards.
final Map<Long, AuditQueryResult> resultsByValueId = new HashMap<Long, AuditQueryResult>(173);
PropertyFinderCallback propertyFinderCallback = new PropertyFinderCallback()
{
public void handleProperty(Long id, Serializable value)
{
// get the row
AuditQueryResult row = resultsByValueId.get(id);
try
{
row.setAuditValue((Map<String, Serializable>) value);
}
catch (ClassCastException e)
{
// The handler will deal with the entry
}
}
};
List<AuditQueryResult> rows = template.selectList(SELECT_ENTRIES_WITHOUT_VALUES, params, new RowBounds(0, maxResults));
for (AuditQueryResult row : rows)
{
resultsByValueId.put(row.getAuditValuesId(), row);
if (resultsByValueId.size() >= 100)
{
// Fetch values for the results. The treemap is ordered.
List<Long> valueIds = new ArrayList<Long>(resultsByValueId.keySet());
propertyValueDAO.getPropertiesByIds(valueIds, propertyFinderCallback);
// Clear and continue
resultsByValueId.clear();
}
}
// Process any remaining results
if (resultsByValueId.size() > 0)
{
// Fetch values for the results. The treemap is ordered.
List<Long> valueIds = new ArrayList<Long>(resultsByValueId.keySet());
propertyValueDAO.getPropertiesByIds(valueIds, propertyFinderCallback);
}
// Now pass the filled-out results to the row handler (order-preserved)
for (AuditQueryResult row : rows)
{
rowHandler.processResult(row);
}
}
else
{
throw new IllegalArgumentException("maxResults must be greater than 0");
}
}
}
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2024 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.domain.audit.ibatis;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.ibatis.session.RowBounds;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.dao.ConcurrencyFailureException;
import org.alfresco.repo.domain.audit.AbstractAuditDAOImpl;
import org.alfresco.repo.domain.audit.AuditApplicationEntity;
import org.alfresco.repo.domain.audit.AuditDeleteParameters;
import org.alfresco.repo.domain.audit.AuditEntryEntity;
import org.alfresco.repo.domain.audit.AuditModelEntity;
import org.alfresco.repo.domain.audit.AuditQueryParameters;
import org.alfresco.repo.domain.audit.AuditQueryResult;
import org.alfresco.repo.domain.propval.PropertyValueDAO.PropertyFinderCallback;
import org.alfresco.util.Pair;
/**
* iBatis-specific implementation of the DAO for <b>alf_audit_XXX</b> tables.
*
* @author Derek Hulley
* @since 3.2
*/
public class AuditDAOImpl extends AbstractAuditDAOImpl
{
private static final String SELECT_MODEL_BY_CRC = "alfresco.audit.select_AuditModelByCrc";
private static final String INSERT_MODEL = "alfresco.audit.insert.insert_AuditModel";
private static final String SELECT_APPLICATION_BY_ID = "alfresco.audit.select_AuditApplicationById";
private static final String SELECT_APPLICATION_BY_NAME_ID = "alfresco.audit.select_AuditApplicationByNameId";
private static final String INSERT_APPLICATION = "alfresco.audit.insert.insert_AuditApplication";
private static final String UPDATE_APPLICATION = "alfresco.audit.update_AuditApplication";
private static final String DELETE_ENTRIES = "alfresco.audit.delete_AuditEntries";
private static final String DELETE_ENTRIES_BY_ID = "alfresco.audit.delete_AuditEntriesById";
private static final String INSERT_ENTRY = "alfresco.audit.insert.insert_AuditEntry";
private static final String SELECT_MINMAX_ENTRY_FOR_APP = "alfresco.audit.select_MinMaxAuditEntryId";
private static final String SELECT_COUNT_ENTRIES_FOR_APP = "alfresco.audit.select_CountAuditEntryId";
private static final String SELECT_COUNT_ENTRIES_FOR_APP_WITH_PROPERTIES = "select_CountAuditEntryIdWithWhereClause";
@SuppressWarnings("unused")
private static final String SELECT_ENTRIES_SIMPLE = "alfresco.audit.select_AuditEntriesSimple";
private static final String SELECT_ENTRIES_WITH_VALUES = "alfresco.audit.select_AuditEntriesWithValues";
private static final String SELECT_ENTRIES_WITHOUT_VALUES = "alfresco.audit.select_AuditEntriesWithoutValues";
private SqlSessionTemplate template;
public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate)
{
this.template = sqlSessionTemplate;
}
@Override
protected AuditModelEntity getAuditModelByCrc(long crc)
{
AuditModelEntity entity = new AuditModelEntity();
entity.setContentCrc(crc);
entity = template.selectOne(
SELECT_MODEL_BY_CRC,
entity);
// Done
return entity;
}
@Override
protected AuditModelEntity createAuditModel(Long contentDataId, long crc)
{
AuditModelEntity entity = new AuditModelEntity();
entity.setContentDataId(contentDataId);
entity.setContentCrc(crc);
template.insert(INSERT_MODEL, entity);
return entity;
}
@Override
protected AuditApplicationEntity getAuditApplicationById(Long id)
{
Map<String, Object> params = new HashMap<String, Object>(11);
params.put("id", id);
AuditApplicationEntity entity = template.selectOne(
SELECT_APPLICATION_BY_ID,
params);
// Done
if (logger.isDebugEnabled())
{
logger.debug("Searched for audit application ID " + id + " and found: " + entity);
}
return entity;
}
@Override
protected AuditApplicationEntity getAuditApplicationByName(String appName)
{
// Resolve the name as a property ID
Pair<Long, Serializable> appNamePair = propertyValueDAO.getPropertyValue(appName);
if (appNamePair == null)
{
// There will be no results
return null;
}
Map<String, Object> params = new HashMap<String, Object>(11);
params.put("id", appNamePair.getFirst());
AuditApplicationEntity entity = template.selectOne(
SELECT_APPLICATION_BY_NAME_ID,
params);
// Done
if (logger.isDebugEnabled())
{
logger.debug("Searched for audit application '" + appName + "' and found: " + entity);
}
return entity;
}
@Override
protected AuditApplicationEntity createAuditApplication(Long appNameId, Long modelId, Long disabledPathsId)
{
AuditApplicationEntity entity = new AuditApplicationEntity();
entity.setVersion((short) 0);
entity.setApplicationNameId(appNameId);
entity.setAuditModelId(modelId);
entity.setDisabledPathsId(disabledPathsId);
template.insert(INSERT_APPLICATION, entity);
return entity;
}
@Override
protected AuditApplicationEntity updateAuditApplication(AuditApplicationEntity entity)
{
AuditApplicationEntity updateEntity = new AuditApplicationEntity();
updateEntity.setId(entity.getId());
updateEntity.setVersion(entity.getVersion());
updateEntity.incrementVersion();
updateEntity.setApplicationNameId(entity.getApplicationNameId());
updateEntity.setAuditModelId(entity.getAuditModelId());
updateEntity.setDisabledPathsId(entity.getDisabledPathsId());
int updated = template.update(UPDATE_APPLICATION, updateEntity);
if (updated != 1)
{
// unexpected number of rows affected
throw new ConcurrencyFailureException("Incorrect number of rows affected for updateAuditApplication: " + updateEntity + ": expected 1, actual " + updated);
}
// Done
return updateEntity;
}
public int deleteAuditEntries(Long applicationId, Long from, Long to)
{
AuditDeleteParameters params = new AuditDeleteParameters();
params.setAuditApplicationId(applicationId);
params.setAuditFromTime(from);
params.setAuditToTime(to);
return template.delete(DELETE_ENTRIES, params);
}
public int deleteAuditEntriesByIdRange(Long applicationId, Long fromId, Long toId)
{
AuditDeleteParameters params = new AuditDeleteParameters();
params.setAuditApplicationId(applicationId);
params.setAuditFromId(fromId);
params.setAuditToId(toId);
return template.delete(DELETE_ENTRIES, params);
}
@Override
protected int deleteAuditEntriesImpl(List<Long> auditEntryIds)
{
AuditDeleteParameters params = new AuditDeleteParameters();
params.setAuditEntryIds(auditEntryIds);
return template.delete(DELETE_ENTRIES_BY_ID, params);
}
@Override
protected AuditEntryEntity createAuditEntry(Long applicationId, long time, Long usernameId, Long valuesId)
{
AuditEntryEntity entity = new AuditEntryEntity();
entity.setAuditApplicationId(applicationId);
entity.setAuditTime(time);
entity.setAuditUserId(usernameId);
entity.setAuditValuesId(valuesId);
template.insert(INSERT_ENTRY, entity);
return entity;
}
public HashMap<String, Long> getAuditMinMaxByApp(long appId, List<String> extremes)
{
// Build parameters to be used in the query. Filter the duplicates when inserting into map
Map<String, Object> params = extremes.stream().collect(Collectors.toMap(s -> s, s -> Boolean.TRUE, (s1, s2) -> s1));
params.put("auditAppId", appId);
HashMap<String, Long> result = template.selectOne(SELECT_MINMAX_ENTRY_FOR_APP, params);
return result;
}
@Override
public int getAuditEntriesCountByApp(long applicationId)
{
Map<String, Object> params = new HashMap<>();
params.put("auditAppId", applicationId);
int result = template.selectOne(SELECT_COUNT_ENTRIES_FOR_APP, params);
return result;
}
@Override
public int getAuditEntriesCountByAppAndProperties(String applicationName, org.alfresco.service.cmr.audit.AuditQueryParameters parameters)
{
AuditQueryParameters dbParameters = convertFromRestAuditQueryParameters(parameters);
int result = template.selectOne(SELECT_COUNT_ENTRIES_FOR_APP_WITH_PROPERTIES, dbParameters);
return result;
}
@SuppressWarnings("unchecked")
@Override
protected void findAuditEntries(
final AuditQueryRowHandler rowHandler,
int maxResults,
org.alfresco.service.cmr.audit.AuditQueryParameters restParameters)
{
AuditQueryParameters params = convertFromRestAuditQueryParameters(restParameters);
if (params == null)
{
return;
}
if (maxResults > 0)
{
// Query without getting the values. We gather all the results and batch-fetch the audited
// values afterwards.
final Map<Long, AuditQueryResult> resultsByValueId = new HashMap<Long, AuditQueryResult>(173);
PropertyFinderCallback propertyFinderCallback = new PropertyFinderCallback() {
public void handleProperty(Long id, Serializable value)
{
// get the row
AuditQueryResult row = resultsByValueId.get(id);
try
{
row.setAuditValue((Map<String, Serializable>) value);
}
catch (ClassCastException e)
{
// The handler will deal with the entry
}
}
};
List<AuditQueryResult> rows = template.selectList(SELECT_ENTRIES_WITHOUT_VALUES, params, new RowBounds(0, maxResults));
for (AuditQueryResult row : rows)
{
resultsByValueId.put(row.getAuditValuesId(), row);
if (resultsByValueId.size() >= 100)
{
// Fetch values for the results. The treemap is ordered.
List<Long> valueIds = new ArrayList<Long>(resultsByValueId.keySet());
propertyValueDAO.getPropertiesByIds(valueIds, propertyFinderCallback);
// Clear and continue
resultsByValueId.clear();
}
}
// Process any remaining results
if (resultsByValueId.size() > 0)
{
// Fetch values for the results. The treemap is ordered.
List<Long> valueIds = new ArrayList<Long>(resultsByValueId.keySet());
propertyValueDAO.getPropertiesByIds(valueIds, propertyFinderCallback);
}
// Now pass the filled-out results to the row handler (order-preserved)
for (AuditQueryResult row : rows)
{
rowHandler.processResult(row);
}
}
else
{
throw new IllegalArgumentException("maxResults must be greater than 0");
}
}
}

View File

@@ -2785,6 +2785,23 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
selectNodesWithAspects(qnameIds, minNodeId, maxNodeId, ordered, resultsCallback);
}
@Override
public void getNodesWithAspects(
Set<QName> aspectQNames,
Long minNodeId, Long maxNodeId, boolean ordered,
int maxResults,
NodeRefQueryCallback resultsCallback)
{
Set<Long> qnameIdsSet = qnameDAO.convertQNamesToIds(aspectQNames, false);
if (qnameIdsSet.isEmpty())
{
// No point running a query
return;
}
List<Long> qnameIds = new ArrayList<>(qnameIdsSet);
selectNodesWithAspects(qnameIds, minNodeId, maxNodeId, ordered, maxResults, resultsCallback);
}
/**
* @return Returns a writable copy of the cached aspects set
*/
@@ -4960,6 +4977,10 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
List<Long> qnameIds,
Long minNodeId, Long maxNodeId, boolean ordered,
NodeRefQueryCallback resultsCallback);
protected abstract void selectNodesWithAspects(
List<Long> qnameIds,
Long minNodeId, Long maxNodeId, boolean ordered, int maxResults,
NodeRefQueryCallback resultsCallback);
protected abstract Long insertNodeAssoc(Long sourceNodeId, Long targetNodeId, Long assocTypeQNameId, int assocIndex);
protected abstract int updateNodeAssoc(Long id, int assocIndex);
protected abstract int deleteNodeAssoc(Long sourceNodeId, Long targetNodeId, Long assocTypeQNameId);
@@ -5088,4 +5109,5 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
protected abstract Long selectMinTxInNodeIdRange(Long fromNodeId, Long toNodeId);
protected abstract Long selectMaxTxInNodeIdRange(Long fromNodeId, Long toNodeId);
protected abstract Long selectNextTxCommitTime(Long fromCommitTime);
}

View File

@@ -427,6 +427,22 @@ public interface NodeDAO extends NodeBulkLoader
Long minNodeId, Long maxNodeId, boolean ordered,
NodeRefQueryCallback resultsCallback);
/**
* Get nodes with aspects between the given ranges, ordering the results optionally
* and limit the result set
*
* @param aspectQNames the aspects that must be on the nodes
* @param minNodeId the minimum node ID (inclusive)
* @param maxNodeId the maximum node ID (exclusive)
* @param ordered if the results are to be ordered by nodeID
* @param maxResults limit query to maxResults
* @param resultsCallback callback to process results
*/
public void getNodesWithAspects(
Set<QName> aspectQNames,
Long minNodeId, Long maxNodeId, boolean ordered, int maxResults,
NodeRefQueryCallback resultsCallback);
/*
* Node Assocs
*/

View File

@@ -116,6 +116,7 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
private static final String SELECT_NODE_MAX_ID = "alfresco.node.select_NodeMaxId";
private static final String SELECT_NODE_INTERVAL_BY_TYPE = "alfresco.node.select_MinMaxNodeIdForNodeType";
private static final String SELECT_NODES_WITH_ASPECT_IDS = "alfresco.node.select_NodesWithAspectIds";
private static final String SELECT_NODES_WITH_ASPECT_IDS_LIMITED = "alfresco.node.select_NodesWithAspectIds_Limited";
private static final String INSERT_NODE_ASSOC = "alfresco.node.insert.insert_NodeAssoc";
private static final String UPDATE_NODE_ASSOC = "alfresco.node.update_NodeAssoc";
private static final String DELETE_NODE_ASSOC = "alfresco.node.delete_NodeAssoc";
@@ -799,6 +800,33 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
template.select(SELECT_NODES_WITH_ASPECT_IDS, parameters, resultHandler);
}
@Override
protected void selectNodesWithAspects(
List<Long> qnameIds,
Long minNodeId, Long maxNodeId, boolean ordered,
final int maxResults,
final NodeRefQueryCallback resultsCallback)
{
@SuppressWarnings("rawtypes")
ResultHandler resultHandler = new ResultHandler()
{
public void handleResult(ResultContext context)
{
NodeEntity entity = (NodeEntity) context.getResultObject();
Pair<Long, NodeRef> nodePair = new Pair<>(entity.getId(), entity.getNodeRef());
resultsCallback.handle(nodePair);
}
};
IdsEntity parameters = new IdsEntity();
parameters.setIdOne(minNodeId);
parameters.setIdTwo(maxNodeId);
parameters.setIds(qnameIds);
parameters.setOrdered(ordered);
parameters.setMaxResults(maxResults);
template.select(SELECT_NODES_WITH_ASPECT_IDS_LIMITED, parameters, resultHandler);
}
@Override
protected Long insertNodeAssoc(Long sourceNodeId, Long targetNodeId, Long assocTypeQNameId, int assocIndex)
{

View File

@@ -85,8 +85,11 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
public static final String FIXED_ACL_ASYNC_REQUIRED_KEY = "FIXED_ACL_ASYNC_REQUIRED";
public static final String FIXED_ACL_ASYNC_CALL_KEY = "FIXED_ACL_ASYNC_CALL";
protected static final QName LOCK_Q_NAME = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "FixedAclUpdater");
private static final int DEFAULT_MAX_ITEMS = Integer.MAX_VALUE;
/** A set of listeners to receive callback events whenever permissions are updated by this class. */
private static Set<FixedAclUpdaterListener> listeners = Sets.newConcurrentHashSet();
@@ -101,6 +104,8 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
private int maxItemBatchSize = 100;
private int numThreads = 4;
private boolean forceSharedACL = false;
private int maxItems = DEFAULT_MAX_ITEMS;
private boolean orderNodes = true;
private ClassPolicyDelegate<OnInheritPermissionsDisabled> onInheritPermissionsDisabledDelegate;
private PolicyComponent policyComponent;
@@ -147,12 +152,22 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
this.forceSharedACL = forceSharedACL;
}
public void setOrderNodes(boolean orderNodes)
{
this.orderNodes = orderNodes;
}
public void setLockTimeToLive(long lockTimeToLive)
{
this.lockTimeToLive = lockTimeToLive;
this.lockRefreshTime = lockTimeToLive / 2;
}
public void setMaxItems(int maxItems)
{
this.maxItems = maxItems > 0 ? maxItems : DEFAULT_MAX_ITEMS;
}
public void setPolicyComponent(PolicyComponent policyComponent)
{
this.policyComponent = policyComponent;
@@ -209,7 +224,7 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
public List<NodeRef> execute() throws Throwable
{
getNodesCallback.init();
nodeDAO.getNodesWithAspects(aspects, getNodesCallback.getMinNodeId(), null, true, getNodesCallback);
nodeDAO.getNodesWithAspects(aspects, getNodesCallback.getMinNodeId(), null, orderNodes, maxItemBatchSize, getNodesCallback);
getNodesCallback.done();
return getNodesCallback.getNodes();
@@ -220,6 +235,11 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
int countNodesWithAspects()
{
if (maxItems < DEFAULT_MAX_ITEMS) {
log.info("Job limited to process a maximum of " + maxItems + " Pending Acls");
return maxItems;
}
final CountNodesWithAspectCallback countNodesCallback = new CountNodesWithAspectCallback();
int count = transactionService.getRetryingTransactionHelper()
.doInTransaction(new RetryingTransactionCallback<Integer>()
@@ -238,6 +258,9 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
private class AclWorkProvider implements BatchProcessWorkProvider<NodeRef>
{
private GetNodesWithAspects getNodesWithAspects;
private long estimatedUpdatedItems;
private long execTime;
private long execBatches;
AclWorkProvider()
{
@@ -259,8 +282,37 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
@Override
public Collection<NodeRef> getNextWork()
{
return getNodesWithAspects.getNodesWithAspects();
if(estimatedUpdatedItems >= maxItems)
{
log.info("Reached max items to process. Nodes Processed: " + estimatedUpdatedItems + "/" + maxItems);
return Collections.emptyList();
}
long initTime = System.currentTimeMillis();
Collection<NodeRef> batchNodes = getNodesWithAspects.getNodesWithAspects();
long endTime = System.currentTimeMillis();
if (log.isDebugEnabled())
{
log.debug("Query for batch executed in " + (endTime-initTime) + " ms");
}
if (!batchNodes.isEmpty())
{
// Increment estimatedUpdatedItems with the expected number of nodes to process
estimatedUpdatedItems += batchNodes.size();
execTime+=endTime-initTime;
execBatches++;
}
return batchNodes;
}
public double getAverageQueryExecutionTime()
{
return execBatches > 0 ? execTime/execBatches : 0;
}
}
protected class AclWorker implements BatchProcessor.BatchProcessWorker<NodeRef>
@@ -451,6 +503,7 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
try
{
log.info("Running FixedAclUpdater. Max Items: " + maxItems + ", Impose order: " + orderNodes);
lockToken = jobLockService.getLock(LOCK_Q_NAME, lockTimeToLive, 0, 1);
jobLockService.refreshLock(lockToken, LOCK_Q_NAME, lockRefreshTime, jobLockRefreshCallback);
@@ -460,6 +513,7 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
transactionService.getRetryingTransactionHelper(), provider, numThreads, maxItemBatchSize, applicationContext,
log, 100);
int count = bp.process(worker, true);
log.info("FixedAclUpdater updated " + count + ". Average query time " + provider.getAverageQueryExecutionTime() + " ms");
return count;
}
catch (LockAcquisitionException e)

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -23,137 +23,137 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.domain.propval;
import org.alfresco.repo.domain.CrcHelper;
import org.alfresco.util.EqualsHelper;
import org.alfresco.util.Pair;
/**
* Entity bean for <b>alf_prop_string_value</b> table.
*
* @author Derek Hulley
* @since 3.2
*/
public class PropertyStringValueEntity
{
public static final String EMPTY_STRING = "";
public static final String EMPTY_STRING_REPLACEMENT = ".empty";
private Long id;
private String stringValue;
private String stringEndLower;
private Long stringCrc;
public PropertyStringValueEntity()
{
}
@Override
public int hashCode()
{
return (stringValue == null ? 0 : stringValue.hashCode());
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj != null && obj instanceof PropertyStringValueEntity)
{
PropertyStringValueEntity that = (PropertyStringValueEntity) obj;
return EqualsHelper.nullSafeEquals(this.stringValue, that.stringValue);
}
else
{
return false;
}
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder(512);
sb.append("PropertyStringValueEntity")
.append("[ ID=").append(id)
.append(", stringValue=").append(stringValue)
.append("]");
return sb.toString();
}
public Pair<Long, String> getEntityPair()
{
if (stringValue != null && stringValue.equals(PropertyStringValueEntity.EMPTY_STRING_REPLACEMENT))
{
return new Pair<Long, String>(id, PropertyStringValueEntity.EMPTY_STRING);
}
else
{
return new Pair<Long, String>(id, stringValue);
}
}
/**
* Set the string and string-end values
*/
public void setValue(String value)
{
if (value == null)
{
throw new IllegalArgumentException("Null strings cannot be persisted");
}
if (value != null && value.equals(PropertyStringValueEntity.EMPTY_STRING))
{
// Oracle: We can't insert empty strings into the column.
value = PropertyStringValueEntity.EMPTY_STRING_REPLACEMENT;
}
stringValue = value;
// Calculate the crc value from the original value
Pair<String, Long> crcPair = CrcHelper.getStringCrcPair(value, 16, false, true);
stringEndLower = crcPair.getFirst();
stringCrc = crcPair.getSecond();
}
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getStringValue()
{
return stringValue;
}
public void setStringValue(String stringValue)
{
this.stringValue = stringValue;
}
public String getStringEndLower()
{
return stringEndLower;
}
public void setStringEndLower(String stringEndLower)
{
this.stringEndLower = stringEndLower;
}
public Long getStringCrc()
{
return stringCrc;
}
public void setStringCrc(Long stringCrc)
{
this.stringCrc = stringCrc;
}
}
package org.alfresco.repo.domain.propval;
import org.alfresco.repo.domain.CrcHelper;
import org.alfresco.util.EqualsHelper;
import org.alfresco.util.Pair;
/**
* Entity bean for <b>alf_prop_string_value</b> table.
*
* @author Derek Hulley
* @since 3.2
*/
public class PropertyStringValueEntity
{
public static final String EMPTY_STRING = "";
public static final String EMPTY_STRING_REPLACEMENT = ".empty";
private Long id;
private String stringValue;
private String stringEndLower;
private Long stringCrc;
public PropertyStringValueEntity()
{}
@Override
public int hashCode()
{
return (stringValue == null ? 0 : stringValue.hashCode());
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj != null && obj instanceof PropertyStringValueEntity)
{
PropertyStringValueEntity that = (PropertyStringValueEntity) obj;
return EqualsHelper.nullSafeEquals(this.stringValue, that.stringValue);
}
else
{
return false;
}
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder(512);
sb.append("PropertyStringValueEntity")
.append("[ ID=").append(id)
.append(", stringValue=").append(stringValue)
.append("]");
return sb.toString();
}
public Pair<Long, String> getEntityPair()
{
if (stringValue != null && stringValue.equals(PropertyStringValueEntity.EMPTY_STRING_REPLACEMENT))
{
return new Pair<Long, String>(id, PropertyStringValueEntity.EMPTY_STRING);
}
else
{
return new Pair<Long, String>(id, stringValue);
}
}
/**
* Set the string and string-end values
*/
public void setValue(String value)
{
if (value == null)
{
throw new IllegalArgumentException("Null strings cannot be persisted");
}
if (value != null && value.equals(PropertyStringValueEntity.EMPTY_STRING))
{
// Oracle: We can't insert empty strings into the column.
value = PropertyStringValueEntity.EMPTY_STRING_REPLACEMENT;
}
stringValue = value;
// Calculate the crc value from the original value
Pair<String, Long> crcPair = CrcHelper.getStringCrcPair(value, 16, false, true);
stringEndLower = crcPair.getFirst();
stringCrc = crcPair.getSecond();
}
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getStringValue()
{
return stringValue;
}
public void setStringValue(String stringValue)
{
this.stringValue = stringValue;
}
public String getStringEndLower()
{
return stringEndLower;
}
public void setStringEndLower(String stringEndLower)
{
this.stringEndLower = stringEndLower;
}
public Long getStringCrc()
{
return stringCrc;
}
public void setStringCrc(Long stringCrc)
{
this.stringCrc = stringCrc;
}
}

View File

@@ -36,7 +36,10 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import com.fasterxml.uuid.Generators;
import com.fasterxml.uuid.impl.UUIDUtil;
import org.alfresco.sync.events.types.ActivityEvent;
import org.alfresco.sync.events.types.Event;
import org.alfresco.model.ContentModel;
@@ -108,8 +111,6 @@ import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.joda.time.PeriodType;
import org.safehaus.uuid.UUID;
import org.safehaus.uuid.UUIDGenerator;
/**
* QuickShare Service implementation.
@@ -435,8 +436,8 @@ public class QuickShareServiceImpl implements QuickShareService,
// If it is retura dto built from the existing properties.
if (! nodeService.getAspects(nodeRef).contains(QuickShareModel.ASPECT_QSHARE))
{
UUID uuid = UUIDGenerator.getInstance().generateRandomBasedUUID();
sharedId = Base64.encodeBase64URLSafeString(uuid.toByteArray()); // => 22 chars (eg. q3bEKPeDQvmJYgt4hJxOjw)
UUID uuid = Generators.randomBasedGenerator().generate();
sharedId = Base64.encodeBase64URLSafeString(UUIDUtil.asByteArray(uuid)); // => 22 chars (eg. q3bEKPeDQvmJYgt4hJxOjw)
final Map<QName, Serializable> props = new HashMap<QName, Serializable>(2);
props.put(QuickShareModel.PROP_QSHARE_SHAREDID, sharedId);
@@ -1246,7 +1247,7 @@ public class QuickShareServiceImpl implements QuickShareService,
}
// Create the expiry action
final QuickShareLinkExpiryAction expiryAction = new QuickShareLinkExpiryActionImpl(java.util.UUID.randomUUID().toString(), sharedId,
final QuickShareLinkExpiryAction expiryAction = new QuickShareLinkExpiryActionImpl(UUID.randomUUID().toString(), sharedId,
"QuickShare link expiry action");
// Create the persisted schedule
final ScheduledPersistedAction schedule = scheduledPersistedActionService.createSchedule(expiryAction);

View File

@@ -0,0 +1,112 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2024 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.rendition2.script;
import java.util.List;
import org.alfresco.repo.jscript.BaseScopableProcessorExtension;
import org.alfresco.repo.jscript.ScriptNode;
import org.alfresco.repo.rendition2.RenditionService2;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* The {@code ScriptRenditionService2} class provides a scripting interface for working with Rendition Service 2.
* It allows rendering source nodes with specified rendition definitions and retrieving renditions associated with a node.
*/
@SuppressWarnings({"PMD.ProperLogger", "PMD.FieldNamingConventions"})
public class ScriptRenditionService2 extends BaseScopableProcessorExtension
{
private static final Log logger = LogFactory.getLog(ScriptRenditionService2.class);
private ServiceRegistry serviceRegistry;
private RenditionService2 renditionService;
/**
* Sets the {@link ServiceRegistry} to be used by this script object.
*
* @param serviceRegistry The ServiceRegistry to be set.
*/
public void setServiceRegistry(ServiceRegistry serviceRegistry)
{
this.serviceRegistry = serviceRegistry;
this.renditionService = serviceRegistry.getRenditionService2();
}
/**
* Renders the specified source node with the given rendition definition.
* Since renditionService2 is designed to asynchronous, no result is returned.
*
* @param sourceNode The source node to be rendered.
* @param renditionName The name of the rendition definition, like "pdf".
*/
public void render(ScriptNode sourceNode, String renditionName)
{
if (logger.isDebugEnabled())
{
String msg = "Rendering source node '" +
sourceNode +
"' with renditionDef '" + renditionName +
"'";
logger.debug(msg);
}
this.renditionService.render(sourceNode.getNodeRef(), renditionName);
}
/**
* Retrieves an array of {@link ScriptNode} objects representing renditions associated with the specified node.
*
* @param node The node for which to retrieve renditions.
* @return An array of {@code ScriptNode} objects representing renditions.
*/
public ScriptNode[] getRenditions(ScriptNode node)
{
List<ChildAssociationRef> renditions = this.renditionService.getRenditions(node.getNodeRef());
ScriptNode[] renditionObjs = new ScriptNode[renditions.size()];
for (int i = 0; i < renditions.size(); i++)
{
renditionObjs[i] = new ScriptNode(renditions.get(i).getChildRef(), serviceRegistry);
}
return renditionObjs;
}
/**
* Retrieves a {@link ScriptNode} object representing the rendition with the specified name associated with the given node.
*
* @param node The node for which to retrieve the rendition.
* @param renditionName The name of the rendition.
* @return A {@code ScriptNode} object representing the specified rendition, or {@code null} if not found.
*/
public ScriptNode getRenditionByName(ScriptNode node, String renditionName)
{
ChildAssociationRef result = this.renditionService.getRenditionByName(node.getNodeRef(), renditionName);
return result == null ? null : new ScriptNode(result.getChildRef(), serviceRegistry);
}
}

View File

@@ -36,7 +36,11 @@ import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import net.sf.acegisecurity.providers.dao.User;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.alfresco.service.cmr.security.PersonService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -49,12 +53,30 @@ public class AuthenticationContextImpl implements AuthenticationContext
private final Log logger = LogFactory.getLog(getClass());
private TenantService tenantService;
private PersonService personService;
private AuthenticationService authenticationService;
private Boolean allowImmutableEnabledUpdate;
public void setTenantService(TenantService tenantService)
{
this.tenantService = tenantService;
}
public void setPersonService(PersonService personService)
{
this.personService = personService;
}
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
public void setAllowImmutableEnabledUpdate(Boolean allowImmutableEnabledUpdate)
{
this.allowImmutableEnabledUpdate = allowImmutableEnabledUpdate;
}
/**
* Explicitly set the given validated user details to be authenticated.
*
@@ -70,7 +92,7 @@ public class AuthenticationContextImpl implements AuthenticationContext
{
// Apply the same validation that ACEGI would have to the user details - we may be going through a 'back
// door'.
if (!ud.isEnabled())
if (isDisabled(userId, ud))
{
throw new DisabledException("User is disabled");
}
@@ -114,6 +136,43 @@ public class AuthenticationContextImpl implements AuthenticationContext
}
}
private boolean isDisabled(String userId, UserDetails ud)
{
boolean isDisabled = !ud.isEnabled();
boolean isSystemUser = isSystemUserName(userId);
if (allowImmutableEnabledUpdate && !isSystemUser)
{
try
{
boolean isImmutable = isImmutableAuthority(userId);
boolean isPersonEnabled = personService.isEnabled(userId);
isDisabled = isDisabled || (isImmutable && !isPersonEnabled);
}
catch (Exception e)
{
if (logger.isWarnEnabled())
{
logger.warn("Failed to determine if person is enabled: " + userId + ", using user details status: " + isDisabled);
}
}
}
return isDisabled;
}
private boolean isImmutableAuthority(String authorityName)
{
return AuthenticationUtil.runAsSystem(new RunAsWork<Boolean>()
{
@Override public Boolean doWork() throws Exception
{
MutableAuthenticationService mutableAuthenticationService = (MutableAuthenticationService) authenticationService;
return !mutableAuthenticationService.isAuthenticationMutable(authorityName);
}
});
}
public Authentication setSystemUserAsCurrentUser()
{
return setSystemUserAsCurrentUser(TenantService.DEFAULT_DOMAIN);

View File

@@ -1,32 +1,33 @@
/*
* #%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 <http://www.gnu.org/licenses/>.
* #L%
*/
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2024 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.security.person;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.batch.BatchProcessor;
@@ -41,7 +42,6 @@ import org.springframework.extensions.surf.util.AbstractLifecycleBean;
import org.alfresco.util.GUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.safehaus.uuid.UUID;
import org.springframework.context.ApplicationEvent;
/**
@@ -168,7 +168,7 @@ public class SplitPersonCleanupBootstrapBean extends AbstractLifecycleBean
try
{
@SuppressWarnings("unused")
UUID id = new UUID(guidString);
UUID id = UUID.fromString(guidString);
// We have a valid guid.
return true;
}
@@ -188,7 +188,7 @@ public class SplitPersonCleanupBootstrapBean extends AbstractLifecycleBean
try
{
@SuppressWarnings("unused")
UUID id = new UUID(guidString);
UUID id = UUID.fromString(guidString);
// We have a valid guid.
return true;
}

View File

@@ -1,267 +1,299 @@
/*
* #%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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.service.cmr.audit;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* The public API by which applications can query the audit logs and enable or disable auditing.
*
* @author Derek Hulley
*/
public interface AuditService
{
/**
* @return Returns <tt>true</tt> if auditing is globally enabled
*
* @since 3.4
*/
boolean isAuditEnabled();
/**
* Enable or disable the global auditing state
*
* @param enable <tt>true</tt> to enable auditing globally or <tt>false</tt> to disable
*
* @since 3.4
*/
void setAuditEnabled(boolean enable);
/**
* Helper bean to carry information about an audit application.
*
* @author Derek Hulley
* @since 3.4
*/
public static class AuditApplication
{
private final String name;
private final String key;
private final boolean enabled;
/**
* Constructor for final variables
*/
public AuditApplication(String name, String key, boolean enabled)
{
this.name = name;
this.key = key;
this.enabled = enabled;
}
public String getName()
{
return name;
}
public String getKey()
{
return key;
}
public boolean isEnabled()
{
return enabled;
}
}
/**
* Get all registered audit applications
*
* @return Returns a map of audit applications keyed by their name
*
* @since 3.4
*/
Map<String, AuditApplication> getAuditApplications();
/**
* @param applicationName the name of the application to check
* @param path the path to check
* @return Returns <tt>true</tt> if auditing is enabled for the given path
*
* @since 3.2
*/
boolean isAuditEnabled(String applicationName, String path);
/**
* Enable auditing for an application path
*
* @param applicationName the name of the application to check
* @param path the path to enable
*
* @since 3.2
*/
void enableAudit(String applicationName, String path);
/**
* Disable auditing for an application path
*
* @param applicationName the name of the application to check
* @param path the path to disable
*
* @since 3.2
*/
void disableAudit(String applicationName, String path);
/**
* Remove all audit entries for the given application
*
* @param applicationName the name of the application for which to remove entries
* @return Returns the number of audit entries deleted
*
* @since 3.2
*
* @deprecated Use {@link #clearAudit(String, Long, Long)}
*/
int clearAudit(String applicationName);
/**
* Remove audit entries for the given application between the time ranges. If no start
* time is given then entries are deleted as far back as they exist. If no end time is
* given then entries are deleted up until the current time.
*
* @param applicationName the name of the application for which to remove entries
* @param fromTime the start time of entries to remove (inclusive and optional)
* @param toTime the end time of entries to remove (exclusive and optional)
* @return Returns the number of audit entries deleted
*
* @since 3.4
*/
int clearAudit(String applicationName, Long fromTime, Long toTime);
/**
* Remove audit entries for the given application between the audit entry ids.
*
* @param applicationName the name of the application for which to remove entries
* @param fromId the start time of entries to remove (inclusive and optional)
* @param toId the end time of entries to remove (exclusive and optional)
* @return Returns the number of audit entries deleted
*
* @since 5.2.2
*/
int clearAuditByIdRange(String applicationName, Long fromId, Long toId);
/**
* Delete a discrete list of audit entries.
* <p/>
* This method should not be called <i>while</i> processing
* {@link #auditQuery(AuditQueryCallback, AuditQueryParameters, int) query results}.
*
* @param auditEntryIds the IDs of all audit entries to delete
* @return Returns the number of audit entries deleted
*
* @since 3.4
*/
int clearAudit(List<Long> auditEntryIds);
/**
* The interface that will be used to give query results to the calling code.
*
* @since 3.2
*/
public static interface AuditQueryCallback
{
/**
* Determines whether this callback requires the values argument to be populated when {@link #handleAuditEntry}
* is called.
*
* @return <code>true</code> if this callback requires the values argument to be populated
*/
boolean valuesRequired();
/**
* Handle a row of audit entry data.
*
* @param entryId the unique audit entry ID
* @param applicationName the name of the application
* @param user the user that logged the entry
* @param time the time of the entry
* @param values the values map as created
* @return Return <tt>true</tt> to continue processing rows or <tt>false</tt> to stop
*/
boolean handleAuditEntry(
Long entryId,
String applicationName,
String user,
long time,
Map<String, Serializable> values);
/**
* Handle audit entry failures
*
* @param entryId the entry ID
* @param errorMsg the error message
* @param error the exception causing the error (may be <tt>null</tt>)
* @return Return <tt>true</tt> to continue processing rows or <tt>false</tt> to stop
*/
boolean handleAuditEntryError(Long entryId, String errorMsg, Throwable error);
}
/**
* Issue an audit query using the given parameters and consuming results in the callback.
* Results are returned in entry order, corresponding to time order.
*
* @param callback the callback that will handle results
* @param parameters the parameters for the query (may not be <tt>null</tt>)
* @param maxResults the maximum number of results to retrieve (must be greater than 0)
*
* @throws IllegalArgumentException if maxResults less or equal to zero
*
* @since 3.3
*/
void auditQuery(AuditQueryCallback callback, AuditQueryParameters parameters, int maxResults);
/**
* Issue an audit query to retrieve min / max audit record id for a given application.
*
* @param applicationName the name of the application
* @param extremes a list containing min/max or both
* @return a map containing min/max and the associated value
*/
HashMap<String, Long> getAuditMinMaxByApp(String applicationName, List<String> extremes);
/**
* Issue an audit query to retrieve min / max audit record id for a given application.
*
* @param applicationName the name of the application
* @return a map containing min/max and the associated value
*/
default int getAuditEntriesCountByApp(String applicationName)
{
return -1;
}
/**
* Issue an audit query to retrieve min / max audit record id for a given application and properties
*
* @param applicationName the name of the application
* @param parameters audit parameters provided by the <code>where</code> clause on the ReST API
* @return a map containing min/max and the associated value
*/
default int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
{
return -1;
}
}
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2024 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.service.cmr.audit;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* The public API by which applications can query the audit logs and enable or disable auditing.
*
* @author Derek Hulley
*/
public interface AuditService
{
/**
* @return Returns <tt>true</tt> if auditing is globally enabled
*
* @since 3.4
*/
boolean isAuditEnabled();
/**
* Enable or disable the global auditing state
*
* @param enable
* <tt>true</tt> to enable auditing globally or <tt>false</tt> to disable
*
* @since 3.4
*/
void setAuditEnabled(boolean enable);
/**
* Helper bean to carry information about an audit application.
*
* @author Derek Hulley
* @since 3.4
*/
public static class AuditApplication
{
private final String name;
private final String key;
private final boolean enabled;
/**
* Constructor for final variables
*/
public AuditApplication(String name, String key, boolean enabled)
{
this.name = name;
this.key = key;
this.enabled = enabled;
}
public String getName()
{
return name;
}
public String getKey()
{
return key;
}
public boolean isEnabled()
{
return enabled;
}
}
/**
* Get all registered audit applications
*
* @return Returns a map of audit applications keyed by their name
*
* @since 3.4
*/
Map<String, AuditApplication> getAuditApplications();
/**
* @param applicationName
* the name of the application to check
* @param path
* the path to check
* @return Returns <tt>true</tt> if auditing is enabled for the given path
*
* @since 3.2
*/
boolean isAuditEnabled(String applicationName, String path);
/**
* Enable auditing for an application path
*
* @param applicationName
* the name of the application to check
* @param path
* the path to enable
*
* @since 3.2
*/
void enableAudit(String applicationName, String path);
/**
* Disable auditing for an application path
*
* @param applicationName
* the name of the application to check
* @param path
* the path to disable
*
* @since 3.2
*/
void disableAudit(String applicationName, String path);
/**
* Remove all audit entries for the given application
*
* @param applicationName
* the name of the application for which to remove entries
* @return Returns the number of audit entries deleted
*
* @since 3.2
*
* @deprecated Use {@link #clearAudit(String, Long, Long)}
*/
int clearAudit(String applicationName);
/**
* Remove audit entries for the given application between the time ranges. If no start time is given then entries are deleted as far back as they exist. If no end time is given then entries are deleted up until the current time.
*
* @param applicationName
* the name of the application for which to remove entries
* @param fromTime
* the start time of entries to remove (inclusive and optional)
* @param toTime
* the end time of entries to remove (exclusive and optional)
* @return Returns the number of audit entries deleted
*
* @since 3.4
*/
int clearAudit(String applicationName, Long fromTime, Long toTime);
/**
* Remove audit entries for the given application between the audit entry ids.
*
* @param applicationName
* the name of the application for which to remove entries
* @param fromId
* the start time of entries to remove (inclusive and optional)
* @param toId
* the end time of entries to remove (exclusive and optional)
* @return Returns the number of audit entries deleted
*
* @since 5.2.2
*/
int clearAuditByIdRange(String applicationName, Long fromId, Long toId);
/**
* Delete a discrete list of audit entries.
* <p/>
* This method should not be called <i>while</i> processing {@link #auditQuery(AuditQueryCallback, AuditQueryParameters, int) query results}.
*
* @param auditEntryIds
* the IDs of all audit entries to delete
* @return Returns the number of audit entries deleted
*
* @since 3.4
*/
int clearAudit(List<Long> auditEntryIds);
/**
* The interface that will be used to give query results to the calling code.
*
* @since 3.2
*/
public static interface AuditQueryCallback
{
/**
* Determines whether this callback requires the values argument to be populated when {@link #handleAuditEntry} is called.
*
* @return <code>true</code> if this callback requires the values argument to be populated
*/
boolean valuesRequired();
/**
* Handle a row of audit entry data.
*
* @param entryId
* the unique audit entry ID
* @param applicationName
* the name of the application
* @param user
* the user that logged the entry
* @param time
* the time of the entry
* @param values
* the values map as created
* @return Return <tt>true</tt> to continue processing rows or <tt>false</tt> to stop
*/
boolean handleAuditEntry(
Long entryId,
String applicationName,
String user,
long time,
Map<String, Serializable> values);
/**
* Handle audit entry failures
*
* @param entryId
* the entry ID
* @param errorMsg
* the error message
* @param error
* the exception causing the error (may be <tt>null</tt>)
* @return Return <tt>true</tt> to continue processing rows or <tt>false</tt> to stop
*/
boolean handleAuditEntryError(Long entryId, String errorMsg, Throwable error);
}
/**
* Issue an audit query using the given parameters and consuming results in the callback. Results are returned in entry order, corresponding to time order.
*
* @param callback
* the callback that will handle results
* @param parameters
* the parameters for the query (may not be <tt>null</tt>)
* @param maxResults
* the maximum number of results to retrieve (must be greater than 0)
*
* @throws IllegalArgumentException
* if maxResults less or equal to zero
*
* @since 3.3
*/
void auditQuery(AuditQueryCallback callback, AuditQueryParameters parameters, int maxResults);
/**
* Issue an audit query to retrieve min / max audit record id for a given application.
*
* @param applicationName
* the name of the application
* @param extremes
* a list containing min/max or both
* @return a map containing min/max and the associated value
*/
HashMap<String, Long> getAuditMinMaxByApp(String applicationName, List<String> extremes);
/**
* Issue an audit query to retrieve min / max audit record id for a given application.
*
* @param applicationName
* the name of the application
* @return a map containing min/max and the associated value
*/
default int getAuditEntriesCountByApp(String applicationName)
{
return -1;
}
/**
* Issue an audit query to retrieve min / max audit record id for a given application and properties
*
* @param applicationName
* the name of the application
* @param parameters
* audit parameters provided by the <code>where</code> clause on the ReST API
* @return a map containing min/max and the associated value
*/
default int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
{
return -1;
}
}

View File

@@ -274,6 +274,15 @@
<property name="tenantService">
<ref bean="tenantService" />
</property>
<property name="personService">
<ref bean="personService" />
</property>
<property name="authenticationService">
<ref bean="AuthenticationService" />
</property>
<property name="allowImmutableEnabledUpdate">
<value>${allow.immutable.user.enabled.status.update}</value>
</property>
</bean>
<!-- Simple Authentication component that rejects all authentication requests -->

View File

@@ -1342,6 +1342,8 @@
</property>
</bean>
<bean id="search.suggesterService" class="org.alfresco.repo.search.impl.DummySuggesterServiceImpl">
</bean>
<!-- Custom property editors -->
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="propertyEditorRegistrars">

View File

@@ -782,6 +782,25 @@
<if test="ordered == true">order by node.id ASC</if>
</select>
<select id="select_NodesWithAspectIds_Limited" parameterType="Ids" resultMap="result_NodeRef" >
select
node.id as id,
store.protocol as protocol,
store.identifier as identifier,
node.uuid as uuid
from
alf_node_aspects na
join alf_node node on (na.node_id = node.id)
left join alf_store store on (store.id = node.store_id)
where
<![CDATA[na.node_id >= #{idOne}]]>
<if test="idTwo != null"><![CDATA[and na.node_id < #{idTwo}]]></if>
and na.qname_id in
<foreach item="item" index="i" collection="ids" open="(" separator="," close=")">#{item}</foreach>
<if test="ordered == true">order by node.id ASC</if>
<if test="maxResults != null"><![CDATA[limit #{maxResults}]]></if>
</select>
<!-- Common results for result_NodeAssoc -->
<sql id="select_NodeAssoc_Results">
select

View File

@@ -121,6 +121,8 @@
<property name="maxItemBatchSize" value="${system.fixedACLsUpdater.maxItemBatchSize}"/>
<property name="numThreads" value="${system.fixedACLsUpdater.numThreads}"/>
<property name="forceSharedACL" value="${system.fixedACLsUpdater.forceSharedACL}"/>
<property name="maxItems" value="${system.fixedACLsUpdater.maxItems}"/>
<property name="orderNodes" value="${system.fixedACLsUpdater.orderNodes}"/>
<property name="lockTimeToLive" value="${system.fixedACLsUpdater.lockTTL}"/>
<property name="policyComponent" ref="policyComponent"/>
<property name="policyIgnoreUtil" ref="policyIgnoreUtil"/>

View File

@@ -176,4 +176,11 @@
<!-- The definitions are read from json files (possibly added to a volume via k8 ConfigMaps) -->
</beans>
<!-- JavaScript API support -->
<bean id="renditionService2Script"
class="org.alfresco.repo.rendition2.script.ScriptRenditionService2"
parent="baseJavaScriptExtension">
<property name="extensionName" value="renditionService2" />
<property name="serviceRegistry" ref="ServiceRegistry" />
</bean>
</beans>

View File

@@ -435,6 +435,9 @@ repo.remote.endpoint=/service
# persisted.
create.missing.people=${server.transaction.allow-writes}
# Allow an immutable user to have its enabled status changed
allow.immutable.user.enabled.status.update=false
# Create home folders (unless disabled, see next property) as people are created (true) or create them lazily (false)
home.folder.creation.eager=true
# Disable home folder creation - if true then home folders are not created (neither eagerly nor lazily)
@@ -1104,7 +1107,11 @@ system.fixedACLsUpdater.numThreads=4
# fixedACLsUpdater - Force shared ACL to propagate through children even if there is an unexpected ACL
system.fixedACLsUpdater.forceSharedACL=false
# fixedACLsUpdater cron expression - fire at midnight every day
system.fixedACLsUpdater.cronExpression=0 0 0 * * ?
system.fixedACLsUpdater.cronExpression=0 0 0 * * ?
# fixedACLsUpdater - maximum number of pending ACLs to process overall
system.fixedACLsUpdater.maxItems=-1
# fixedACLsUpdater - Impose the order by in the query. If false, it may not process all the results but should do the queries faster
system.fixedACLsUpdater.orderNodes=true
cmis.disable.hidden.leading.period.files=false

View File

@@ -104,9 +104,9 @@ public class FixedAclUpdaterTest
private ContentService contentService;
private AuthorityService authorityService;
private static final long MAX_TRANSACTION_TIME_DEFAULT = 10;
private static final int LARGE_TRANSACTION_TIME = 86_400_000;
private static final int[] filesPerLevelMoreFolders = { 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
private static final int[] filesPerLevelMoreFiles = { 5, 100 };
private long maxTransactionTime;
private static HashMap<Integer, Class<?>> errors;
private static String TEST_GROUP_NAME = "FixedACLUpdaterTest";
private static String TEST_GROUP_NAME_FULL = PermissionService.GROUP_PREFIX + TEST_GROUP_NAME;
@@ -134,8 +134,11 @@ public class FixedAclUpdaterTest
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
homeFolderNodeRef = repository.getCompanyHome();
maxTransactionTime = MAX_TRANSACTION_TIME_DEFAULT;
setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, maxTransactionTime);
setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, MAX_TRANSACTION_TIME_DEFAULT);
fixedAclUpdater.setForceSharedACL(false);
fixedAclUpdater.setMaxItems(-1);
fixedAclUpdater.setOrderNodes(true);
}
@After
@@ -155,8 +158,7 @@ public class FixedAclUpdaterTest
try
{
maxTransactionTime = 86400000;
setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, maxTransactionTime);
setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, LARGE_TRANSACTION_TIME);
setPermissionsOnTree(folderRef, false, false);
aclComparator.compareACLs();
@@ -164,6 +166,7 @@ public class FixedAclUpdaterTest
}
finally
{
setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, MAX_TRANSACTION_TIME_DEFAULT);
deleteNodes(folderRef);
}
}
@@ -344,8 +347,7 @@ public class FixedAclUpdaterTest
try
{
maxTransactionTime = 86400000;
setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, maxTransactionTime);
setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, LARGE_TRANSACTION_TIME);
// Set permissions on target folder
txnHelper.doInTransaction((RetryingTransactionCallback<Void>) () -> {
@@ -386,6 +388,7 @@ public class FixedAclUpdaterTest
}
finally
{
setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, MAX_TRANSACTION_TIME_DEFAULT);
deleteNodes(originalRef);
deleteNodes(targetRefBase);
}
@@ -1438,6 +1441,79 @@ public class FixedAclUpdaterTest
}
}
/*
* Test with maxItems limit
*/
@Test
@RetryAtMost(3)
public void testWithLimits()
{
NodeRef folderRef = createFolderHierarchyInRootForFileTests("testWithLimitsFolder");
try
{
int maxItems = 200;
setPermissionsOnTree(folderRef, true, true);
// Get the current amount of pending ACls
int initialPendingAcls = getNodesCountWithPendingFixedAclAspect();
// We need at least maxItems+1 pending ACLs
while (initialPendingAcls <= maxItems && initialPendingAcls > 0)
{
// Trigger the job a single round each time to create new pendings until we have enough
triggerFixedACLJob(false,true,maxItems,1);
initialPendingAcls = getNodesCountWithPendingFixedAclAspect();
}
assertTrue("We don't have enough pending acls to test", initialPendingAcls > 0);
// Increase transaction time to not create new pending ACLs
setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, LARGE_TRANSACTION_TIME);
// Trigger job in single round without timeout
triggerFixedACLJob(false,true,maxItems,1);
int finalPendingAcls = getNodesCountWithPendingFixedAclAspect();
assertTrue("Processed ACLs should not have exceeded 200", (initialPendingAcls - finalPendingAcls) <= maxItems);
}
finally
{
setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, MAX_TRANSACTION_TIME_DEFAULT);
deleteNodes(folderRef);
}
}
/*
* Test without imposing the order by
*/
@Test
@RetryAtMost(3)
public void testUnordered()
{
NodeRef folderRef = createFolderHierarchyInRootForFileTests("testWithLimitsFolder");
try
{
setPermissionsOnTree(folderRef, true, true);
int initialPendingAcls = getNodesCountWithPendingFixedAclAspect();
assertTrue("We don't have enough pending acls to test", initialPendingAcls > 0);
triggerFixedACLJob(false,true,-1,30);
int finalPendingAcls = getNodesCountWithPendingFixedAclAspect();
assertEquals("Not all ACls were processed",0, finalPendingAcls);
}
finally
{
setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, MAX_TRANSACTION_TIME_DEFAULT);
deleteNodes(folderRef);
}
}
private Long getChild(Long parentId)
{
List<FileInfo> children = fileFolderService.list(nodeDAO.getNodePair(parentId).getSecond());
@@ -1601,13 +1677,18 @@ public class FixedAclUpdaterTest
private void triggerFixedACLJob()
{
triggerFixedACLJob(false);
// Trigger job 30 times max to process all nodes
triggerFixedACLJob(false, true, -1, 30);
}
private void triggerFixedACLJob(boolean forceSharedACL)
{
triggerFixedACLJob(forceSharedACL, true, -1, 30);
}
private void triggerFixedACLJob(boolean forceSharedACL, boolean orderNodes, int maxItems, int rounds)
{
LOG.debug("Fixing ACL");
final int rounds = 30;
final int enoughZeros = 3;
int numberOfConsecutiveZeros = 0;
@@ -1615,6 +1696,8 @@ public class FixedAclUpdaterTest
{
int count = txnHelper.doInTransaction(() -> {
fixedAclUpdater.setForceSharedACL(forceSharedACL);
fixedAclUpdater.setMaxItems(maxItems);
fixedAclUpdater.setOrderNodes(orderNodes);
return fixedAclUpdater.execute();
}, false, true);
numberOfConsecutiveZeros = count == 0 ? numberOfConsecutiveZeros + 1 : 0;

View File

@@ -37,7 +37,10 @@ import java.io.Serializable;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import com.fasterxml.uuid.Generators;
import com.fasterxml.uuid.impl.UUIDUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.model.QuickShareModel;
import org.alfresco.repo.model.Repository;
@@ -83,8 +86,6 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.RuleChain;
import org.safehaus.uuid.UUID;
import org.safehaus.uuid.UUIDGenerator;
import org.springframework.context.ApplicationContext;
/**
@@ -420,8 +421,8 @@ public class QuickShareServiceIntegrationTest
@Test(expected=InvalidSharedIdException.class) public void getMetadataFromShareIdWithInvalidId()
{
UUID uuid = UUIDGenerator.getInstance().generateRandomBasedUUID();
String sharedId = Base64.encodeBase64URLSafeString(uuid.toByteArray()); // => 22 chars (eg. q3bEKPeDQvmJYgt4hJxOjw)
UUID uuid = Generators.randomBasedGenerator().generate();
String sharedId = Base64.encodeBase64URLSafeString(UUIDUtil.asByteArray(uuid)); // => 22 chars (eg. q3bEKPeDQvmJYgt4hJxOjw)
Map<String, Object> metadata = quickShareService.getMetaData(sharedId);
}
@@ -884,7 +885,7 @@ public class QuickShareServiceIntegrationTest
{
// Create a private site
AuthenticationUtil.setFullyAuthenticatedUser(user1.getUsername());
String randomUUID = UUIDGenerator.getInstance().generateRandomBasedUUID().toString();
String randomUUID = Generators.randomBasedGenerator().generate().toString();
String siteName = "testSite" + randomUUID;
siteService.createSite("site-dashboard", siteName, "Title for " + siteName,
"Description for " + siteName, SiteVisibility.PRIVATE);

View File

@@ -59,7 +59,7 @@ services:
CLIENT_SSL_TRUST_STORE_TYPE: "JCEKS"
keycloak:
profiles: ["with-sso"]
image: quay.io/keycloak/keycloak:24.0.3
image: quay.io/keycloak/keycloak:25.0.6
environment:
- KEYCLOAK_ADMIN=admin
- KEYCLOAK_ADMIN_PASSWORD=admin

View File

@@ -0,0 +1,21 @@
#!/usr/bin/env bash
set +x
if [[ -z ${GITHUB_MODIFIED_FILES} ]]
then
modified_files=$(git diff --cached --name-only --diff-filter=ACMR)
else
modified_files=${GITHUB_MODIFIED_FILES}
fi
include_list=""
for file in ${modified_files}
do
include_list="${include_list},${file}"
done
include_list=${include_list:1}
mvn spotless:apply validate -DlicenseUpdateHeaders=true -Pags,all-tas-tests -Dspotless-include-list="${include_list}" > /dev/null || true
set -x