Compare commits

...

101 Commits
9.10 ... 10.14

Author SHA1 Message Date
Travis CI User
d1a10f4396 [maven-release-plugin][skip ci] prepare release 10.14 2022-08-22 12:21:43 +00:00
mikolajbrzezinski
9f3946e40c ACS-3316 Fix custom models downloading and XSS Backport (#1328)
* ACS-3316 Fix custom models downloading and XSS (#1304)

* Revert "Revert "ACS-3316 Fix HTML sanitisation bypass (#1266)" (#1294)"

This reverts commit 6c407b1ef5.

* ACS-3316 Set node name for download node

* ACS-3316 Update license

Co-authored-by: Damian.Ujma@hyland.com <Damian.Ujma@hyland.com>

(cherry picked from commit cc3f8aaff4)

* add non attach mimetypes
2022-08-22 12:07:44 +02:00
Travis CI User
1ec48de252 [maven-release-plugin][skip ci] prepare for next development iteration 2022-07-14 23:53:32 +00:00
Travis CI User
f14191cbf0 [maven-release-plugin][skip ci] prepare release 10.13 2022-07-14 23:53:29 +00:00
tiagosalvado10
f458a67562 [ACS-3271] Update MySQL 5.7.23 tests to 5.7.28 version (#1209) (#1219)
* ACS-3271 Update MySQL 5.7.23 tests to 5.7.28 version (#1209)

(cherry picked from commit 3990bc9db4)

Co-authored-by: Damian Ujma <92095156+damianujma@users.noreply.github.com>
2022-07-14 23:45:18 +01:00
Travis CI User
fdfade3f5b [maven-release-plugin][skip ci] prepare for next development iteration 2022-05-02 18:26:00 +00:00
Travis CI User
c6e12d0ef4 [maven-release-plugin][skip ci] prepare release 10.12 2022-05-02 18:25:57 +00:00
evasques
f791bb7a40 MNT-22968 - Bump Freemarker (#1096) 2022-05-02 18:03:18 +01:00
Travis CI User
8ba14902ec [maven-release-plugin][skip ci] prepare for next development iteration 2022-04-14 08:13:27 +00:00
Travis CI User
2299c5fb92 [maven-release-plugin][skip ci] prepare release 10.11 2022-04-14 08:13:25 +00:00
Vítor Moreira
4ab84ff819 Fix/mnt 22946 spring rce databind jdk9 70 n (#1058)
* Bump dependency.webscripts.version from 8.28 to 8.29 (#1052)

(cherry picked from commit 22a0343c41)

* MNT-22946: bump spring version to 5.3.18 (#1054)

(cherry picked from commit 53777cd5b9)

* MNT-22946: implemented empty new methods from springframework

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-13 23:49:44 +01:00
Travis CI User
7eb0a2bce1 [maven-release-plugin][skip ci] prepare for next development iteration 2022-04-12 21:42:17 +00:00
Travis CI User
89f90d80a0 [maven-release-plugin][skip ci] prepare release 10.10 2022-04-12 21:42:15 +00:00
Vítor Moreira
a452a52e71 ACS-1970 Switch to the alfresco/alfresco-base-tomcat:9.0.52-java-11-centos-7 base image (#693) (#1065)
(cherry picked from commit 507c6b2ed8)

Co-authored-by: Piotr Żurek <Piotr.Zurek@hyland.com>
2022-04-12 19:45:48 +01:00
Travis CI User
456198467a [maven-release-plugin][skip ci] prepare for next development iteration 2021-08-31 15:19:39 +00:00
Travis CI User
2b2646097c [maven-release-plugin][skip ci] prepare release 10.9 2021-08-31 15:19:36 +00:00
alandavis
070f727495 "ACS-1907/MNT-22536 TMDQ against MySql throws SQLException in certain situations (#679)"
(cherry picked from commit bb58c4a2d9)

Also include travis changes to make it easier to skip repo, tas, db and also use latest db
2021-08-31 15:29:25 +01:00
Travis CI User
fc3ab90f6f [maven-release-plugin][skip ci] prepare for next development iteration 2021-08-30 12:13:48 +00:00
Travis CI User
9272373d0f [maven-release-plugin][skip ci] prepare release 10.8 2021-08-30 12:13:44 +00:00
antoniojfelix
3b7ee1c4a3 PRODSEC-5480 - Bump jsoup version from 1.13.1 to 1.14.2 (#685)
(cherry picked from commit 411f13d831)
2021-08-30 12:22:02 +01:00
Stefan Kopf
5fecd6f75c Add missing 3rd party license files
(cherry picked from commit 6b4df496ce)
2021-08-19 19:02:30 +02:00
Travis CI User
5d108bd4ad [maven-release-plugin][skip ci] prepare for next development iteration 2021-08-13 08:31:47 +00:00
Travis CI User
742715f738 [maven-release-plugin][skip ci] prepare release 10.7 2021-08-13 08:31:45 +00:00
tiagosalvado10
8bf474941f [PRODSEC-5254] Bump commons-compress to 1.21 (#658) (#659)
(cherry picked from commit 3530e3dc3b)
2021-08-12 22:07:21 +01:00
Travis CI User
5bd83fff0e [maven-release-plugin][skip ci] prepare for next development iteration 2021-08-04 18:18:36 +00:00
Travis CI User
3b2e81b6b7 [maven-release-plugin][skip ci] prepare release 10.6 2021-08-04 18:18:31 +00:00
evasques
124d8e5277 PRODSEC-4421 - Bump surf-webscripts to 8.22 (#647) 2021-08-04 18:50:10 +01:00
Travis CI User
1d28d28623 [maven-release-plugin][skip ci] prepare for next development iteration 2021-08-04 12:14:15 +00:00
Travis CI User
be580313ef [maven-release-plugin][skip ci] prepare release 10.5 2021-08-04 12:14:11 +00:00
evasques
cff3408f27 PRODSEC-4422 - Scripts not in Data Dictionary can be executed by action (#596) (#643)
Added validation to the ScriptActionExecuter class to enforce the existing constraints on parameter script-ref (Repo has the constraint to only allow scripts in Data Dictionary / Scripts and AGS has the constraint to only allow scripts in Data Dictionary / Records Management / Records Management Scripts") by validating if the given scriptRef is in the allowed valued of the constraint set on that param
* Moved test testActionResult from ActionServiceImplTest to class ActionServiceImpl2Test - Before it ran with a script not in Data Dictionary so with the added validation it started to fail. I moved the unit test do avoid duplicating the code to create the script in the correct location.

(cherry picked from commit ac4a1643e1)
2021-08-04 12:26:53 +01:00
Travis CI User
8a6c64c4b8 [maven-release-plugin][skip ci] prepare for next development iteration 2021-07-19 13:49:58 +00:00
Travis CI User
38cb0aba92 [maven-release-plugin][skip ci] prepare release 10.4 2021-07-19 13:49:52 +00:00
Abdul Mohammed
56d6957935 Add friendly name to scheduled jobs that are currently showing class names (#603) 2021-07-19 13:56:15 +01:00
Travis CI User
84d9916788 [maven-release-plugin][skip ci] prepare for next development iteration 2021-07-15 10:17:34 +00:00
Travis CI User
22ef4441f3 [maven-release-plugin][skip ci] prepare release 10.3 2021-07-15 10:17:28 +00:00
alandavis
2f77c8b304 Correct the <acs.version.revision> so the acs version is seen as 7.0.2
[skip tests][no downstream]
2021-07-15 11:09:50 +01:00
Travis CI User
e34165b72e [maven-release-plugin][skip ci] prepare for next development iteration 2021-07-15 08:34:20 +00:00
Travis CI User
f7f4f70990 [maven-release-plugin][skip ci] prepare release 10.2 2021-07-15 08:34:14 +00:00
Davide
e293976b58 SEARCH-2878 Update the supported for SearchService (#587) 2021-07-15 09:44:31 +02:00
Travis CI User
747f2c8919 [maven-release-plugin][skip ci] prepare for next development iteration 2021-07-14 16:37:14 +00:00
Travis CI User
f445646045 [maven-release-plugin][skip ci] prepare release 10.1 2021-07-14 16:37:08 +00:00
alandavis
1e02870774 Use branch for ACS 7.0.2 (version.schema=14200 and pom version = 10.x) 2021-07-14 16:50:50 +01:00
Travis CI User
9cb2b23ef5 [maven-release-plugin][skip ci] prepare for next development iteration 2021-07-09 23:02:38 +00:00
Travis CI User
7db90ee90c [maven-release-plugin][skip ci] prepare release 9.28 2021-07-09 23:02:33 +00:00
Davide
9d0106e000 SEARCH-2878 Update the supported for SearchService to 2.0.2-RC2 (#588) 2021-07-09 22:13:07 +01:00
Travis CI User
26c991a563 [maven-release-plugin][skip ci] prepare for next development iteration 2021-07-09 16:48:11 +00:00
Travis CI User
ddfabba4ba [maven-release-plugin][skip ci] prepare release 9.27 2021-07-09 16:48:05 +00:00
Jamal Kaabi-Mofrad
ab7d757412 AUTH-532: Upgrade Keycloak client to match IDS-1.5.0 2021-07-09 16:50:24 +01:00
Travis CI User
fe028f5b85 [maven-release-plugin][skip ci] prepare for next development iteration 2021-07-09 11:45:43 +00:00
Travis CI User
2baf1b9c91 [maven-release-plugin][skip ci] prepare release 9.26 2021-07-09 11:45:38 +00:00
tiagosalvado10
3818f94268 ACS-1734 Remove libreofficeToPdf + libreofficeToPdfBoxViaPdf (#577)
* ACS-1734 Remove broken transformerFailover from libreofficeToPdf (#572)

(cherry picked from commit 0d09a048da)

* ACS-1734 Remove libreofficeToPdf + Update libreofficeToPdfBoxViaPdf (#573)

(cherry picked from commit 38d66b69bb)

Co-authored-by: David Edwards <david.edwards@alfresco.com>
2021-07-08 13:11:41 +01:00
Travis CI User
53b41068d4 [maven-release-plugin][skip ci] prepare for next development iteration 2021-07-06 10:30:20 +00:00
Travis CI User
c302bc31ff [maven-release-plugin][skip ci] prepare release 9.25 2021-07-06 10:30:14 +00:00
Tom Page
9a30044064 SEARCH-2909 Return Http Status Code 501 (Not Implemented) in REST API… (#519) (#561)
* SEARCH-2909 Return Http Status Code 501 (Not Implemented) in REST API for invocations to Search Services that are not supported.

* SEARCH-2909 Refactor exception mapping to simplify QueryParserException.

* SEARCH-2909 Add unit tests for postQuery.

This includes a test for the status code replacement with unsupported operations.

* SEARCH-2909 Add new unit test file to test suite.

Also add copyright header to test class.

Co-authored-by: Tom Page <thomas.page@alfresco.com>
(cherry picked from commit f1a5425f62)

Co-authored-by: Angel Borroy <48685308+aborroy@users.noreply.github.com>
2021-07-06 09:37:55 +01:00
Travis CI User
41edced9f1 [maven-release-plugin][skip ci] prepare for next development iteration 2021-06-29 11:40:14 +00:00
Travis CI User
15ca9e21be [maven-release-plugin][skip ci] prepare release 9.24 2021-06-29 11:40:09 +00:00
alandavis
36bf6d2f81 Bump camel-amqp 3.7.1 to 3.7.4 and netty 4.1.58.Final to 4.1.60.Final #567
(cherry picked from commit acb155739a)
2021-06-29 10:11:18 +01:00
Travis CI User
cf01f167ae [maven-release-plugin][skip ci] prepare for next development iteration 2021-06-26 07:30:30 +00:00
Travis CI User
4c94059bbf [maven-release-plugin][skip ci] prepare release 9.23 2021-06-26 07:30:25 +00:00
Alex Mukha
5efe11008d SEARCH-2876 Update Solr 2.0.2-RC1 (#564) 2021-06-26 01:40:06 +01:00
Travis CI User
3225eefd0b [maven-release-plugin][skip ci] prepare for next development iteration 2021-06-25 20:22:19 +00:00
Travis CI User
b6de89aa8d [maven-release-plugin][skip ci] prepare release 9.22 2021-06-25 20:22:14 +00:00
alandavis
4cc1c10ce5 MNT-21902 minor fixes to logic added in REPO-5549
(cherry picked from commit 0445ba9c93)
2021-06-25 18:38:11 +01:00
Travis CI User
7641c128c5 [maven-release-plugin][skip ci] prepare for next development iteration 2021-06-25 13:08:07 +00:00
Travis CI User
a62ad8715e [maven-release-plugin][skip ci] prepare release 9.21 2021-06-25 13:08:00 +00:00
tiagosalvado10
542f189907 [MNT-21611] Removed HTML transformation pipelines (with LibreOffice). Added new HTML pipelines via TEXT (#391) (#553)
(cherry picked from commit a8959b98c1)
2021-06-24 15:35:57 +01:00
Travis CI User
a006b5acaf [maven-release-plugin][skip ci] prepare for next development iteration 2021-06-21 19:46:34 +00:00
Travis CI User
c2e516b69a [maven-release-plugin][skip ci] prepare release 9.20 2021-06-21 19:46:28 +00:00
evasques
2c5044896b MNT-21837 - License expires 23h earlier - correction (#544) (#547)
* period.getMillis() (joda lib) returns an int instead of a long, so on larger periods (like 30days) we get an error that the value cannot fit in an int
* Changed the validation to only calculate the remaining milliseconds in the edge case of the remaining days being zero (as both 23h before and 23h after correspond to 0 remaining days)
* Added a unit test that validates the usage 60 days up from the licence expiring to validate the problem stops occurring
* Added a unit test that validates the usage 30 days after the licence expiring to cover all use cases

(cherry picked from commit 6e1d25a8f0)
2021-06-21 17:11:34 +01:00
Alan Davis
24454afe6b MNT-22388 [Security] multiple pdfbox vulnerabilities (Repo) (#539) (#548)
* Remove pdfbox jars as they should no longer be needed.
* Reintroduce tests that use Tika to 'guess' mimetypes as it was the tika parse that was pulling in the pdfbox libraries.

Classes that use Tika:
* HTMLRenderingEngine - removed as it is no longer used
* RemoteConnectorResponseImpl - called tika utility toByteArray so not using pdfbox
* TikaCharsetFinder - called to identify the charset not mimetype so not using pdfbox
* MimetypeMap - main use of Tika. Used to detect mimetypes. Might have been using pdfbox.

Cherry pick from master (7.1.0)
2021-06-21 16:42:33 +01:00
Travis CI User
aec55ed8a6 [maven-release-plugin][skip ci] prepare for next development iteration 2021-06-18 15:32:20 +00:00
Travis CI User
ddd5a4ae48 [maven-release-plugin][skip ci] prepare release 9.19 2021-06-18 15:32:15 +00:00
evasques
e523245a10 MNT-21837 License expires 23h earlier (#541) (#543)
* MNT-21837 - License expires 23h earlier
* Original problem is that the remaining time to license expires is calculated in days (long, not double) and anything less then 24h computes to 0 days. The validation for license being valid is that the remaining days is more than zero.
* Added method calculateMs in DateUtil class to return the interval in ms considering 2 given dates and respective timezones
* Changed the validation to use the remaining milliseconds value instead of remaining days
* Added unit test where license expires 6 hours from now - repo is not supposed to enter read-only mode
* Added unit test where license expired 1 minute ago - repo is supposed to enter read-only mode

* Removed unused import

(cherry picked from commit 630cd99067)
2021-06-18 15:34:35 +01:00
Travis CI User
c4217b32fb [maven-release-plugin][skip ci] prepare for next development iteration 2021-06-17 17:23:28 +00:00
Travis CI User
2fbd21076f [maven-release-plugin][skip ci] prepare release 9.18 2021-06-17 17:23:22 +00:00
alandavis
cb1419b140 Use alfresco/alfresco-base-tomcat:9.0.45-java-11-centos-8 2021-06-17 17:51:42 +01:00
Travis CI User
9a6c6f2ee9 [maven-release-plugin][skip ci] prepare for next development iteration 2021-06-17 11:30:48 +00:00
Travis CI User
eaff930456 [maven-release-plugin][skip ci] prepare release 9.17 2021-06-17 11:30:42 +00:00
evasques
4a03e8cc98 MNT-20500 - Admin console breaks with serialised objects (#538)
* MNT-20500 - Admin console breaks with serialised objects (#291)

* Added macro convertToJSON to recursively parse hashes and enumerables
* Added attempt/recover in macros to handle errors and not break the page
* Changed the output of serialized objects to JSON format

(cherry picked from commit ce62fb1da3)

* MNT-20500 - Admin console breaks with serialised objects (#536)

* In node browser:
** Added macro convertToJSON to recursively parse hashes and enumerables
** Added attempt/recover in macros to handle errors and not break the page
** Changed the output of serialized objects to JSON format
* In both admin console and node browser:
** Adjusted consistency of the ouput when an error occurs
** Validate the depth of each hash. When we find a hash with over 1000 elements, we throw an error instead of displaying the object. Used the stop tag to effectively force an abort of the template processing preventing performance or security issues regarding very large objects.

(cherry picked from commit d7ec130756)
2021-06-17 12:00:17 +01:00
Travis CI User
0eaeea35f8 [maven-release-plugin][skip ci] prepare for next development iteration 2021-06-11 16:08:16 +00:00
Travis CI User
f4c632c26b [maven-release-plugin][skip ci] prepare release 9.16 2021-06-11 16:08:11 +00:00
alandavis
3c96ed9482 Bump woodstox-core from 6.2.5 to 6.2.6 (#393)
(cherry picked from commit fdfb7d170d)
2021-06-11 16:34:19 +01:00
Travis CI User
0141284b37 [maven-release-plugin][skip ci] prepare for next development iteration 2021-06-10 19:56:14 +00:00
Travis CI User
2c8ed7f4b5 [maven-release-plugin][skip ci] prepare release 9.15 2021-06-10 19:56:09 +00:00
alandavis
decbe6b285 dependabot changes from master plus tidyup 2021-06-10 17:44:25 +01:00
alandavis
f0f538bad0 ACS-1520 : Upgrade trashcan-cleaner
(cherry picked from commit fe64c8cc60)
[skip ci]
2021-06-10 17:16:46 +01:00
alandavis
c0aaf75284 ATS-912: Bump to T-Core 2.4.0 (#441)
(cherry picked from commit 6f35fddab7)
[skip ci]
2021-06-10 17:13:33 +01:00
Travis CI User
7f5889474e [maven-release-plugin][skip ci] prepare for next development iteration 2021-06-07 14:55:20 +00:00
Travis CI User
11c6125760 [maven-release-plugin][skip ci] prepare release 9.14 2021-06-07 14:55:14 +00:00
cturlica
ba4effc6ec Merge remote-tracking branch 'origin/release/7.0.N' into release/7.0.N 2021-06-07 17:16:07 +03:00
cturlica
3f52aec2dc MNT-22186: propTablesCleanupJobDetail v2 can cause Out of Memory
Cherry-picked f201f35 b7828c0 from master to release/7.0.N
2021-06-07 17:13:13 +03:00
Travis CI User
eb3df043be [maven-release-plugin][skip ci] prepare for next development iteration 2021-06-07 11:38:58 +00:00
Travis CI User
c5aed167f4 [maven-release-plugin][skip ci] prepare release 9.13 2021-06-07 11:38:52 +00:00
cturlica
a477c19e9a ACS-1648: update dejavu-fonts version from 2.35-6.el8 to 2.35-7.el8 2021-06-07 14:10:20 +03:00
Travis CI User
1497362d3e [maven-release-plugin][skip ci] prepare for next development iteration 2021-06-02 14:38:23 +00:00
Travis CI User
27e2775e40 [maven-release-plugin][skip ci] prepare release 9.12 2021-06-02 14:38:18 +00:00
dependabot-preview[bot]
f2ecce0f46 Bump dependency.tika.version from 1.25 to 1.26 (#366) 2021-06-02 15:05:22 +01:00
Travis CI User
0ad54cbf77 [maven-release-plugin][skip ci] prepare for next development iteration 2021-05-28 11:50:12 +00:00
Travis CI User
3e3cd479c2 [maven-release-plugin][skip ci] prepare release 9.11 2021-05-28 11:50:08 +00:00
Nana Insaidoo
b9b41a10e8 MNT-22385 Cmis query GetTotalNumItems is returning wrong value (#504)
* Changes made to correct the value of totalItems when performing a TMDQ

* Fixes after review

- Slight change was made to NodePermissionAssessor to log when permission
  limits are exceeded

* Now pre-computing maxPermissionChecks value as per review suggestion

(cherry picked from commit cb636d1140)
2021-05-28 11:01:25 +01:00
Travis CI User
664d0b9704 [maven-release-plugin][skip ci] prepare for next development iteration 2021-05-25 09:32:12 +00:00
72 changed files with 2719 additions and 2180 deletions

View File

@@ -46,38 +46,44 @@ jobs:
include:
- name: "Core, Data-Model, Repository - AllUnitTestsSuite - Build and test"
if: commit_message !~ /\[skip repo\]/
script:
- travis_retry mvn -B test -pl core,data-model
- travis_retry mvn -B test -pl repository -Dtest=AllUnitTestsSuite
- name: "Repository - AppContext01TestSuite"
if: commit_message !~ /\[skip repo\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.1 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.10
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.4.0
script: travis_wait 20 mvn -B test -pl repository -Dtest=AppContext01TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - AppContext02TestSuite"
if: commit_message !~ /\[skip repo\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.1 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
script: travis_wait 20 mvn -B test -pl repository -Dtest=AppContext02TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - AppContext03TestSuite"
if: commit_message !~ /\[skip repo\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.1 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.10
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.4.0
script: travis_wait 20 mvn -B test -pl repository -Dtest=AppContext03TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - AppContext04TestSuite"
if: commit_message !~ /\[skip repo\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.1 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.10
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.4.0
script: travis_wait 20 mvn -B test -pl repository -Dtest=AppContext04TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - AppContext05TestSuite"
if: commit_message !~ /\[skip repo\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.1 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
@@ -88,130 +94,141 @@ jobs:
script: travis_wait 20 mvn -B test -pl repository -Dtest=AppContext05TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco "-Didentity-service.auth-server-url=http://${HOST_IP}:8999/auth"
- name: "Repository - AppContext06TestSuite"
if: commit_message !~ /\[skip repo\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.1 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.10
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.4.0
script: travis_wait 20 mvn -B test -pl repository -Dtest=AppContext06TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - AppContextExtraTestSuite"
if: commit_message !~ /\[skip repo\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.1 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.10
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.4.0
script: travis_wait 20 mvn -B test -pl repository -Dtest=AppContextExtraTestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - MiscContextTestSuite"
if: commit_message !~ /\[skip repo\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.1 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.10
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.4.0
script: travis_wait 20 mvn -B test -pl repository -Dtest=MiscContextTestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - SearchTestSuite"
if: commit_message !~ /\[skip repo\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.1 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
script: travis_wait 20 mvn -B test -pl repository -Dtest=SearchTestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco -Dindex.subsystem.name=solr6
- name: "Repository - MariaDB 10.2.18 tests"
if: commit_message !~ /\[skip db\]/
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/
before_script:
- docker run -d -p 3307:3306 --name mariadb -e MYSQL_ROOT_PASSWORD=alfresco -e MYSQL_USER=alfresco -e MYSQL_DATABASE=alfresco -e MYSQL_PASSWORD=alfresco mariadb:10.2.18 --transaction-isolation=READ-COMMITTED --max-connections=300 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
script: travis_wait 20 mvn -B test -pl repository -Dtest=AllDBTestsTestSuite -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
- name: "Repository - MariaDB 10.4 tests"
if: commit_message !~ /\[skip db\]/
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/
before_script:
- docker run -d -p 3307:3306 --name mariadb -e MYSQL_ROOT_PASSWORD=alfresco -e MYSQL_USER=alfresco -e MYSQL_DATABASE=alfresco -e MYSQL_PASSWORD=alfresco mariadb:10.4 --transaction-isolation=READ-COMMITTED --max-connections=300 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
script: travis_wait 20 mvn -B test -pl repository -Dtest=AllDBTestsTestSuite -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
- name: "Repository - MariaDB 10.5 tests"
if: commit_message !~ /\[skip db\]/
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/ OR commit_message =~ /\[latest db\]/
before_script:
- docker run -d -p 3307:3306 --name mariadb -e MYSQL_ROOT_PASSWORD=alfresco -e MYSQL_USER=alfresco -e MYSQL_DATABASE=alfresco -e MYSQL_PASSWORD=alfresco mariadb:10.5 --transaction-isolation=READ-COMMITTED --max-connections=300 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
script: travis_wait 20 mvn -B test -pl repository -Dtest=AllDBTestsTestSuite -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
- name: "Repository - MySQL 5.7.23 tests"
if: commit_message !~ /\[skip db\]/
- name: "Repository - MySQL 5.7.28 tests"
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/
before_script:
- docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=alfresco -e MYSQL_USER=alfresco -e MYSQL_DATABASE=alfresco -e MYSQL_PASSWORD=alfresco mysql:5.7.23 --transaction-isolation='READ-COMMITTED'
- docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=alfresco -e MYSQL_USER=alfresco -e MYSQL_DATABASE=alfresco -e MYSQL_PASSWORD=alfresco mysql:5.7.28 --transaction-isolation='READ-COMMITTED'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
script: travis_wait 20 mvn -B test -pl repository -Dtest=AllDBTestsTestSuite -Ddb.driver=com.mysql.jdbc.Driver -Ddb.name=alfresco -Ddb.url=jdbc:mysql://localhost:3307/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - MySQL 8 tests"
if: commit_message !~ /\[skip db\]/
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/ OR commit_message =~ /\[latest db\]/
before_script:
- docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=alfresco -e MYSQL_USER=alfresco -e MYSQL_DATABASE=alfresco -e MYSQL_PASSWORD=alfresco mysql:8 --transaction-isolation='READ-COMMITTED'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
script: travis_wait 20 mvn -B test -pl repository -Dtest=AllDBTestsTestSuite -Ddb.driver=com.mysql.jdbc.Driver -Ddb.name=alfresco -Ddb.url=jdbc:mysql://localhost:3307/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - PostgreSQL 10.9 tests"
if: commit_message !~ /\[skip db\]/
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:10.9 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
script: travis_wait 20 mvn -B test -pl repository -Dtest=AllDBTestsTestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - PostgreSQL 11.7 tests"
if: commit_message !~ /\[skip db\]/
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.7 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
script: travis_wait 20 mvn -B test -pl repository -Dtest=AllDBTestsTestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - PostgreSQL 12.4 tests"
if: commit_message !~ /\[skip db\]/
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:12.4 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
script: travis_wait 20 mvn -B test -pl repository -Dtest=AllDBTestsTestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - PostgreSQL 13.1 tests"
if: commit_message !~ /\[skip db\]/
# We only run DB tests on the latest version of PostgreSQL on feature branches
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.1 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
script: travis_wait 20 mvn -B test -pl repository -Dtest=AllDBTestsTestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Remote-api - AppContext01TestSuite"
if: commit_message !~ /\[skip repo\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.1 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
script: travis_wait 20 mvn -B test -pl remote-api -Dtest=AppContext01TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Remote-api - AppContext02TestSuite"
if: commit_message !~ /\[skip repo\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.1 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.10
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.4.0
script: travis_wait 20 mvn -B test -pl remote-api -Dtest=AppContext02TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Remote-api - AppContext03TestSuite"
if: commit_message !~ /\[skip repo\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.1 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.10
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.4.0
script: travis_wait 20 mvn -B test -pl remote-api -Dtest=AppContext03TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Remote-api - AppContext04TestSuite"
if: commit_message !~ /\[skip repo\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.1 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.10
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.4.0
script: travis_wait 20 mvn -B test -pl remote-api -Dtest=AppContext04TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Remote-api - AppContextExtraTestSuite"
if: commit_message !~ /\[skip repo\]/
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.1 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
script: travis_wait 20 mvn -B test -pl remote-api -Dtest=AppContextExtraTestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "REST API TAS tests part1"
if: branch = master OR commit_message =~ /\[tas\]/
# TAS tests are generally skipped on feature branches as they will be repeated on the enterprise repo or community packaging builds
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
before_script:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
@@ -219,7 +236,7 @@ jobs:
- travis_wait 60 mvn -B install -f packaging/tests/tas-restapi/pom.xml -Pall-tas-tests,run-restapi-part1 -Denvironment=default -DrunBugs=false
- name: "REST API TAS tests part2"
if: branch = master OR commit_message =~ /\[tas\]/
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
before_script:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
@@ -227,7 +244,7 @@ jobs:
- travis_wait 60 mvn -B install -f packaging/tests/tas-restapi/pom.xml -Pall-tas-tests,run-restapi-part2 -Denvironment=default -DrunBugs=false
- name: "REST API TAS tests part3"
if: branch = master OR commit_message =~ /\[tas\]/
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
before_script:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
@@ -235,7 +252,7 @@ jobs:
- travis_wait 60 mvn -B install -f packaging/tests/tas-restapi/pom.xml -Pall-tas-tests,run-restapi-part3 -Denvironment=default -DrunBugs=false
- name: "CMIS TAS tests - BROWSER binding"
if: branch = master OR commit_message =~ /\[tas\]/
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
before_script:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
@@ -243,7 +260,7 @@ jobs:
- travis_wait 40 mvn -B install -f packaging/tests/tas-cmis/pom.xml -Pall-tas-tests,run-cmis-browser -Denvironment=default -DrunBugs=false
- name: "CMIS TAS tests - ATOM binding"
if: branch = master OR commit_message =~ /\[tas\]/
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
before_script:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
@@ -251,7 +268,7 @@ jobs:
- travis_wait 40 mvn -B install -f packaging/tests/tas-cmis/pom.xml -Pall-tas-tests,run-cmis-atom -Denvironment=default -DrunBugs=false
- name: "CMIS TAS tests - WEBSERVICES binding"
if: branch = master OR commit_message =~ /\[tas\]/
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
before_script:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
@@ -259,7 +276,7 @@ jobs:
- travis_wait 40 mvn -B install -f packaging/tests/tas-cmis/pom.xml -Pall-tas-tests,run-cmis-webservices -Denvironment=default -DrunBugs=false
- name: "Email TAS tests"
if: branch = master OR commit_message =~ /\[tas\]/
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
before_script:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
@@ -267,7 +284,7 @@ jobs:
- travis_wait 30 mvn -B install -f packaging/tests/tas-email/pom.xml -Pall-tas-tests -Denvironment=default -DrunBugs=false
- name: "WebDAV TAS tests"
if: branch = master OR commit_message =~ /\[tas\]/
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
before_script:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
@@ -275,7 +292,7 @@ jobs:
- travis_wait 30 mvn -B install -f packaging/tests/tas-webdav/pom.xml -Pall-tas-tests -Denvironment=default -DrunBugs=false
- name: "Integration TAS tests"
if: branch = master OR commit_message =~ /\[tas\]/
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
before_script:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>9.10</version>
<version>10.14</version>
</parent>
<dependencies>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>9.10</version>
<version>10.14</version>
</parent>
<properties>
@@ -167,7 +167,7 @@
<dependency>
<groupId>com.fasterxml.woodstox</groupId>
<artifactId>woodstox-core</artifactId>
<version>6.2.4</version>
<version>6.2.6</version>
</dependency>
<!-- the cxf libs were updated, see dependencyManagement section -->
@@ -283,6 +283,31 @@
<groupId>com.sun.activation</groupId>
<artifactId>javax.activation</artifactId>
</exclusion>
<!-- No longer needed -->
<exclusion>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-tools</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.pdfbox</groupId>
<artifactId>preflight</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.pdfbox</groupId>
<artifactId>jempbox</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.pdfbox</groupId>
<artifactId>xmpbox</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.pdfbox</groupId>
<artifactId>jbig2-imageio</artifactId>
</exclusion>
</exclusions>
</dependency>

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of

View File

@@ -60,12 +60,15 @@ public abstract class ConfigScheduler<Data>
// Synchronized has little effect in normal operation, but on laptops that are suspended, there can be a number
// of Threads calling execute concurrently without it, resulting in errors in the log. Theoretically possible in
// production but not very likely.
public synchronized void execute(JobExecutionContext context) throws JobExecutionException
public void execute(JobExecutionContext context) throws JobExecutionException
{
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
ConfigScheduler configScheduler = (ConfigScheduler)dataMap.get(CONFIG_SCHEDULER);
boolean successReadingConfig = configScheduler.readConfigAndReplace(true);
configScheduler.changeScheduleOnStateChange(successReadingConfig);
synchronized (configScheduler)
{
boolean successReadingConfig = configScheduler.readConfigAndReplace(true);
configScheduler.changeScheduleOnStateChange(successReadingConfig);
}
}
}

View File

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

View File

@@ -0,0 +1,54 @@
/*--
Copyright (C) 2000-2012 Jason Hunter & Brett McLaughlin.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the disclaimer that follows
these conditions in the documentation and/or other materials
provided with the distribution.
3. The name "JDOM" must not be used to endorse or promote products
derived from this software without prior written permission. For
written permission, please contact <request_AT_jdom_DOT_org>.
4. Products derived from this software may not be called "JDOM", nor
may "JDOM" appear in their name, without prior written permission
from the JDOM Project Management <request_AT_jdom_DOT_org>.
In addition, we request (but do not require) that you include in the
end-user documentation provided with the redistribution and/or in the
software itself an acknowledgement equivalent to the following:
"This product includes software developed by the
JDOM Project (http://www.jdom.org/)."
Alternatively, the acknowledgment may be graphical using the logos
available at http://www.jdom.org/images/logos.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
This software consists of voluntary contributions made by many
individuals on behalf of the JDOM Project and was originally
created by Jason Hunter <jhunter_AT_jdom_DOT_org> and
Brett McLaughlin <brett_AT_jdom_DOT_org>. For more information
on the JDOM Project, please see <http://www.jdom.org/>.
*/

View File

@@ -0,0 +1,46 @@
Indiana University Extreme! Lab Software License
Version 1.1.1
Copyright (c) 2002 Extreme! Lab, Indiana University. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The end-user documentation included with the redistribution, if any,
must include the following acknowledgment:
"This product includes software developed by the Indiana University
Extreme! Lab (http://www.extreme.indiana.edu/)."
Alternately, this acknowledgment may appear in the software itself,
if and wherever such third-party acknowledgments normally appear.
4. The names "Indiana Univeristy" and "Indiana Univeristy Extreme! Lab"
must not be used to endorse or promote products derived from this
software without prior written permission. For written permission,
please contact http://www.extreme.indiana.edu/.
5. Products derived from this software may not use "Indiana Univeristy"
name nor may "Indiana Univeristy" appear in their name, without prior
written permission of the Indiana University.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHORS, COPYRIGHT HOLDERS OR ITS CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,6 +1,6 @@
# Fetch image based on Tomcat 9.0, Java 11 and Centos 8
# More infos about this image: https://github.com/Alfresco/alfresco-docker-base-tomcat
FROM alfresco/alfresco-base-tomcat:9.0.41-java-11-openjdk-centos-8
FROM alfresco/alfresco-base-tomcat:9.0.52-java-11-centos-7
# Set default docker_context.
ARG resource_path=target
@@ -65,12 +65,12 @@ RUN sed -i -e "s_log4j.appender.File.File\=alfresco.log_log4j.appender.File.File
# fontconfig is required by Activiti worflow diagram generator
# installing pinned dependencies as well
RUN yum install -y fontconfig-2.13.1-3.el8 \
dejavu-fonts-common-2.35-6.el8 \
fontpackages-filesystem-1.44-22.el8 \
freetype-2.9.1-4.el8_3.1 \
libpng-1.6.34-5.el8 \
dejavu-sans-fonts-2.35-6.el8 && \
RUN yum install -y fontconfig-2.13.0-4.3.el7 \
dejavu-fonts-common-2.33-6.el7 \
fontpackages-filesystem-1.44-8.el7 \
freetype-2.8-14.el7_9.1 \
libpng-1.5.13-8.el7 \
dejavu-sans-fonts-2.33-6.el7 && \
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>9.10</version>
<version>10.14</version>
</parent>
<properties>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>9.10</version>
<version>10.14</version>
</parent>
<profiles>

View File

@@ -1,4 +1,4 @@
TRANSFORMERS_TAG=2.3.10
SOLR6_TAG=2.0.1
TRANSFORMERS_TAG=2.5.0
SOLR6_TAG=2.0.2
POSTGRES_TAG=13.1
ACTIVEMQ_TAG=5.16.1

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>9.10</version>
<version>10.14</version>
</parent>
<properties>

71
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>9.10</version>
<version>10.14</version>
<packaging>pom</packaging>
<name>Alfresco Community Repo Parent</name>
@@ -23,7 +23,7 @@
<properties>
<acs.version.major>7</acs.version.major>
<acs.version.minor>0</acs.version.minor>
<acs.version.revision>1</acs.version.revision>
<acs.version.revision>2</acs.version.revision>
<acs.version.label />
<version.edition>Community</version.edition>
@@ -34,15 +34,15 @@
<image.registry>quay.io</image.registry>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<maven.build.sourceVersion>11</maven.build.sourceVersion>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.build.sourceVersion>${java.version}</maven.build.sourceVersion>
<dir.root>${project.build.directory}/alf_data</dir.root>
<dependency.alfresco-hb-data-sender.version>1.0.12</dependency.alfresco-hb-data-sender.version>
<dependency.alfresco-mmt.version>6.0</dependency.alfresco-mmt.version>
<dependency.alfresco-trashcan-cleaner.version>2.3</dependency.alfresco-trashcan-cleaner.version>
<dependency.alfresco-trashcan-cleaner.version>2.4.1</dependency.alfresco-trashcan-cleaner.version>
<dependency.alfresco-jlan.version>7.1</dependency.alfresco-jlan.version>
<dependency.alfresco-server-root.version>6.0.1</dependency.alfresco-server-root.version>
<dependency.alfresco-messaging-repo.version>1.2.15</dependency.alfresco-messaging-repo.version>
@@ -53,16 +53,16 @@
<dependency.alfresco-greenmail.version>6.2</dependency.alfresco-greenmail.version>
<dependency.acs-event-model.version>0.0.12</dependency.acs-event-model.version>
<dependency.spring.version>5.3.3</dependency.spring.version>
<dependency.spring.version>5.3.18</dependency.spring.version>
<dependency.antlr.version>3.5.2</dependency.antlr.version>
<dependency.jackson.version>2.12.1</dependency.jackson.version>
<dependency.jackson-databind.version>${dependency.jackson.version}</dependency.jackson-databind.version>
<dependency.cxf.version>3.4.2</dependency.cxf.version>
<dependency.jackson.version>2.12.3</dependency.jackson.version>
<dependency.jackson-databind.version>2.12.3</dependency.jackson-databind.version>
<dependency.cxf.version>3.4.4</dependency.cxf.version>
<dependency.opencmis.version>1.0.0</dependency.opencmis.version>
<dependency.webscripts.version>8.18</dependency.webscripts.version>
<dependency.bouncycastle.version>1.68</dependency.bouncycastle.version>
<dependency.mockito-core.version>3.8.0</dependency.mockito-core.version>
<dependency.org-json.version>20201115</dependency.org-json.version>
<dependency.webscripts.version>8.29</dependency.webscripts.version>
<dependency.bouncycastle.version>1.69</dependency.bouncycastle.version>
<dependency.mockito-core.version>3.9.0</dependency.mockito-core.version>
<dependency.org-json.version>20210307</dependency.org-json.version>
<dependency.commons-dbcp.version>1.4-DBCP330</dependency.commons-dbcp.version>
<dependency.commons-io.version>2.8.0</dependency.commons-io.version>
<dependency.gson.version>2.8.5</dependency.gson.version>
@@ -73,17 +73,18 @@
<dependency.slf4j.version>1.7.30</dependency.slf4j.version>
<dependency.gytheio.version>0.12</dependency.gytheio.version>
<dependency.groovy.version>2.5.9</dependency.groovy.version>
<dependency.tika.version>1.25</dependency.tika.version>
<dependency.spring-security.version>5.4.1</dependency.spring-security.version>
<dependency.tika.version>1.26</dependency.tika.version>
<dependency.spring-security.version>5.5.0</dependency.spring-security.version>
<dependency.truezip.version>7.7.10</dependency.truezip.version>
<dependency.poi.version>4.1.2</dependency.poi.version>
<dependency.ooxml-schemas.version>1.4</dependency.ooxml-schemas.version>
<dependency.keycloak.version>11.0.0-alfresco-001</dependency.keycloak.version>
<dependency.keycloak.version>13.0.1</dependency.keycloak.version>
<dependency.jboss.logging.version>3.4.1.Final</dependency.jboss.logging.version>
<dependency.camel.version>3.7.0</dependency.camel.version>
<dependency.camel.version>3.7.4</dependency.camel.version>
<dependency.activemq.version>5.16.1</dependency.activemq.version>
<dependency.apache-compress.version>1.21</dependency.apache-compress.version>
<dependency.apache.taglibs.version>1.2.5</dependency.apache.taglibs.version>
<dependency.awaitility.version>4.0.3</dependency.awaitility.version>
<dependency.awaitility.version>4.1.0</dependency.awaitility.version>
<dependency.jakarta-jaxb-api.version>2.3.3</dependency.jakarta-jaxb-api.version>
<dependency.jakarta-ws-api.version>2.3.3</dependency.jakarta-ws-api.version>
@@ -96,16 +97,16 @@
<dependency.jakarta-json-api.version>1.1.6</dependency.jakarta-json-api.version>
<dependency.jakarta-rpc-api.version>1.1.4</dependency.jakarta-rpc-api.version>
<alfresco.googledrive.version>3.2.1</alfresco.googledrive.version>
<alfresco.aos-module.version>1.4.0</alfresco.aos-module.version>
<alfresco.googledrive.version>3.2.1.3</alfresco.googledrive.version>
<alfresco.aos-module.version>1.4.0.1</alfresco.aos-module.version>
<dependency.postgresql.version>42.2.19</dependency.postgresql.version>
<dependency.mysql.version>8.0.23</dependency.mysql.version>
<dependency.postgresql.version>42.2.20</dependency.postgresql.version>
<dependency.mysql.version>8.0.25</dependency.mysql.version>
<dependency.mariadb.version>2.7.2</dependency.mariadb.version>
<dependency.tas-utility.version>3.0.43</dependency.tas-utility.version>
<dependency.tas-utility.version>3.0.44</dependency.tas-utility.version>
<dependency.rest-assured.version>3.3.0</dependency.rest-assured.version>
<dependency.tas-restapi.version>1.56</dependency.tas-restapi.version>
<dependency.tas-cmis.version>1.27</dependency.tas-cmis.version>
<dependency.tas-restapi.version>1.58</dependency.tas-restapi.version>
<dependency.tas-cmis.version>1.30</dependency.tas-cmis.version>
<dependency.tas-email.version>1.8</dependency.tas-email.version>
<dependency.tas-webdav.version>1.6</dependency.tas-webdav.version>
<dependency.tas-ftp.version>1.5</dependency.tas-ftp.version>
@@ -116,7 +117,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>9.10</tag>
<tag>10.14</tag>
</scm>
<distributionManagement>
@@ -549,8 +550,7 @@
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.68</version>
<!-- <version>${dependency.bouncycastle.version}</version>-->
<version>${dependency.bouncycastle.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
@@ -583,7 +583,7 @@
<dependency>
<groupId>com.drewnoakes</groupId>
<artifactId>metadata-extractor</artifactId>
<version>2.15.0</version>
<version>2.16.0</version>
</dependency>
<!-- upgrade dependency from TIKA -->
<dependency>
@@ -595,13 +595,13 @@
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.13.1</version>
<version>1.14.2</version>
</dependency>
<!-- upgrade dependency from TIKA -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.20</version>
<version>${dependency.apache-compress.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
@@ -679,7 +679,7 @@
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.9</version>
<version>2.10.10</version>
</dependency>
<!-- provided dependencies -->
@@ -694,7 +694,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -814,7 +814,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<version>3.3.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -829,5 +829,4 @@
</plugins>
</pluginManagement>
</build>
</project>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>9.10</version>
<version>10.14</version>
</parent>
<dependencies>

View File

@@ -0,0 +1,64 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 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.web.scripts;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.springframework.extensions.webscripts.WebScriptRequest;
public class MimeTypeUtil
{
/**
* Get the file mimetype from the file ContentReader, and if its null then set the mimetype to binary by default
* and try to get the correct one from file extension
*
*
* @param reader reader of the file in the request
* @param req request relating to the file
* @param mimetypeService MimetypeService
*
* @return mimetype of the file as a string
*/
public static String determineMimetype(ContentReader reader, WebScriptRequest req, MimetypeService mimetypeService)
{
String mimetype = reader.getMimetype();
if (mimetype == null || mimetype.length() == 0)
{
String extensionPath = req.getExtensionPath();
mimetype = MimetypeMap.MIMETYPE_BINARY;
int extIndex = extensionPath.lastIndexOf('.');
if (extIndex != -1)
{
String ext = extensionPath.substring(extIndex + 1);
mimetype = mimetypeService.getMimetype(ext);
}
}
return mimetype;
}
}

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -26,14 +26,18 @@
package org.alfresco.repo.web.scripts.content;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.web.scripts.MimeTypeUtil;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.NamespaceService;
@@ -65,6 +69,19 @@ public class ContentGet extends StreamContent implements ServletContextAware
private NamespaceService namespaceService;
private ContentService contentService;
private List<String> nonAttachContentTypes = Collections.emptyList();
/**
* @param nonAttachContentTypes List<String>
*/
public void setNonAttachContentTypes(List<String> nonAttachContentTypes)
{
if (nonAttachContentTypes != null && !nonAttachContentTypes.isEmpty())
{
this.nonAttachContentTypes = nonAttachContentTypes;
}
}
/**
* @param servletContext ServletContext
*/
@@ -121,9 +138,7 @@ public class ContentGet extends StreamContent implements ServletContextAware
{
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + reference.toString());
}
// determine attachment
boolean attach = Boolean.valueOf(req.getParameter("a"));
// render content
QName propertyQName = ContentModel.PROP_CONTENT;
@@ -140,6 +155,19 @@ public class ContentGet extends StreamContent implements ServletContextAware
propertyQName = QName.createQName(propertyName, namespaceService);
}
}
// determine attachment and force download for specific mimetypes - see PRODSEC-5862
boolean attach = Boolean.valueOf(req.getParameter("a"));
ContentReader reader = contentService.getReader(nodeRef, propertyQName);
String mimetype = MimeTypeUtil.determineMimetype(reader, req, mimetypeService);
if (!attach)
{
if (nonAttachContentTypes == null || !nonAttachContentTypes.contains(mimetype))
{
attach = true;
logger.warn("Ignored a=false for " + nodeRef.getId() + " since " + mimetype + " is not in the whitelist for non-attach content types");
}
}
// Stream the content
streamContentLocal(req, res, nodeRef, attach, propertyQName, null);

View File

@@ -1,28 +1,28 @@
/*
* #%L
* Alfresco Remote API
* %%
* 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 Remote API
* %%
* Copyright (C) 2005 - 2022 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.web.scripts.content;
import java.io.IOException;
@@ -33,7 +33,7 @@ import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.web.scripts.MimeTypeUtil;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
@@ -79,18 +79,7 @@ public class ContentInfo extends StreamContent
delegate.setAttachment(req, res, attach, attachFileName);
// establish mimetype
String mimetype = reader.getMimetype();
String extensionPath = req.getExtensionPath();
if (mimetype == null || mimetype.length() == 0)
{
mimetype = MimetypeMap.MIMETYPE_BINARY;
int extIndex = extensionPath.lastIndexOf('.');
if (extIndex != -1)
{
String ext = extensionPath.substring(extIndex + 1);
mimetype = mimetypeService.getMimetype(ext);
}
}
String mimetype = MimeTypeUtil.determineMimetype(reader, req, mimetypeService);
// set mimetype for the content and the character encoding + length for the stream
res.setContentType(mimetype);

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -41,6 +41,7 @@ import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.repo.web.scripts.MimeTypeUtil;
import org.alfresco.sync.repo.events.EventPublisher;
import org.alfresco.repo.web.util.HttpRangeProcessor;
import org.alfresco.rest.framework.resource.content.CacheDirective;
@@ -359,18 +360,7 @@ public class ContentStreamer implements ResourceLoaderAware
setAttachment(req, res, attach, attachFileName);
// establish mimetype
String mimetype = reader.getMimetype();
String extensionPath = req.getExtensionPath();
if (mimetype == null || mimetype.length() == 0)
{
mimetype = MimetypeMap.MIMETYPE_BINARY;
int extIndex = extensionPath.lastIndexOf('.');
if (extIndex != -1)
{
String ext = extensionPath.substring(extIndex + 1);
mimetype = mimetypeService.getMimetype(ext);
}
}
String mimetype = MimeTypeUtil.determineMimetype(reader, req, mimetypeService);
res.setHeader(HEADER_ACCEPT_RANGES, "bytes");
try

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -713,6 +713,7 @@ public class CustomModelsImpl implements CustomModels
try
{
NodeRef nodeRef = customModelService.createDownloadNode(modelName, withForm);
nodeService.setProperty(nodeRef, ContentModel.PROP_NAME, modelName + DownloadsImpl.DEFAULT_ARCHIVE_EXTENSION);
return new CustomModelDownload(nodeRef);
}
catch (Exception ex)

View File

@@ -41,7 +41,11 @@ public class DefaultExceptionResolver implements ExceptionResolver<Exception>
@Override
public ErrorResponse resolveException(Exception ex)
{
return new ErrorResponse(DEFAULT_MESSAGE_ID, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex.getLocalizedMessage(), ex.getStackTrace(), null);
return new ErrorResponse(DEFAULT_MESSAGE_ID,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
ex.getLocalizedMessage(),
ex.getStackTrace(),
null);
}
}

View File

@@ -0,0 +1,48 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2021 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.rest.framework.core.exceptions;
import org.alfresco.repo.search.QueryParserException;
/**
* QueryParserException is related with search requests to Search Services.
*/
public class QueryParserExceptionResolver implements ExceptionResolver<QueryParserException>
{
@Override
public ErrorResponse resolveException(QueryParserException ex)
{
return new ErrorResponse(
DefaultExceptionResolver.DEFAULT_MESSAGE_ID,
// Mapping the original HTTP Status code returned by Search Services
ex.getHttpStatusCode(),
ex.getLocalizedMessage(),
ex.getStackTrace(),
null);
}
}

View File

@@ -26,10 +26,12 @@
package org.alfresco.rest.framework.tools;
import org.alfresco.metrics.rest.RestMetricsReporter;
import org.alfresco.repo.search.QueryParserException;
import org.alfresco.rest.framework.Api;
import org.alfresco.rest.framework.core.exceptions.DefaultExceptionResolver;
import org.alfresco.rest.framework.core.exceptions.ErrorResponse;
import org.alfresco.rest.framework.core.exceptions.ExceptionResolver;
import org.alfresco.rest.framework.core.exceptions.QueryParserExceptionResolver;
import org.alfresco.rest.framework.jacksonextensions.JacksonHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -48,6 +50,7 @@ public class ApiAssistant {
private ExceptionResolver<Exception> defaultResolver = new DefaultExceptionResolver();
private ExceptionResolver<WebScriptException> webScriptExceptionResolver;
private ExceptionResolver<QueryParserException> queryParserExceptionResolver;
private ExceptionResolver<Exception> resolver;
private JacksonHelper jsonHelper;
private RestMetricsReporter restMetricsReporter;
@@ -77,6 +80,10 @@ public class ApiAssistant {
{
error = webScriptExceptionResolver.resolveException((WebScriptException) ex);
}
else if (ex instanceof QueryParserException)
{
error = queryParserExceptionResolver.resolveException((QueryParserException) ex);
}
else
{
error = resolver.resolveException(ex);
@@ -100,6 +107,11 @@ public class ApiAssistant {
this.webScriptExceptionResolver = webScriptExceptionResolver;
}
public void setQueryParserExceptionResolver(ExceptionResolver<QueryParserException> queryParserExceptionResolver)
{
this.queryParserExceptionResolver = queryParserExceptionResolver;
}
public void setResolver(ExceptionResolver<Exception> resolver) {
this.resolver = resolver;
}

View File

@@ -134,6 +134,8 @@
</bean>
<bean id="webScriptExceptionResolver" class="org.alfresco.rest.framework.core.exceptions.WebScriptExceptionResolver">
</bean>
<bean id="queryParserExceptionResolver" class="org.alfresco.rest.framework.core.exceptions.QueryParserExceptionResolver">
</bean>
<bean id="simpleMappingExceptionResolverParent" abstract="true" class="org.alfresco.rest.framework.core.exceptions.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<map>
@@ -182,6 +184,7 @@
<property name="resolver" ref="simpleMappingExceptionResolver" />
<property name="webScriptExceptionResolver" ref="webScriptExceptionResolver" />
<property name="restMetricsReporter" ref="restMetricsReporter"/>
<property name="queryParserExceptionResolver" ref="queryParserExceptionResolver" />
</bean>
<!-- Using annotation-config=false means AutowiredAnnotationBeanPostProcessor

View File

@@ -1,34 +1,76 @@
<#assign null><span style="color:red">${msg("nodebrowser.null")?html}</span></#assign>
<#assign none><span style="color:red">${msg("nodebrowser.none")?html}</span></#assign>
<#assign collection>${msg("nodebrowser.collection")?html}</#assign>
<#assign maxDepth=1000 />
<#macro dateFormat date>${date?string("dd MMM yyyy HH:mm:ss 'GMT'Z '('zzz')'")}</#macro>
<#macro propValue p>
<#if p.value??>
<#if p.value?is_date>
<@dateFormat p.value />
<#elseif p.value?is_boolean>
${p.value?string}
<#elseif p.value?is_number>
${p.value?c}
<#elseif p.value?is_string>
${p.value?html}
<#elseif p.value?is_hash>
<#assign result = "{"/>
<#assign first = true />
<#list p.value?keys as key>
<#if first = false>
<#assign result = result + ", "/>
<#attempt>
<#if p.value??>
<#if p.value?is_date>
<@dateFormat p.value />
<#elseif p.value?is_boolean>
${p.value?string}
<#elseif p.value?is_number>
${p.value?c}
<#elseif p.value?is_string>
${p.value?html}
<#elseif p.value?is_hash || p.value?is_enumerable>
<@convertToJSON p.value />
</#if>
<#else>
${null}
</#if>
<#recover>
<span style="color:red">${.error}</span>
</#attempt>
</#macro>
<#macro convertToJSON v>
<#if v??>
<#if v?is_date>
<@dateFormat v />
<#elseif v?is_boolean>
${v?string}
<#elseif v?is_number>
${v?c}
<#elseif v?is_string>
"${v?string}"
<#elseif v?is_hash>
<#if v?keys?size gt maxDepth >
<#stop "Max depth of object achieved">
</#if>
<#assign result = result + "${key}=${p.value[key]?html}" />
<#assign first = false/>
</#list>
<#assign result = result + "}"/>
${result}
<@compress single_line=true>
{
<#assign first = true />
<#list v?keys as key>
<#if first = false>,</#if>
"${key}":
<#if v[key]??>
<@convertToJSON v[key] />
<#else>
${null}
</#if>
<#assign first = false/>
</#list>
}
</@compress>
<#elseif v?is_enumerable>
<#if v?size gt maxDepth>
<#stop "Max depth of object achieved" >
</#if>
<#assign first = true />
<@compress single_line=true>
[
<#list v as item>
<#if first = false>,</#if>
<@convertToJSON item />
<#assign first = false/>
</#list>
]
</@compress>
</#if>
<#else>
${null}
</#if>
<#else>
${null}
</#if>
</#macro>
<#macro contentUrl nodeRef prop>
${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url}

View File

@@ -249,6 +249,7 @@
<property name="delegate" ref="webscript.content.streamer" />
<property name="contentService" ref="contentService" />
<property name="repository" ref="repositoryHelper" />
<property name="nonAttachContentTypes" value="#{T(java.util.Arrays).asList('${content.nonAttach.mimetypes}')}" />
</bean>
<!-- Content Info -->

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Share Services AMP
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -66,13 +66,17 @@ public class ContentGetTest extends BaseWebScriptTest
{
super.setUp();
this.authenticationService = (MutableAuthenticationService) getServer().getApplicationContext()
.getBean("AuthenticationService");
this.authenticationService = (MutableAuthenticationService)getServer().getApplicationContext().getBean("AuthenticationService");
this.personService = (PersonService) getServer().getApplicationContext().getBean("PersonService");
this.nodeService = (NodeService) getServer().getApplicationContext().getBean("NodeService");
this.contentService = (ContentService) getServer().getApplicationContext().getBean("ContentService");
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
createUser(USER_ONE);
Repository repositoryHelper = (Repository) getServer().getApplicationContext().getBean("repositoryHelper");
NodeRef companyHome = repositoryHelper.getCompanyHome();
rootFolder = createNode(companyHome, "rootFolder", ContentModel.TYPE_FOLDER);
}
private void createUser(String userName)
@@ -117,18 +121,13 @@ public class ContentGetTest extends BaseWebScriptTest
*/
public void testRelativePath() throws Exception
{
Repository repositoryHelper = (Repository) getServer().getApplicationContext().getBean("repositoryHelper");
NodeRef companyHome = repositoryHelper.getCompanyHome();
rootFolder = createNode(companyHome, "rootFolder", ContentModel.TYPE_FOLDER);
NodeRef doc1 = createNodeWithTextContent(rootFolder, "doc1", ContentModel.TYPE_CONTENT, "doc1 file content");
NodeRef doc1 = createNodeWithTextContent(rootFolder, "doc1", ContentModel.TYPE_CONTENT, "doc1 file content", MimetypeMap.MIMETYPE_TEXT_PLAIN);
NodeRef folderX = createNode(rootFolder, "X", ContentModel.TYPE_FOLDER);
NodeRef folderY = createNode(folderX, "Y", ContentModel.TYPE_FOLDER);
NodeRef folderZ = createNode(folderY, "Z", ContentModel.TYPE_FOLDER);
NodeRef doc2 = createNodeWithTextContent(folderZ, "doc2", ContentModel.TYPE_CONTENT, "doc2 file content");
NodeRef doc2 = createNodeWithTextContent(folderZ, "doc2", ContentModel.TYPE_CONTENT, "doc2 file content", MimetypeMap.MIMETYPE_TEXT_PLAIN);
// uri with relative path at the end
String uri = URL_CONTENT_DOWNLOAD + doc1.getId() + "/X/Y/Z/doc2";
@@ -138,7 +137,46 @@ public class ContentGetTest extends BaseWebScriptTest
Assert.assertEquals("doc2 file content", resp.getContentAsString());
}
public NodeRef createNodeWithTextContent(NodeRef parentNode, String nodeCmName, QName nodeType, String content)
public void testForcedAttachment() throws Exception
{
NodeRef testhtml = createNodeWithTextContent(rootFolder, "testhtml", ContentModel.TYPE_CONTENT, "testhtml content", MimetypeMap.MIMETYPE_HTML);
NodeRef testpdf = createNodeWithTextContent(rootFolder, "testpdf", ContentModel.TYPE_CONTENT, "testpdf content", MimetypeMap.MIMETYPE_PDF);
String uri = URL_CONTENT_DOWNLOAD + testhtml.getId() + "?a=false";
GetRequest req = new GetRequest(uri);
Response res = sendRequest(req, 200);
assertEquals("attachment", res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8", res.getContentType());
uri = URL_CONTENT_DOWNLOAD + testhtml.getId();
res = sendRequest(new GetRequest(uri), 200);
assertEquals("attachment", res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8", res.getContentType());
uri = URL_CONTENT_DOWNLOAD + testhtml.getId() + "?a=true";
res = sendRequest(new GetRequest(uri), 200);
assertEquals("attachment", res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8", res.getContentType());
uri = URL_CONTENT_DOWNLOAD + testpdf.getId() + "?a=false";
res = sendRequest(new GetRequest(uri), 200);
assertNull(res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_PDF + ";charset=UTF-8", res.getContentType());
uri = URL_CONTENT_DOWNLOAD + testpdf.getId();
res = sendRequest(new GetRequest(uri), 200);
assertNull(res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_PDF + ";charset=UTF-8", res.getContentType());
uri = URL_CONTENT_DOWNLOAD + testpdf.getId() + "?a=true";
res = sendRequest(new GetRequest(uri), 200);
assertEquals("attachment", res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_PDF + ";charset=UTF-8", res.getContentType());
}
public NodeRef createNodeWithTextContent(NodeRef parentNode, String nodeCmName, QName nodeType, String content, String mimetype)
{
NodeRef nodeRef = createNode(parentNode, nodeCmName, nodeType);
@@ -146,7 +184,7 @@ public class ContentGetTest extends BaseWebScriptTest
if (content != null)
{
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.setMimetype(mimetype);
writer.setEncoding("UTF-8");
writer.putContent(content);
}

View File

@@ -23,45 +23,46 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.framework.tests.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import org.alfresco.repo.forms.FormNotFoundException;
package org.alfresco.rest.framework.tests.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import org.alfresco.repo.forms.FormNotFoundException;
import org.alfresco.repo.node.integrity.IntegrityException;
import org.alfresco.rest.framework.core.exceptions.ApiException;
import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException;
import org.alfresco.rest.framework.core.exceptions.DeletedResourceException;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.ErrorResponse;
import org.alfresco.repo.search.QueryParserException;
import org.alfresco.rest.framework.core.exceptions.ApiException;
import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException;
import org.alfresco.rest.framework.core.exceptions.DeletedResourceException;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.ErrorResponse;
import org.alfresco.rest.framework.core.exceptions.InsufficientStorageException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
import org.alfresco.rest.framework.core.exceptions.StaleEntityException;
import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException;
import org.alfresco.rest.framework.resource.parameters.where.InvalidQueryException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
import org.alfresco.rest.framework.core.exceptions.StaleEntityException;
import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException;
import org.alfresco.rest.framework.resource.parameters.where.InvalidQueryException;
import org.alfresco.rest.framework.tools.ApiAssistant;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.servlet.http.HttpServletResponse;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:test-rest-context.xml" })
public class ExceptionResolverTests
{
@Autowired
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:test-rest-context.xml" })
public class ExceptionResolverTests
{
@Autowired
ApiAssistant assistant;
@Test
@Test
public void testWebscriptException()
{
ErrorResponse response = assistant.resolveException(new WebScriptException(null));
@@ -75,43 +76,43 @@ public class ExceptionResolverTests
//04180006 Authentication failed for Web Script org/alfresco/api/ResourceWebScript.get
@Test
public void testMatchException()
{
public void testMatchException()
{
ErrorResponse response = assistant.resolveException(new ApiException(null));
assertNotNull(response);
assertEquals(500, response.getStatusCode()); //default to INTERNAL_SERVER_ERROR
assertNotNull(response);
assertEquals(500, response.getStatusCode()); //default to INTERNAL_SERVER_ERROR
response = assistant.resolveException(new InvalidArgumentException(null));
assertEquals(400, response.getStatusCode()); //default to STATUS_BAD_REQUEST
response = assistant.resolveException(new InvalidQueryException(null));
assertEquals(400, response.getStatusCode()); //default to STATUS_BAD_REQUEST
response = assistant.resolveException(new NotFoundException(null));
assertEquals(404, response.getStatusCode()); //default to STATUS_NOT_FOUND
response = assistant.resolveException(new EntityNotFoundException(null));
assertEquals(404, response.getStatusCode()); //default to STATUS_NOT_FOUND
response = assistant.resolveException(new RelationshipResourceNotFoundException(null, null));
assertEquals(404, response.getStatusCode()); //default to STATUS_NOT_FOUND
response = assistant.resolveException(new PermissionDeniedException(null));
assertEquals(403, response.getStatusCode()); //default to STATUS_FORBIDDEN
response = assistant.resolveException(new UnsupportedResourceOperationException(null));
assertEquals(405, response.getStatusCode()); //default to STATUS_METHOD_NOT_ALLOWED
response = assistant.resolveException(new DeletedResourceException(null));
assertEquals(405, response.getStatusCode()); //default to STATUS_METHOD_NOT_ALLOWED
response = assistant.resolveException(new ConstraintViolatedException(null));
assertEquals(409, response.getStatusCode()); //default to STATUS_CONFLICT
response = assistant.resolveException(new StaleEntityException(null));
assertEquals(409, response.getStatusCode()); //default to STATUS_CONFLICT
assertEquals(400, response.getStatusCode()); //default to STATUS_BAD_REQUEST
//Try a random exception
response = assistant.resolveException(new InvalidQueryException(null));
assertEquals(400, response.getStatusCode()); //default to STATUS_BAD_REQUEST
response = assistant.resolveException(new NotFoundException(null));
assertEquals(404, response.getStatusCode()); //default to STATUS_NOT_FOUND
response = assistant.resolveException(new EntityNotFoundException(null));
assertEquals(404, response.getStatusCode()); //default to STATUS_NOT_FOUND
response = assistant.resolveException(new RelationshipResourceNotFoundException(null, null));
assertEquals(404, response.getStatusCode()); //default to STATUS_NOT_FOUND
response = assistant.resolveException(new PermissionDeniedException(null));
assertEquals(403, response.getStatusCode()); //default to STATUS_FORBIDDEN
response = assistant.resolveException(new UnsupportedResourceOperationException(null));
assertEquals(405, response.getStatusCode()); //default to STATUS_METHOD_NOT_ALLOWED
response = assistant.resolveException(new DeletedResourceException(null));
assertEquals(405, response.getStatusCode()); //default to STATUS_METHOD_NOT_ALLOWED
response = assistant.resolveException(new ConstraintViolatedException(null));
assertEquals(409, response.getStatusCode()); //default to STATUS_CONFLICT
response = assistant.resolveException(new StaleEntityException(null));
assertEquals(409, response.getStatusCode()); //default to STATUS_CONFLICT
//Try a random exception
response = assistant.resolveException(new FormNotFoundException(null));
assertEquals(500, response.getStatusCode()); //default to INTERNAL_SERVER_ERROR
@@ -120,6 +121,15 @@ public class ExceptionResolverTests
response = assistant.resolveException(new IntegrityException(null));
assertEquals(422, response.getStatusCode());
}
}
}
/** Check that the status code from SS is passed back to the caller. */
@Test
public void testQueryParserException()
{
ErrorResponse response = assistant.resolveException(new QueryParserException("Endpoint not found", 404));
assertNotNull(response);
assertEquals("Expected status code to be passed through from query parser.", 404, response.getStatusCode());
}
}

View File

@@ -33,10 +33,12 @@
</bean>
<bean id="webScriptExceptionResolver" class="org.alfresco.rest.framework.core.exceptions.WebScriptExceptionResolver">
</bean>
<bean id="queryParserExceptionResolver" class="org.alfresco.rest.framework.core.exceptions.QueryParserExceptionResolver" />
<bean id="apiAssistant" class="org.alfresco.rest.framework.tools.ApiAssistant">
<property name="jsonHelper" ref="jsonHelper" />
<property name="resolver" ref="simpleMappingExceptionResolver" />
<property name="webScriptExceptionResolver" ref="webScriptExceptionResolver" />
<property name="queryParserExceptionResolver" ref="queryParserExceptionResolver" />
</bean>
<bean id="simpleMappingExceptionResolver" class="org.alfresco.rest.framework.core.exceptions.SimpleMappingExceptionResolver">
<property name="exceptionMappings">

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>9.10</version>
<version>10.14</version>
</parent>
<dependencies>
@@ -245,7 +245,7 @@
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.20-alfresco-patched-20200421</version>
<version>2.3.20-alfresco-patched-20220413</version>
</dependency>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
@@ -383,7 +383,7 @@
<dependency>
<groupId>com.fasterxml.woodstox</groupId>
<artifactId>woodstox-core</artifactId>
<version>6.2.4</version>
<version>6.2.6</version>
</dependency>
<!-- GData -->

View File

@@ -34,7 +34,10 @@ import org.alfresco.repo.action.ParameterDefinitionImpl;
import org.alfresco.repo.admin.SysAdminParams;
import org.alfresco.repo.jscript.ScriptAction;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionDefinition;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.action.ParameterConstraint;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -126,6 +129,10 @@ public class ScriptActionExecuter extends ActionExecuterAbstractBase
if (nodeService.exists(actionedUponNodeRef))
{
NodeRef scriptRef = (NodeRef)action.getParameterValue(PARAM_SCRIPTREF);
if(!isValidScriptRef(action))
{
throw new IllegalStateException("Invalid script ref path: " + scriptRef);
}
NodeRef spaceRef = this.serviceRegistry.getRuleService().getOwningNodeRef(action);
if (spaceRef == null)
{
@@ -222,4 +229,19 @@ public class ScriptActionExecuter extends ActionExecuterAbstractBase
return companyHomeRef;
}
private boolean isValidScriptRef(Action action)
{
NodeRef scriptRef = (NodeRef) action.getParameterValue(PARAM_SCRIPTREF);
ActionService actionService = this.serviceRegistry.getActionService();
ActionDefinition actDef = actionService.getActionDefinition(action.getActionDefinitionName());
ParameterDefinition parameterDef = actDef.getParameterDefintion(PARAM_SCRIPTREF);
String paramConstraintName = parameterDef.getParameterConstraintName();
if (paramConstraintName != null)
{
ParameterConstraint paramConstraint = actionService.getParameterConstraint(paramConstraintName);
return paramConstraint.isValidValue(scriptRef.toString());
}
return true;
}
}

View File

@@ -69,19 +69,19 @@ public class DeleteNotExistsExecutor implements StatementExecutor
public static final String PROPERTY_READ_ONLY = "system.delete_not_exists.read_only";
public static final String PROPERTY_TIMEOUT_SECONDS = "system.delete_not_exists.timeout_seconds";
private Connection connection;
protected Connection connection;
private String sql;
private int line;
private File scriptFile;
private Properties globalProperties;
private boolean readOnly;
private int deleteBatchSize;
private int batchSize;
protected boolean readOnly;
protected int deleteBatchSize;
protected int batchSize;
private long timeoutSec;
private long deletedCount;
private Date startTime;
protected long deletedCount;
protected Date startTime;
public DeleteNotExistsExecutor(Connection connection, String sql, int line, File scriptFile, Properties globalProperties)
{
@@ -164,7 +164,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
}
}
private void process(Pair<String, String>[] tableColumn, Long[] tableUpperLimits, String[] optionalWhereClauses) throws SQLException
protected void process(Pair<String, String>[] tableColumn, Long[] tableUpperLimits, String[] optionalWhereClauses) throws SQLException
{
// The approach is to fetch ordered row ids from all referencer/secondary (e.g.
// alf_audit_app, alf_audit_entry, alf_prop_unique_ctx) tables and
@@ -190,6 +190,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
try
{
connection.setAutoCommit(false);
primaryPrepStmt = connection.prepareStatement(createPreparedSelectStatement(primaryTableName, primaryColumnName, primaryWhereClause));
primaryPrepStmt.setFetchSize(batchSize);
primaryPrepStmt.setLong(1, primaryId);
@@ -264,7 +265,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
}
}
private boolean isTimeoutExceeded()
protected boolean isTimeoutExceeded()
{
if (timeoutSec <= 0)
{
@@ -275,7 +276,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
return (now.getTime() > startTime.getTime() + (timeoutSec * 1000));
}
private Long processPrimaryTableResultSet(PreparedStatement primaryPrepStmt, PreparedStatement[] secondaryPrepStmts, PreparedStatement deletePrepStmt, Set<Long> deleteIds, String primaryTableName,
protected Long processPrimaryTableResultSet(PreparedStatement primaryPrepStmt, PreparedStatement[] secondaryPrepStmts, PreparedStatement deletePrepStmt, Set<Long> deleteIds, String primaryTableName,
String primaryColumnName, Pair<String, String>[] tableColumn) throws SQLException
{
int rowsProcessed = 0;
@@ -336,7 +337,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
return primaryId;
}
private void deleteFromPrimaryTable(PreparedStatement deletePrepStmt, Set<Long> deleteIds, String primaryTableName) throws SQLException
protected void deleteFromPrimaryTable(PreparedStatement deletePrepStmt, Set<Long> deleteIds, String primaryTableName) throws SQLException
{
int deletedBatchCount = deleteIds.size();
if (!readOnly && !deleteIds.isEmpty())
@@ -425,7 +426,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
return batchUpperLimit;
}
private boolean isLess(Long primaryId, Long[] secondaryIds)
protected boolean isLess(Long primaryId, Long[] secondaryIds)
{
for (Long secondaryId : secondaryIds)
{
@@ -447,8 +448,8 @@ public class DeleteNotExistsExecutor implements StatementExecutor
return quotedString.replace("\"", "");
}
private String createPreparedSelectStatement(String tableName, String columnName, String whereClause)
protected String createPreparedSelectStatement(String tableName, String columnName, String whereClause)
{
StringBuilder sqlBuilder = new StringBuilder("SELECT " + columnName + " FROM " + tableName + " WHERE ");
@@ -461,7 +462,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
return sqlBuilder.toString();
}
private String createPreparedDeleteStatement(String tableName, String idColumnName, int deleteBatchSize, String whereClause)
protected String createPreparedDeleteStatement(String tableName, String idColumnName, int deleteBatchSize, String whereClause)
{
StringBuilder stmtBuilder = new StringBuilder("DELETE FROM " + tableName + " WHERE ");
@@ -515,7 +516,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
}
}
private Long getColumnValueById(ResultSet resultSet, String columnId) throws SQLException
protected Long getColumnValueById(ResultSet resultSet, String columnId) throws SQLException
{
Long columnValue = null;
if (resultSet != null && resultSet.next())
@@ -526,7 +527,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
return columnValue;
}
private ResultSet[] getSecondaryResultSets(PreparedStatement[] preparedStatements) throws SQLException
protected ResultSet[] getSecondaryResultSets(PreparedStatement[] preparedStatements) throws SQLException
{
ResultSet[] secondaryResultSets = new ResultSet[preparedStatements.length];
for (int i = 1; i < preparedStatements.length; i++)
@@ -540,7 +541,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
return secondaryResultSets;
}
private Long[] getSecondaryIds(ResultSet[] secondaryResultSets, Pair<String, String>[] tableColumn) throws SQLException
protected Long[] getSecondaryIds(ResultSet[] secondaryResultSets, Pair<String, String>[] tableColumn) throws SQLException
{
Long[] secondaryIds = new Long[tableColumn.length];
@@ -571,7 +572,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
}
}
private void closeQuietly(Statement statement)
protected void closeQuietly(Statement statement)
{
if (statement != null)
{
@@ -586,7 +587,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
}
}
private void closeQuietly(Statement[] statements)
protected void closeQuietly(Statement[] statements)
{
if (statements != null)
{
@@ -597,7 +598,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
}
}
private void closeQuietly(ResultSet resultSet)
protected void closeQuietly(ResultSet resultSet)
{
if (resultSet != null)
{
@@ -612,7 +613,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
}
}
private void closeQuietly(ResultSet[] resultSets)
protected void closeQuietly(ResultSet[] resultSets)
{
if (resultSets != null)
{

View File

@@ -0,0 +1,278 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.domain.schema.script;
import org.alfresco.util.Pair;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.sql.DataSource;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
/**
* Extends <code>{@link DeleteNotExistsExecutor}</code> to cope with MySQL
* specific fetch size limitation and restrictions.
*/
public class MySQLDeleteNotExistsExecutor extends DeleteNotExistsExecutor
{
private static final Log logger = LogFactory.getLog(MySQLDeleteNotExistsExecutor.class);
private final DataSource dataSource;
public MySQLDeleteNotExistsExecutor(Connection connection, String sql, int line, File scriptFile, Properties globalProperties, DataSource dataSource)
{
super(connection, sql, line, scriptFile, globalProperties);
this.dataSource = dataSource;
}
@Override
protected void process(Pair<String, String>[] tableColumn, Long[] tableUpperLimits, String[] optionalWhereClauses) throws SQLException
{
// The approach is to fetch ordered row ids from all referencer/secondary (e.g.
// alf_audit_app, alf_audit_entry, alf_prop_unique_ctx) tables and
// referenced/primary table (e.g. alf_prop_root) concurrently, so that it is
// possible skip over id gaps efficiently while at the same time being able to
// work out which ids are obsolete and delete them in batches.
// The algorithm can be further improved by iterating over the rows in descending order.
// This is due to the fact that older data should be more stable in time.
String primaryTableName = tableColumn[0].getFirst();
String primaryColumnName = tableColumn[0].getSecond();
String primaryWhereClause = optionalWhereClauses[0];
Long primaryId = 0L;
PreparedStatement primaryPrepStmt = null;
PreparedStatement[] secondaryPrepStmts = null;
PreparedStatement deletePrepStmt = null;
Set<Long> deleteIds = new HashSet<>();
deletedCount = 0L;
startTime = new Date();
long defaultOffset = 0L;
try
{
connection.setAutoCommit(false);
primaryPrepStmt = connection.prepareStatement(createLimitPreparedSelectStatement(primaryTableName, primaryColumnName, primaryWhereClause));
primaryPrepStmt.setLong(1, primaryId);
primaryPrepStmt.setLong(2, tableUpperLimits[0]);
primaryPrepStmt.setInt(3, batchSize);
primaryPrepStmt.setLong(4, defaultOffset);
boolean hasResults = primaryPrepStmt.execute();
if (hasResults)
{
secondaryPrepStmts = new PreparedStatement[tableColumn.length];
for (int i = 1; i < tableColumn.length; i++)
{
PreparedStatement secStmt = connection.prepareStatement(createLimitPreparedSelectStatement(tableColumn[i].getFirst(), tableColumn[i].getSecond(), optionalWhereClauses[i]));
secStmt.setLong(1, primaryId);
secStmt.setLong(2, tableUpperLimits[i]);
secStmt.setInt(3, batchSize);
secStmt.setLong(4, defaultOffset);
secondaryPrepStmts[i] = secStmt;
}
deletePrepStmt = connection.prepareStatement(createPreparedDeleteStatement(primaryTableName, primaryColumnName, deleteBatchSize, primaryWhereClause));
// Timeout is only checked at each bach start.
// It can be further refined by being verified at each primary row processing.
while (hasResults && !isTimeoutExceeded())
{
// Process batch
primaryId = processPrimaryTableResultSet(primaryPrepStmt, secondaryPrepStmts, deletePrepStmt, deleteIds, primaryTableName, primaryColumnName, tableColumn);
connection.commit();
if (primaryId == null)
{
break;
}
// Prepare for next batch
primaryPrepStmt.setLong(1, primaryId);
primaryPrepStmt.setLong(2, tableUpperLimits[0]);
primaryPrepStmt.setInt(3, batchSize);
primaryPrepStmt.setLong(4, defaultOffset);
for (int i = 1; i < tableColumn.length; i++)
{
PreparedStatement secStmt = secondaryPrepStmts[i];
secStmt.setLong(1, primaryId);
secStmt.setLong(2, tableUpperLimits[i]);
secStmt.setInt(3, batchSize);
secStmt.setLong(4, defaultOffset);
}
hasResults = primaryPrepStmt.execute();
}
}
// Check if we have any more ids to delete
if (!deleteIds.isEmpty())
{
deleteFromPrimaryTable(deletePrepStmt, deleteIds, primaryTableName);
connection.commit();
}
if (logger.isDebugEnabled())
{
String msg = ((readOnly) ? "Script would have" : "Script") + " deleted a total of " + deletedCount + " items from table " + primaryTableName + ".";
logger.debug(msg);
}
}
finally
{
closeQuietly(deletePrepStmt);
closeQuietly(secondaryPrepStmts);
closeQuietly(primaryPrepStmt);
connection.setAutoCommit(true);
}
}
protected Long processPrimaryTableResultSet(PreparedStatement primaryPrepStmt, PreparedStatement[] secondaryPrepStmts, PreparedStatement deletePrepStmt, Set<Long> deleteIds,
String primaryTableName, String primaryColumnName, Pair<String, String>[] tableColumn) throws SQLException
{
int rowsProcessed = 0;
Long primaryId = null;
ResultSet[] secondaryResultSets = null;
try (ResultSet resultSet = primaryPrepStmt.getResultSet())
{
secondaryResultSets = getSecondaryResultSets(secondaryPrepStmts);
Long[] secondaryIds = getSecondaryIds(secondaryResultSets, tableColumn);
// Create and populate secondary tables offsets
Long[] secondaryOffsets = new Long[tableColumn.length];
for (int i = 1; i < tableColumn.length; i++)
{
secondaryOffsets[i] = 0L;
}
while (resultSet.next())
{
++rowsProcessed;
primaryId = resultSet.getLong(primaryColumnName);
while (isLess(primaryId, secondaryIds))
{
deleteIds.add(primaryId);
if (deleteIds.size() == deleteBatchSize)
{
deleteFromPrimaryTable(deletePrepStmt, deleteIds, primaryTableName);
connection.commit();
}
if (!resultSet.next())
{
break;
}
++rowsProcessed;
primaryId = resultSet.getLong(primaryColumnName);
}
if (logger.isTraceEnabled())
{
logger.trace("RowsProcessed " + rowsProcessed + " from primary table " + primaryTableName);
}
updateSecondaryIds(primaryId, secondaryIds, secondaryPrepStmts, secondaryOffsets, secondaryResultSets, tableColumn);
}
}
finally
{
closeQuietly(secondaryResultSets);
}
return primaryId;
}
private void updateSecondaryIds(Long primaryId, Long[] secondaryIds, PreparedStatement[] secondaryPrepStmts, Long[] secondaryOffsets, ResultSet[] secondaryResultSets,
Pair<String, String>[] tableColumn) throws SQLException
{
for (int i = 1; i < tableColumn.length; i++)
{
Long secondaryId = secondaryIds[i];
while (secondaryId != null && primaryId >= secondaryId)
{
ResultSet resultSet = secondaryResultSets[i];
String columnId = tableColumn[i].getSecond();
secondaryId = getColumnValueById(resultSet, columnId);
// Check if we reach the end of the first page
if (secondaryId == null)
{
// Close the previous result set
closeQuietly(resultSet);
// Set to use the next page
long offset = secondaryOffsets[i] + batchSize;
secondaryOffsets[i] = offset;
PreparedStatement secStmt = secondaryPrepStmts[i];
secStmt.setLong(4, offset);
// Check if any results were found
boolean secHasResults = secStmt.execute();
secondaryResultSets[i] = secHasResults ? secStmt.getResultSet() : null;
// Try again to get the next secondary id
secondaryId = getColumnValueById(secondaryResultSets[i], columnId);
}
secondaryIds[i] = secondaryId;
}
}
}
private String createLimitPreparedSelectStatement(String tableName, String columnName, String whereClause)
{
StringBuilder sqlBuilder = new StringBuilder("SELECT " + columnName + " FROM " + tableName + " WHERE ");
if (whereClause != null && !whereClause.isEmpty())
{
sqlBuilder.append(whereClause + " AND ");
}
sqlBuilder.append(columnName + " > ? AND " + columnName + " <= ? ORDER BY " + columnName + " ASC LIMIT ? OFFSET ?");
return sqlBuilder.toString();
}
}

View File

@@ -350,7 +350,7 @@ public class ScriptExecutorImpl implements ScriptExecutor
}
else if (sql.startsWith("--DELETE_NOT_EXISTS"))
{
DeleteNotExistsExecutor deleteNotExists = new DeleteNotExistsExecutor(connection, sql, line, scriptFile, globalProperties);
DeleteNotExistsExecutor deleteNotExists = createDeleteNotExistsExecutor(dialect, connection, sql, line, scriptFile);
deleteNotExists.execute();
// Reset
@@ -537,7 +537,17 @@ public class ScriptExecutorImpl implements ScriptExecutor
try { scriptInputStream.close(); } catch (Throwable e) {}
}
}
private DeleteNotExistsExecutor createDeleteNotExistsExecutor(Dialect dialect, Connection connection, String sql, int line, File scriptFile)
{
if (dialect instanceof MySQLInnoDBDialect)
{
return new MySQLDeleteNotExistsExecutor(connection, sql, line, scriptFile, globalProperties, dataSource);
}
return new DeleteNotExistsExecutor(connection, sql, line, scriptFile, globalProperties);
}
/**
* Execute the given SQL statement, absorbing exceptions that we expect during
* schema creation or upgrade.

View File

@@ -33,6 +33,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.function.Predicate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -152,6 +153,16 @@ public class SafeApplicationEventMulticaster implements ApplicationEventMulticas
}
}
@Override
public void removeApplicationListeners(Predicate<ApplicationListener<?>> predicate)
{
}
@Override
public void removeApplicationListenerBeans(Predicate<String> predicate)
{
}
public void removeAllListeners()
{
synchronized (this.defaultRetriever)

View File

@@ -1,538 +0,0 @@
/*
* #%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.rendition.executer;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.ParameterDefinitionImpl;
import org.alfresco.repo.rendition.RenditionLocation;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.rendition.RenditionServiceException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tika.config.TikaConfig;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.BodyContentHandler;
import org.apache.tika.sax.ContentHandlerDecorator;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
/**
* This class provides a way to turn documents supported by the
* {@link ContentService} standard transformers into basic, clean
* HTML.
* <P/>
* The HTML that is produced probably isn't going to be suitable
* for direct web publishing, as it's likely going to be too
* basic. Instead, it should be simple and clean HTML, suitable
* for being the basis of some web-friendly HTML once edited
* / further transformed.
*
* @author Nick Burch
* @since 3.4
*
* @deprecated The RenditionService is being replace by the simpler async RenditionService2.
*/
@Deprecated
public class HTMLRenderingEngine extends AbstractRenderingEngine
{
private static Log logger = LogFactory.getLog(HTMLRenderingEngine.class);
private TikaConfig tikaConfig;
/**
* This optional parameter, when set to true, causes only the
* contents of the HTML body to be written out as the rendition.
* By default, the whole of the HTML document is used.
*/
public static final String PARAM_BODY_CONTENTS_ONLY = "bodyContentsOnly";
/**
* This optional parameter, when set to true, causes any embedded
* images to be written into the same folder as the html, with
* a name prefix.
* By default, images are placed into a sub-folder.
*/
public static final String PARAM_IMAGES_SAME_FOLDER = "imagesSameFolder";
/*
* Action constants
*/
public static final String NAME = "htmlRenderingEngine";
@Override
protected Collection<ParameterDefinition> getParameterDefinitions() {
Collection<ParameterDefinition> paramList = super.getParameterDefinitions();
paramList.add(new ParameterDefinitionImpl(PARAM_BODY_CONTENTS_ONLY, DataTypeDefinition.BOOLEAN, false,
getParamDisplayLabel(PARAM_BODY_CONTENTS_ONLY)));
paramList.add(new ParameterDefinitionImpl(PARAM_IMAGES_SAME_FOLDER, DataTypeDefinition.BOOLEAN, false,
getParamDisplayLabel(PARAM_IMAGES_SAME_FOLDER)));
return paramList;
}
/**
* Injects the TikaConfig to use
*
* @param tikaConfig The Tika Config to use
*/
public void setTikaConfig(TikaConfig tikaConfig)
{
this.tikaConfig = tikaConfig;
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.rendition.executer.AbstractRenderingEngine#render(org.alfresco.repo.rendition.executer.AbstractRenderingEngine.RenderingContext)
*/
@Override
protected void render(RenderingContext context)
{
ContentReader contentReader = context.makeContentReader();
String sourceMimeType = contentReader.getMimetype();
// Check that Tika supports the supplied file
AutoDetectParser p = new AutoDetectParser(tikaConfig);
MediaType sourceMediaType = MediaType.parse(sourceMimeType);
if(! p.getParsers().containsKey(sourceMediaType))
{
throw new RenditionServiceException(
"Source mime type of " + sourceMimeType +
" is not supported by Tika for HTML conversions"
);
}
// Make the HTML Version using Tika
// This will also extract out any images as found
generateHTML(p, context);
}
private String getHtmlBaseName(RenderingContext context)
{
// Based on the name of the source node, which will
// also largely be the name of the html node
String baseName = nodeService.getProperty(
context.getSourceNode(),
ContentModel.PROP_NAME
).toString();
if(baseName.lastIndexOf('.') > -1)
{
baseName = baseName.substring(0, baseName.lastIndexOf('.'));
}
return baseName;
}
/**
* What name should be used for the images directory?
* Note this is only required if {@link #PARAM_IMAGES_SAME_FOLDER} is false (the default).
*/
private String getImagesDirectoryName(RenderingContext context)
{
// Based on the name of the source node, which will
// also largely be the name of the html node
String folderName = getHtmlBaseName(context);
folderName = folderName + "_files";
return folderName;
}
/**
* What prefix should be applied to the name of images?
*/
private String getImagesPrefixName(RenderingContext context)
{
if( context.getParamWithDefault(PARAM_IMAGES_SAME_FOLDER, false) )
{
// Prefix with the name of the source node
return getHtmlBaseName(context) + "_";
}
else {
// They have their own folder, so no prefix is needed
return "";
}
}
/**
* Creates a directory to store the images in.
* The directory will be a sibling of the rendered
* HTML, and named similar to it.
* Note this is only required if {@link #PARAM_IMAGES_SAME_FOLDER} is false (the default).
*/
private NodeRef createImagesDirectory(RenderingContext context)
{
// It should be a sibling of the HTML in it's eventual location
// (not it's current temporary one!)
RenditionLocation location = resolveRenditionLocation(
context.getSourceNode(), context.getDefinition(), context.getDestinationNode()
);
NodeRef parent = location.getParentRef();
// Figure out what to call it, based on the HTML node
String folderName = getImagesDirectoryName(context);
// It is already there?
// (eg from when the rendition is being re-run)
NodeRef imgFolder = nodeService.getChildByName(
parent, ContentModel.ASSOC_CONTAINS, folderName
);
if(imgFolder != null)
return imgFolder;
// Create the directory
Map<QName,Serializable> properties = new HashMap<QName,Serializable>();
properties.put(ContentModel.PROP_NAME, folderName);
imgFolder = nodeService.createNode(
parent,
ContentModel.ASSOC_CONTAINS,
QName.createQName(folderName),
ContentModel.TYPE_FOLDER,
properties
).getChildRef();
return imgFolder;
}
private NodeRef createEmbeddedImage(NodeRef imgFolder, boolean primary,
String filename, String contentType, InputStream imageSource,
RenderingContext context)
{
// Create the node if needed
NodeRef img = nodeService.getChildByName(
imgFolder, ContentModel.ASSOC_CONTAINS, filename
);
if(img == null)
{
Map<QName,Serializable> properties = new HashMap<QName,Serializable>();
properties.put(ContentModel.PROP_NAME, filename);
img = nodeService.createNode(
imgFolder,
ContentModel.ASSOC_CONTAINS,
QName.createQName(filename),
ContentModel.TYPE_CONTENT,
properties
).getChildRef();
if (logger.isDebugEnabled())
{
logger.debug("Image node created: " + img);
}
}
// TODO Once composite content is properly supported,
// at this point we'll associate the new image with
// the rendered HTML node so the dependency is tracked.
// Put the image into the node
ContentWriter writer = contentService.getWriter(
img, ContentModel.PROP_CONTENT, true
);
writer.setMimetype(contentType);
writer.putContent(imageSource);
if (logger.isDebugEnabled())
{
logger.debug("Image content written into " + img);
}
// All done
return img;
}
/**
* Builds a Tika-compatible SAX content handler, which will
* be used to generate+capture the XHTML
*/
private ContentHandler buildContentHandler(Writer output, RenderingContext context)
{
// Create the main transformer
SAXTransformerFactory factory = (SAXTransformerFactory)
SAXTransformerFactory.newInstance();
TransformerHandler handler;
try {
handler = factory.newTransformerHandler();
} catch (TransformerConfigurationException e) {
throw new RenditionServiceException("SAX Processing isn't available - " + e);
}
handler.getTransformer().setOutputProperty(OutputKeys.INDENT, "yes");
handler.setResult(new StreamResult(output));
handler.getTransformer().setOutputProperty(OutputKeys.METHOD, "xml");
// Change the image links as they go past
String dirName = null, imgPrefix = null;
if(context.getParamWithDefault(PARAM_IMAGES_SAME_FOLDER, false))
{
imgPrefix = getImagesPrefixName(context);
}
else
{
dirName = getImagesDirectoryName(context);
}
ContentHandler contentHandler = new TikaImageRewritingContentHandler(
handler, dirName, imgPrefix
);
// If required, wrap it to only return the body
boolean bodyOnly = context.getParamWithDefault(PARAM_BODY_CONTENTS_ONLY, false);
if(bodyOnly) {
contentHandler = new BodyContentHandler(contentHandler);
}
// All done
return contentHandler;
}
/**
* Asks Tika to translate the contents into HTML
*/
private void generateHTML(Parser p, RenderingContext context)
{
ContentReader contentReader = context.makeContentReader();
// Setup things to parse with
StringWriter sw = new StringWriter();
ContentHandler handler = buildContentHandler(sw, context);
// Tell Tika what we're dealing with
Metadata metadata = new Metadata();
metadata.set(
Metadata.CONTENT_TYPE,
contentReader.getMimetype()
);
metadata.set(
Metadata.RESOURCE_NAME_KEY,
nodeService.getProperty(
context.getSourceNode(),
ContentModel.PROP_NAME
).toString()
);
// Our parse context needs to extract images
ParseContext parseContext = new ParseContext();
parseContext.set(Parser.class, new TikaImageExtractingParser(context));
// Parse
try {
p.parse(
contentReader.getContentInputStream(),
handler, metadata, parseContext
);
} catch(Exception e) {
throw new RenditionServiceException("Tika HTML Conversion Failed", e);
}
// As a string
String html = sw.toString();
// If we're doing body-only, remove all the html namespaces
// that will otherwise clutter up the document
boolean bodyOnly = context.getParamWithDefault(PARAM_BODY_CONTENTS_ONLY, false);
if(bodyOnly) {
html = html.replaceAll("<\\?xml.*?\\?>", "");
html = html.replaceAll("<p xmlns=\"http://www.w3.org/1999/xhtml\"","<p");
html = html.replaceAll("<h(\\d) xmlns=\"http://www.w3.org/1999/xhtml\"","<h\\1");
html = html.replaceAll("<div xmlns=\"http://www.w3.org/1999/xhtml\"","<div");
html = html.replaceAll("<table xmlns=\"http://www.w3.org/1999/xhtml\"","<table");
html = html.replaceAll("&#13;","");
}
// Save it
ContentWriter contentWriter = context.makeContentWriter();
contentWriter.setMimetype("text/html");
contentWriter.putContent( html );
}
/**
* A nested Tika parser which extracts out any
* images as they come past.
*/
@SuppressWarnings("serial")
private class TikaImageExtractingParser implements Parser {
private Set<MediaType> types;
private RenderingContext renderingContext;
private NodeRef imgFolder = null;
private int count = 0;
private TikaImageExtractingParser(RenderingContext renderingContext) {
this.renderingContext = renderingContext;
// Our expected types
types = new HashSet<MediaType>();
types.add(MediaType.image("bmp"));
types.add(MediaType.image("gif"));
types.add(MediaType.image("jpg"));
types.add(MediaType.image("jpeg"));
types.add(MediaType.image("png"));
types.add(MediaType.image("tiff"));
// Are images going in the same place as the HTML?
if( renderingContext.getParamWithDefault(PARAM_IMAGES_SAME_FOLDER, false) )
{
RenditionLocation location = resolveRenditionLocation(
renderingContext.getSourceNode(), renderingContext.getDefinition(),
renderingContext.getDestinationNode()
);
imgFolder = location.getParentRef();
if (logger.isDebugEnabled())
{
logger.debug("Using imgFolder: " + imgFolder);
}
}
}
@Override
public Set<MediaType> getSupportedTypes(ParseContext context) {
return types;
}
@Override
public void parse(InputStream stream, ContentHandler handler,
Metadata metadata, ParseContext context) throws IOException,
SAXException, TikaException {
// Is it a supported image?
String filename = metadata.get(Metadata.RESOURCE_NAME_KEY);
String type = metadata.get(Metadata.CONTENT_TYPE);
boolean accept = false;
if(type != null) {
for(MediaType mt : types) {
if(mt.toString().equals(type)) {
accept = true;
}
}
}
if(filename != null) {
for(MediaType mt : types) {
String ext = "." + mt.getSubtype();
if(filename.endsWith(ext)) {
accept = true;
}
}
}
if(!accept)
return;
handleImage(stream, filename, type);
}
private void handleImage(InputStream stream, String filename, String type) {
count++;
// Do we already have the folder? If not, create it
if(imgFolder == null) {
imgFolder = createImagesDirectory(renderingContext);
}
// Give it a sensible name if needed
if(filename == null) {
filename = "image-" + count + ".";
filename += type.substring(type.indexOf('/')+1);
}
// Prefix the filename if needed
filename = getImagesPrefixName(renderingContext) + filename;
// Save the image
createEmbeddedImage(imgFolder, (count==1), filename, type, stream, renderingContext);
}
}
/**
* A content handler that re-writes image src attributes,
* and passes everything else on to the real one.
*/
private class TikaImageRewritingContentHandler extends ContentHandlerDecorator {
private String imageFolder;
private String imagePrefix;
private TikaImageRewritingContentHandler(ContentHandler handler, String imageFolder, String imagePrefix) {
super(handler);
this.imageFolder = imageFolder;
this.imagePrefix = imagePrefix;
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes origAttrs) throws SAXException {
// If we have an image tag, re-write the src attribute
// if required
if("img".equals(localName)) {
AttributesImpl attrs;
if(origAttrs instanceof AttributesImpl) {
attrs = (AttributesImpl)origAttrs;
} else {
attrs = new AttributesImpl(origAttrs);
}
for(int i=0; i<attrs.getLength(); i++) {
if("src".equals(attrs.getLocalName(i))) {
String src = attrs.getValue(i);
if(src.startsWith("embedded:")) {
String newSrc = "";
if(imageFolder != null)
newSrc += imageFolder + "/";
if(imagePrefix != null)
newSrc += imagePrefix;
newSrc += src.substring(src.indexOf(':')+1);
attrs.setValue(i, newSrc);
}
}
}
super.startElement(uri, localName, qName, attrs);
} else {
// For any other tag, pass through as-is
super.startElement(uri, localName, qName, origAttrs);
}
}
}
}

View File

@@ -26,6 +26,9 @@
package org.alfresco.repo.search;
import org.alfresco.error.AlfrescoRuntimeException;
import org.apache.http.HttpStatus;
import java.util.List;
/**
* @author Andy
@@ -33,11 +36,10 @@ import org.alfresco.error.AlfrescoRuntimeException;
*/
public class QueryParserException extends AlfrescoRuntimeException
{
/**
*
*/
/** Serial version UUID. */
private static final long serialVersionUID = 4886993838297301968L;
/** Http Status Code that should be returned by Remote API. */
private int httpStatusCode;
/**
* @param msgId
@@ -45,7 +47,6 @@ public class QueryParserException extends AlfrescoRuntimeException
public QueryParserException(String msgId)
{
super(msgId);
// TODO Auto-generated constructor stub
}
/**
@@ -55,7 +56,6 @@ public class QueryParserException extends AlfrescoRuntimeException
public QueryParserException(String msgId, Object[] msgParams)
{
super(msgId, msgParams);
// TODO Auto-generated constructor stub
}
/**
@@ -65,7 +65,6 @@ public class QueryParserException extends AlfrescoRuntimeException
public QueryParserException(String msgId, Throwable cause)
{
super(msgId, cause);
// TODO Auto-generated constructor stub
}
/**
@@ -76,7 +75,22 @@ public class QueryParserException extends AlfrescoRuntimeException
public QueryParserException(String msgId, Object[] msgParams, Throwable cause)
{
super(msgId, msgParams, cause);
// TODO Auto-generated constructor stub
}
/**
* Constructor for exception that allows setting an HTTP status code.
*
* @param msgId Message for the exception
* @param httpStatusCode Status code to return for exception
*/
public QueryParserException(String msgId, int httpStatusCode)
{
super(msgId);
this.httpStatusCode = httpStatusCode;
}
public int getHttpStatusCode()
{
return httpStatusCode;
}
}

View File

@@ -1,28 +1,28 @@
/*
* #%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 - 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.search.impl.querymodel.impl.db;
import java.util.ArrayList;
@@ -74,6 +74,10 @@ public class DBQuery extends BaseQuery implements DBQueryBuilderComponent
Set<String> selectorGroup;
private int limit = 0;
private int offset = 0;
/**
* @param source Source
* @param constraint Constraint
@@ -133,6 +137,22 @@ public class DBQuery extends BaseQuery implements DBQueryBuilderComponent
this.sinceTxId = sinceTxId;
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public List<DBQueryBuilderJoinCommand> getJoins()
{
HashMap<QName, DBQueryBuilderJoinCommand> singleJoins = new HashMap<QName, DBQueryBuilderJoinCommand>();

View File

@@ -41,9 +41,13 @@ import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.EqualsHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class NodePermissionAssessor
{
protected static final Log logger = LogFactory.getLog(NodePermissionAssessor.class);
private final boolean isSystemReading;
private final boolean isAdminReading;
private final boolean isNullReading;
@@ -138,24 +142,31 @@ public class NodePermissionAssessor
public void setMaxPermissionChecks(int maxPermissionChecks)
{
this.maxPermissionChecks = maxPermissionChecks;
if (maxPermissionChecks == Integer.MAX_VALUE)
{
this.maxPermissionChecks = maxPermissionChecks;
}
else
{
this.maxPermissionChecks = maxPermissionChecks + 1;
}
}
public boolean shouldQuitChecks()
{
boolean result = false;
if (checksPerformed >= maxPermissionChecks)
{
result = true;
logger.warn("Maximum permission checks exceeded (" + maxPermissionChecks + ")");
return true;
}
if ((System.currentTimeMillis() - startTime) >= maxPermissionCheckTimeMillis)
{
result = true;
logger.warn("Maximum permission checks time exceeded (" + maxPermissionCheckTimeMillis + ")");
return true;
}
return result;
return false;
}
public void setMaxPermissionCheckTimeMillis(long maxPermissionCheckTimeMillis)

View File

@@ -29,26 +29,29 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.search.QueryParserException;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
public abstract class AbstractSolrQueryHTTPClient
{
/** Logger for the class. */
private static final Log LOGGER = LogFactory.getLog(AbstractSolrQueryHTTPClient.class);
public static final int DEFAULT_SAVEPOST_BUFFER = 4096;
// Constants copied from org.apache.solr.common.params.HighlightParams (solr-solrj:1.4.1)
@@ -79,11 +82,13 @@ public abstract class AbstractSolrQueryHTTPClient
public static final String HIGHLIGHT_PARAMS_SLOP = HIGHLIGHT_PARAMS_HIGHLIGHT + "." + HIGHLIGHT_PARAMS_REGEX + ".slop";
public static final String HIGHLIGHT_PARAMS_PATTERN = HIGHLIGHT_PARAMS_HIGHLIGHT + "." + HIGHLIGHT_PARAMS_REGEX + ".pattern";
public static final String HIGHLIGHT_PARAMS_MAX_RE_CHARS = HIGHLIGHT_PARAMS_HIGHLIGHT + "." + HIGHLIGHT_PARAMS_REGEX + ".maxAnalyzedChars";
/** List of SOLR Exceptions that should be returning HTTP 501 status code in Remote API. */
private static final List<String> STATUS_CODE_501_EXCEPTIONS = List.of("java.lang.UnsupportedOperationException");
protected JSONObject postQuery(HttpClient httpClient, String url, JSONObject body) throws UnsupportedEncodingException,
IOException, HttpException, URIException, JSONException
protected JSONObject postQuery(HttpClient httpClient, String url, JSONObject body) throws IOException, JSONException
{
PostMethod post = new PostMethod(url);
PostMethod post = createNewPostMethod(url);
if (body.toString().length() > DEFAULT_SAVEPOST_BUFFER)
{
post.getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, true);
@@ -103,9 +108,33 @@ public abstract class AbstractSolrQueryHTTPClient
httpClient.executeMethod(post);
}
}
String responseBodyStr = post.getResponseBodyAsString();
if (post.getStatusCode() != HttpServletResponse.SC_OK)
{
throw new QueryParserException("Request failed " + post.getStatusCode() + " " + url.toString());
String trace = null;
try
{
trace = new JSONObject(responseBodyStr).getJSONObject("error").getString("trace");
}
catch (JSONException jsonException)
{
LOGGER.warn("Node 'error.trace' is not present in Search Services error response: " + responseBodyStr);
LOGGER.warn("A generic error message will be provided. Check SOLR log file in order to find the root cause for this issue");
}
int httpStatusCode = post.getStatusCode();
String message = "Solr request failed with " + httpStatusCode + " " + url;
// Override the status code for certain exceptions with 501.
if (trace != null)
{
String traceException = trace.substring(0, trace.indexOf(":")).trim();
if (STATUS_CODE_501_EXCEPTIONS.contains(traceException))
{
httpStatusCode = org.apache.http.HttpStatus.SC_NOT_IMPLEMENTED;
}
}
throw new QueryParserException(message, httpStatusCode);
}
Reader reader = new BufferedReader(new InputStreamReader(post.getResponseBodyAsStream(), post.getResponseCharSet()));
@@ -118,4 +147,10 @@ public abstract class AbstractSolrQueryHTTPClient
post.releaseConnection();
}
}
/** Helper method that can be overridden by unit tests. */
protected PostMethod createNewPostMethod(String url)
{
return new PostMethod(url);
}
}

View File

@@ -456,12 +456,20 @@ public class RepoUsageComponentImpl implements RepoUsageComponent
}
}
// Check the license expiry
// Check the license expiration
Long licenseExpiryDate = restrictions.getLicenseExpiryDate();
if (licenseExpiryDate != null)
{
//For informational purposes, get the remaining number of days, counting from the beginning of the day of each date (now and expiration date)
int remainingDays = DateUtil.calculateDays(System.currentTimeMillis(), licenseExpiryDate);
if (remainingDays <= 0)
int remainingMills = 0;
if (remainingDays == 0)
{
//Get exact number of milliseconds between license expiration time and now to see if is expired
remainingMills = DateUtil.calculateMs(System.currentTimeMillis(), licenseExpiryDate);
}
if (remainingDays < 0 || remainingMills < 0)
{
errors.add(I18NUtil.getMessage("system.usage.err.limit_license_expired"));
level = RepoUsageLevel.LOCKED_DOWN;

View File

@@ -322,7 +322,7 @@ public class CombinedConfig
{
combinedTransformers.remove(indexToRemove);
// this may also require the current index i to be changed so we don't skip one.
if (i <= indexToRemove)
if (i >= indexToRemove)
{
i--;
}

View File

@@ -71,4 +71,34 @@ public class DateUtil
}
return days;
}
/**
* Calculate the number of milliseconds between start and end dates based on the <b>default</b> timezone.
* If the end date is before the start date, the returned value is negative.
*
* @param startMs start date in milliseconds
* @param endMs end date in milliseconds
* @return number milliseconds between
*/
public static int calculateMs(long startMs, long endMs)
{
DateTime startDateTime = new DateTime(startMs);
DateTime endDateTime = new DateTime(endMs);
int milliseconds;
if (endDateTime.isBefore(startDateTime))
{
Interval interval = new Interval(endDateTime, startDateTime);
Period period = interval.toPeriod(PeriodType.millis());
milliseconds = 0 - period.getMillis();
}
else
{
Interval interval = new Interval(startDateTime, endDateTime);
Period period = interval.toPeriod(PeriodType.millis());
milliseconds = period.getMillis();
}
return milliseconds;
}
}

View File

@@ -180,7 +180,8 @@
</choose>
</foreach>
</if>
</if>
</sql>
</if>
<if test="limit != 0">limit #{offset}, #{limit}</if>
</sql>
</mapper>

View File

@@ -178,14 +178,6 @@
</property>
</bean>
<bean id="htmlRenderingEngine"
class="org.alfresco.repo.rendition.executer.HTMLRenderingEngine"
parent="baseRenderingAction">
<property name="tikaConfig">
<ref bean="tikaConfig"/>
</property>
</bean>
<bean id="compositeRenderingEngine"
class="org.alfresco.repo.rendition.executer.CompositeRenderingEngine"
parent="baseRenderingAction">

View File

@@ -3,7 +3,7 @@
repository.name=Main Repository
# Schema number
version.schema=14100
version.schema=14200
# Directory configuration
@@ -153,6 +153,7 @@ system.cache.parentAssocs.limitFactor=8
system.acl.maxPermissionCheckTimeMillis=10000
# The maximum number of search results to perform permission checks against
system.acl.maxPermissionChecks=1000
system.acl.maxPermissionCheckEnabled=false
# The maximum number of filefolder list results
system.filefolderservice.defaultListMaxResults=5000
@@ -1236,4 +1237,7 @@ system.new-node-transaction-indexes.ignored=true
# Allows the configuration of maximum limits of the temp files to be deleted or the maximum time allowed to run for the job
system.tempFileCleaner.maxFilesToDelete=
system.tempFileCleaner.maxTimeToRun=
system.tempFileCleaner.maxTimeToRun=
# pre-configured allow list of media/mime types to allow inline instead of attachment (via Content-Disposition response header)
content.nonAttach.mimetypes=application/pdf,image/jpeg,image/gif,image/png,image/tiff,image/bmp

View File

@@ -35,7 +35,7 @@
<property name="cronExpression" value="0 30 * * * ?" /> <!-- Repeat hourly on the half hour -->
<property name="startDelay" value="${system.cronJob.startDelayMilliseconds}"/>
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<bean id="tempFileCleanerJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="org.alfresco.util.TempFileProvider$TempFileCleanerJob"/>
<property name="jobDataAsMap">
<map>
@@ -51,7 +51,7 @@
<property name="cronExpression" value="0 0 * * * ?" /> <!-- Repeat hourly on the start hour -->
<property name="startDelay" value="${system.cronJob.startDelayMilliseconds}"/>
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<bean id="webscripts.tempFileCleanerJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="org.alfresco.util.TempFileProvider$TempFileCleanerJob"/>
<property name="jobDataAsMap">
<map>
@@ -68,7 +68,7 @@
<property name="cronExpression" value="${system.content.orphanCleanup.cronExpression}"/>
<property name="startDelay" value="${system.cronJob.startDelayMilliseconds}"/>
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<bean id="contentStoreCleanerJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="org.alfresco.repo.content.cleanup.ContentStoreCleanupJob"/>
<property name="jobDataAsMap">
<map>
@@ -82,7 +82,7 @@
<property name="cronExpression" value="${system.patch.sharedFolder.cronExpression}"/>
<property name="startDelay" value="${system.cronJob.startDelayMilliseconds}"/>
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<bean id="patchSharedFolderJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="org.alfresco.repo.admin.patch.impl.SharedFolderPatch$SharedFolderPatchJob"/>
<property name="jobDataAsMap">
<map>
@@ -96,7 +96,7 @@
<property name="cronExpression" value="${system.maximumStringLength.jobCronExpression}"/>
<property name="startDelay" value="${system.cronJob.startDelayMilliseconds}"/>
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<bean id="maxStringLengthJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="org.alfresco.repo.node.db.NodeStringLengthWorker$NodeStringLengthJob"/>
<property name="jobDataAsMap">
<map>
@@ -110,7 +110,7 @@
<property name="cronExpression" value="0 0 21 * * ?"/>
<property name="startDelay" value="${system.cronJob.startDelayMilliseconds}"/>
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<bean id="nodeServiceCleanupJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="org.alfresco.repo.node.cleanup.NodeCleanupJob"/>
<property name="jobDataAsMap">
<map>
@@ -124,7 +124,7 @@
<property name="cronExpression" value="0 0/5 * * * ?"/> <!-- run every 5 minutes -->
<property name="startDelay" value="${system.cronJob.startDelayMilliseconds}"/>
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<bean id="userUsageTrackingJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="org.alfresco.repo.usage.UserUsageCollapseJob"/>
<property name="jobDataAsMap">
<map>
@@ -140,7 +140,7 @@
<property name="repeatInterval" value="3600000"/> <!-- 60 minutes -->
<property name="startDelay" value="120"/>
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<bean id="taggingStartupJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="org.alfresco.repo.tagging.UpdateTagScopesQuartzJob"/>
<property name="jobDataAsMap">
<map>
@@ -157,7 +157,7 @@
<property name="cronExpression" value="${ticket.cleanup.cronExpression}"/>
<property name="startDelay" value="${system.cronJob.startDelayMilliseconds}"/>
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<bean id="ticketCleanupJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="org.alfresco.repo.security.authentication.TicketCleanupJob"/>
<property name="jobDataAsMap">
<map>
@@ -171,7 +171,7 @@
<property name="cronExpression" value="${system.patch.surfConfigFolder.cronExpression}"/>
<property name="startDelay" value="${system.cronJob.startDelayMilliseconds}"/>
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<bean id="patchSurfConfigFolderJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="org.alfresco.repo.admin.patch.AsynchronousPatch$AsynchronousPatchJob"/>
<property name="jobDataAsMap">
<map>
@@ -186,7 +186,7 @@
<property name="cronExpression" value="${system.upgradePasswordHash.jobCronExpression}"/>
<property name="startDelay" value="${system.cronJob.startDelayMilliseconds}"/>
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<bean id="upgradePasswordHashJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="org.alfresco.repo.admin.patch.AsynchronousPatch$AsynchronousPatchJob"/>
<property name="jobDataAsMap">
<map>
@@ -201,7 +201,7 @@
<property name="cronExpression" value="${system.patch.addUnmovableAspect.cronExpression}"/>
<property name="startDelay" value="${system.cronJob.startDelayMilliseconds}"/>
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<bean id="patchAddUnmovableAspectJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="org.alfresco.repo.admin.patch.AsynchronousPatch$AsynchronousPatchJob"/>
<property name="jobDataAsMap">
<map>
@@ -216,7 +216,7 @@
<property name="cronExpression" value="${system.fixedACLsUpdater.cronExpression}"/>
<property name="startDelay" value="${system.cronJob.startDelayMilliseconds}"/>
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<bean id="fixedAclUpdaterJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="org.alfresco.repo.domain.permissions.FixedAclUpdaterJob"/>
<property name="jobDataAsMap">
<map>

View File

@@ -105,8 +105,35 @@
<ref bean="metadataQueryIndexesCheck2" />
</property>
</bean>
<bean id="search.dbQueryEngineImpl" class="org.alfresco.repo.search.impl.querymodel.impl.db.DBQueryEngine" >
<bean id="search.dbQueryEngineImpl" class="org.alfresco.util.bean.HierarchicalBeanLoader">
<property name="targetBeanName">
<value>search.dbQueryEngineImpl.#bean.dialect#</value>
</property>
<property name="targetClass">
<value>org.alfresco.repo.search.impl.querymodel.QueryEngine</value>
</property>
<property name="dialectBaseClass">
<value>org.alfresco.repo.domain.dialect.Dialect</value>
</property>
<property name="dialectClass">
<bean class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetBeanName" value="dialect" />
<property name="propertyPath" value="class.name" />
</bean>
</property>
</bean>
<bean id="search.dbQueryEngineImpl.org.alfresco.repo.domain.dialect.Dialect"
parent="search.baseDbQueryEngineImpl">
<property name="usePagingQuery" value="false"/>
</bean>
<bean id="search.dbQueryEngineImpl.org.alfresco.repo.domain.dialect.MySQLInnoDBDialect"
parent="search.baseDbQueryEngineImpl">
<property name="usePagingQuery" value="true"/>
</bean>
<bean id="search.baseDbQueryEngineImpl" class="org.alfresco.repo.search.impl.querymodel.impl.db.DBQueryEngine" abstract="true">
<property name="permissionService" ref="permissionService"/>
<property name="dictionaryService" ref="dictionaryService" />
<property name="namespaceService" ref="namespaceService" />
@@ -126,6 +153,9 @@
<property name="maxPermissionCheckTimeMillis">
<value>${system.acl.maxPermissionCheckTimeMillis}</value>
</property>
<property name="maxPermissionCheckEnabled">
<value>${system.acl.maxPermissionCheckEnabled}</value>
</property>
</bean>
<bean id="search.dbQueryEngine" class="org.springframework.aop.framework.ProxyFactoryBean">

View File

@@ -20,7 +20,7 @@
<property name="cronExpression" value="${solr.backup.alfresco.cronExpression}"/>
<property name="startDelay" value="${system.cronJob.startDelayMilliseconds}"/>
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<bean id="search.alfrescoCoreBackupJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="org.alfresco.repo.search.impl.solr.SolrBackupJob"/>
<property name="jobDataAsMap">
<map>

View File

@@ -117,31 +117,6 @@
"imageMagickOptions"
]
},
{
"transformerName": "htmlToPdfViaOdt",
"transformerPipeline" : [
{"transformerName": "libreoffice", "targetMediaType": "application/vnd.oasis.opendocument.text"},
{"transformerName": "libreoffice"}
],
"supportedSourceAndTargetList": [
{"sourceMediaType": "text/html", "targetMediaType": "application/pdf" }
],
"transformOptions": [
]
},
{
"transformerName": "htmlToImageViaPdf",
"transformerPipeline" : [
{"transformerName": "htmlToPdfViaOdt", "targetMediaType": "application/pdf"},
{"transformerName": "pdfToImageViaPng"}
],
"supportedSourceAndTargetList": [
],
"transformOptions": [
"pdfRendererOptions",
"imageMagickOptions"
]
},
{
"transformerName": "ooXmlToImageViaText",
"transformerPipeline" : [
@@ -198,42 +173,66 @@
"archiveOptions"
]
},
{
"transformerName": "libreofficeHtmlToPdfViaOdt",
"transformerPipeline" : [
{"transformerName": "libreoffice", "targetMediaType": "application/vnd.oasis.opendocument.text"},
{"transformerName": "libreoffice"}
],
"supportedSourceAndTargetList": [
{"sourceMediaType": "text/html", "targetMediaType": "application/pdf" }
],
"transformOptions": [
]
},
{
"transformerName": "libreofficeToPdf",
"transformerFailover" : [ "libreoffice", "libreofficeHtmlToPdfViaOdt" ],
"supportedSourceAndTargetList": [
{"sourceMediaType": "application/vnd.oasis.opendocument.graphics", "priority": 150, "targetMediaType": "application/pdf" },
{"sourceMediaType": "application/vnd.sun.xml.calc.template", "priority": 150, "targetMediaType": "application/pdf" },
{"sourceMediaType": "application/vnd.sun.xml.impress.template", "priority": 150, "targetMediaType": "application/pdf" },
{"sourceMediaType": "application/vnd.sun.xml.writer.template", "priority": 150, "targetMediaType": "application/pdf" },
{"sourceMediaType": "text/tab-separated-values", "priority": 150, "targetMediaType": "application/pdf" },
{"sourceMediaType": "application/vnd.visio2013", "priority": 150, "targetMediaType": "application/pdf" },
{"sourceMediaType": "application/wordperfect", "priority": 150, "targetMediaType": "application/pdf" },
{"sourceMediaType": "application/vnd.sun.xml.calc", "priority": 150, "targetMediaType": "application/pdf" },
{"sourceMediaType": "application/vnd.sun.xml.impress", "priority": 150, "targetMediaType": "application/pdf" }
],
"transformOptions": [
]
},
{
"transformerName": "libreofficeToPdfBoxViaPdf",
"transformerPipeline" : [
{"transformerName": "libreofficeToPdf", "targetMediaType": "application/pdf"},
{"transformerName": "libreoffice", "targetMediaType": "application/pdf"},
{"transformerName": "PdfBox"}
],
"supportedSourceAndTargetList": [
{"sourceMediaType": "application/vnd.oasis.opendocument.graphics", "priority": 150, "targetMediaType": "text/csv"},
{"sourceMediaType": "application/vnd.oasis.opendocument.graphics", "priority": 150, "targetMediaType": "text/html"},
{"sourceMediaType": "application/vnd.oasis.opendocument.graphics", "maxSourceSizeBytes": 26214400, "priority": 150, "targetMediaType": "text/plain"},
{"sourceMediaType": "application/vnd.oasis.opendocument.graphics", "priority": 150, "targetMediaType": "application/xhtml+xml"},
{"sourceMediaType": "application/vnd.oasis.opendocument.graphics", "priority": 150, "targetMediaType": "text/xml"},
{"sourceMediaType": "application/vnd.sun.xml.calc.template", "priority": 150, "targetMediaType": "text/csv"},
{"sourceMediaType": "application/vnd.sun.xml.calc.template", "priority": 150, "targetMediaType": "text/html"},
{"sourceMediaType": "application/vnd.sun.xml.calc.template", "maxSourceSizeBytes": 26214400, "priority": 150, "targetMediaType": "text/plain"},
{"sourceMediaType": "application/vnd.sun.xml.calc.template", "priority": 150, "targetMediaType": "application/xhtml+xml"},
{"sourceMediaType": "application/vnd.sun.xml.calc.template", "priority": 150, "targetMediaType": "text/xml"},
{"sourceMediaType": "application/vnd.sun.xml.impress.template", "priority": 150, "targetMediaType": "text/csv"},
{"sourceMediaType": "application/vnd.sun.xml.impress.template", "priority": 150, "targetMediaType": "text/html"},
{"sourceMediaType": "application/vnd.sun.xml.impress.template", "maxSourceSizeBytes": 26214400, "priority": 150, "targetMediaType": "text/plain"},
{"sourceMediaType": "application/vnd.sun.xml.impress.template", "priority": 150, "targetMediaType": "application/xhtml+xml"},
{"sourceMediaType": "application/vnd.sun.xml.impress.template", "priority": 150, "targetMediaType": "text/xml"},
{"sourceMediaType": "application/vnd.sun.xml.writer.template", "priority": 150, "targetMediaType": "text/csv"},
{"sourceMediaType": "application/vnd.sun.xml.writer.template", "priority": 150, "targetMediaType": "text/html"},
{"sourceMediaType": "application/vnd.sun.xml.writer.template", "maxSourceSizeBytes": 26214400, "priority": 150, "targetMediaType": "text/plain"},
{"sourceMediaType": "application/vnd.sun.xml.writer.template", "priority": 150, "targetMediaType": "application/xhtml+xml"},
{"sourceMediaType": "application/vnd.sun.xml.writer.template", "priority": 150, "targetMediaType": "text/xml"},
{"sourceMediaType": "text/tab-separated-values", "priority": 150, "targetMediaType": "text/csv"},
{"sourceMediaType": "text/tab-separated-values", "priority": 150, "targetMediaType": "text/html"},
{"sourceMediaType": "text/tab-separated-values", "maxSourceSizeBytes": 26214400, "priority": 150, "targetMediaType": "text/plain"},
{"sourceMediaType": "text/tab-separated-values", "priority": 150, "targetMediaType": "application/xhtml+xml"},
{"sourceMediaType": "text/tab-separated-values", "priority": 150, "targetMediaType": "text/xml"},
{"sourceMediaType": "application/vnd.visio2013", "priority": 150, "targetMediaType": "text/csv"},
{"sourceMediaType": "application/vnd.visio2013", "priority": 150, "targetMediaType": "text/html"},
{"sourceMediaType": "application/vnd.visio2013", "maxSourceSizeBytes": 26214400, "priority": 150, "targetMediaType": "text/plain"},
{"sourceMediaType": "application/vnd.visio2013", "priority": 150, "targetMediaType": "application/xhtml+xml"},
{"sourceMediaType": "application/vnd.visio2013", "priority": 150, "targetMediaType": "text/xml"},
{"sourceMediaType": "application/wordperfect", "priority": 150, "targetMediaType": "text/csv"},
{"sourceMediaType": "application/wordperfect", "priority": 150, "targetMediaType": "text/html"},
{"sourceMediaType": "application/wordperfect", "maxSourceSizeBytes": 26214400, "priority": 150, "targetMediaType": "text/plain"},
{"sourceMediaType": "application/wordperfect", "priority": 150, "targetMediaType": "application/xhtml+xml"},
{"sourceMediaType": "application/wordperfect", "priority": 150, "targetMediaType": "text/xml"},
{"sourceMediaType": "application/vnd.sun.xml.calc", "priority": 150, "targetMediaType": "text/csv"},
{"sourceMediaType": "application/vnd.sun.xml.calc", "priority": 150, "targetMediaType": "text/html"},
{"sourceMediaType": "application/vnd.sun.xml.calc", "maxSourceSizeBytes": 26214400, "priority": 150, "targetMediaType": "text/plain"},
{"sourceMediaType": "application/vnd.sun.xml.calc", "priority": 150, "targetMediaType": "application/xhtml+xml"},
{"sourceMediaType": "application/vnd.sun.xml.calc", "priority": 150, "targetMediaType": "text/xml"},
{"sourceMediaType": "application/vnd.sun.xml.impress", "priority": 150, "targetMediaType": "text/csv"},
{"sourceMediaType": "application/vnd.sun.xml.impress", "priority": 150, "targetMediaType": "text/html"},
{"sourceMediaType": "application/vnd.sun.xml.impress", "maxSourceSizeBytes": 26214400, "priority": 150, "targetMediaType": "text/plain"},
{"sourceMediaType": "application/vnd.sun.xml.impress", "priority": 150, "targetMediaType": "application/xhtml+xml"},
{"sourceMediaType": "application/vnd.sun.xml.impress", "priority": 150, "targetMediaType": "text/xml"}
],
"transformOptions": [
"pdfboxOptions"
@@ -263,6 +262,32 @@
"transformOptions": [
"tikaOptions"
]
},
{
"transformerName": "htmlToPdfViaTXT",
"transformerPipeline" : [
{"transformerName": "string", "targetMediaType": "text/plain"},
{"transformerName": "libreoffice"}
],
"supportedSourceAndTargetList": [
{"sourceMediaType": "text/html", "targetMediaType": "application/pdf" }
],
"transformOptions": [
]
},
{
"transformerName": "htmlToImageViaTXT",
"transformerPipeline" : [
{"transformerName": "string", "targetMediaType": "text/plain"},
{"transformerName": "textToImageViaPdf"}
],
"supportedSourceAndTargetList": [
{"sourceMediaType": "text/html", "targetMediaType": "image/png" }
],
"transformOptions": [
"pdfRendererOptions",
"imageMagickOptions"
]
}
]
}
}

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -77,12 +77,17 @@ import org.junit.runners.Suite;
// From MiscContextTestSuite
org.alfresco.repo.domain.query.CannedQueryDAOTest.class,
// REPO-2963 : Tests causing a cascade of failures in AllDBTestsTestSuite on PostgreSQL/MySQL
// ACS-1907
org.alfresco.repo.search.impl.querymodel.impl.db.ACS1907Test.class,
// REPO-2963 : Tests causing a cascade of failures in AllDBTestsTestSuite on PostgreSQL/MySQL
// Moved at the bottom of the suite because DbNodeServiceImplTest.testNodeCleanupRegistry() takes a long time on a clean DB.
org.alfresco.repo.node.db.DbNodeServiceImplTest.class,
org.alfresco.repo.node.cleanup.TransactionCleanupTest.class,
org.alfresco.repo.security.person.GetPeopleCannedQueryTest.class
org.alfresco.repo.security.person.GetPeopleCannedQueryTest.class,
org.alfresco.repo.domain.schema.script.DeleteNotExistsExecutorTest.class
})
public class AllDBTestsTestSuite
{

View File

@@ -111,14 +111,15 @@ import org.junit.runners.Suite;
org.alfresco.util.schemacomp.validator.SchemaVersionValidatorTest.class,
org.alfresco.util.schemacomp.validator.TypeNameOnlyValidatorTest.class,
org.alfresco.util.test.junitrules.TemporaryMockOverrideTest.class,
org.alfresco.repo.search.impl.solr.AbstractSolrQueryHTTPClientTest.class,
org.alfresco.repo.search.impl.solr.SpellCheckDecisionManagerTest.class,
org.alfresco.repo.search.impl.solr.SolrStoreMappingWrapperTest.class,
org.alfresco.repo.search.impl.solr.SolrQueryHTTPClientTest.class,
org.alfresco.repo.search.impl.solr.SolrSQLHttpClientTest.class,
org.alfresco.repo.search.impl.solr.SolrStatsResultTest.class,
org.alfresco.repo.search.impl.solr.facet.SolrFacetComparatorTest.class,
org.alfresco.repo.search.impl.solr.facet.FacetQNameUtilsTest.class,
org.alfresco.util.BeanExtenderUnitTest.class,
org.alfresco.repo.search.impl.solr.SpellCheckDecisionManagerTest.class,
org.alfresco.repo.search.impl.solr.SolrStoreMappingWrapperTest.class,
org.alfresco.repo.security.authentication.CompositePasswordEncoderTest.class,
org.alfresco.repo.security.authentication.PasswordHashingTest.class,
org.alfresco.traitextender.TraitExtenderIntegrationTest.class,

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -39,7 +39,7 @@ import org.junit.runners.Suite;
@RunWith(Categories.class)
@Categories.ExcludeCategory({DBTests.class, NonBuildTests.class})
@Suite.SuiteClasses({
// there is a test that runs for 184s and another one that runs for 40s
org.alfresco.repo.attributes.AttributeServiceTest.class,
@@ -66,7 +66,9 @@ import org.junit.runners.Suite;
org.alfresco.repo.content.RoutingContentStoreTest.class,
org.alfresco.encryption.EncryptionTests.class,
org.alfresco.encryption.KeyStoreTests.class
org.alfresco.encryption.KeyStoreTests.class,
org.alfresco.repo.content.MimetypeMapContentTest.class
// TODO REPO-2791 org.alfresco.repo.content.routing.StoreSelectorAspectContentStoreTest.class,
})

View File

@@ -56,7 +56,6 @@ import org.junit.runners.Suite;
// This test opens, closes and again opens the alfresco application context.
org.alfresco.repo.dictionary.CustomModelRepoRestartTest.class,
org.alfresco.repo.rendition.executer.HTMLRenderingEngineTest.class,
org.alfresco.repo.rendition.executer.XSLTFunctionsTest.class,
org.alfresco.repo.rendition.executer.XSLTRenderingEngineTest.class,
org.alfresco.repo.replication.ReplicationServiceIntegrationTest.class,

View File

@@ -75,7 +75,6 @@ import org.junit.runners.Suite;
org.alfresco.repo.site.SiteServiceImplTest.class,
// [classpath:alfresco/application-context.xml, classpath:scriptexec/script-exec-test.xml]
org.alfresco.repo.domain.schema.script.DeleteNotExistsExecutorTest.class,
org.alfresco.repo.domain.schema.script.ScriptExecutorImplIntegrationTest.class,
org.alfresco.repo.domain.schema.script.ScriptBundleExecutorImplIntegrationTest.class,

View File

@@ -26,8 +26,8 @@
package org.alfresco.repo.action;
import static java.lang.Thread.sleep;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -39,6 +39,7 @@ import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.executer.ActionExecuter;
import org.alfresco.repo.action.executer.ContentMetadataExtracter;
import org.alfresco.repo.action.executer.CounterIncrementActionExecuter;
import org.alfresco.repo.action.executer.ScriptActionExecuter;
@@ -259,7 +260,7 @@ public class ActionServiceImpl2Test
public void testExecuteScript() throws Exception
{
final NodeRef scriptToBeExecuted = addTempScript("changeFileNameTest.js",
"document.properties.name = \"Changed\" + \"_\" + document.properties.name;\ndocument.save();");
"document.properties.name = \"Changed_\" + document.properties.name;\ndocument.save();");
assertNotNull("Failed to add the test script.", scriptToBeExecuted);
// add a test file to the Site in order to change its name
@@ -310,6 +311,73 @@ public class ActionServiceImpl2Test
return null;
}
});
//Execute script not in Data Dictionary > Scripts
AuthenticationUtil.setFullyAuthenticatedUser(testSiteAndMemberInfo.siteManager);
NodeRef companyHomeRef = wellKnownNodes.getCompanyHome();
NodeRef sharedFolderRef = nodeService.getChildByName(companyHomeRef, ContentModel.ASSOC_CONTAINS,
"Shared");
final NodeRef invalidScriptRef = addTempScript("changeFileNameTest.js",
"document.properties.name = \"Invalid_Change.pdf\";\ndocument.save();",sharedFolderRef);
assertNotNull("Failed to add the test script.", scriptToBeExecuted);
transactionHelper.doInTransaction(new RetryingTransactionCallback<Void>()
{
public Void execute() throws Throwable
{
// Create the action
Action action = actionService.createAction(ScriptActionExecuter.NAME);
action.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, invalidScriptRef);
try
{
// Execute the action
actionService.executeAction(action, testNode);
}
catch (Throwable th)
{
// do nothing
}
assertFalse("Scripts outside of Data Dictionary Scripts folder should not be executed",
("Invalid_Change.pdf".equals(nodeService.getProperty(testNode, ContentModel.PROP_NAME))));
return null;
}
});
}
@Test
public void testActionResult() throws Exception
{
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
transactionHelper.doInTransaction(new RetryingTransactionCallback<Void>()
{
public Void execute() throws Throwable
{
try
{
// Create the script node reference
NodeRef script = addTempScript("test-action-result-script.js", "\"VALUE\";");
// Create the action
Action action = actionService.createAction(ScriptActionExecuter.NAME);
action.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, script);
// Execute the action
actionService.executeAction(action, testNode);
// Get the result
String result = (String) action.getParameterValue(ActionExecuter.PARAM_RESULT);
assertNotNull(result);
assertEquals("VALUE", result);
}
finally
{
AuthenticationUtil.clearCurrentSecurityContext();
}
return null;
}
});
}
@Test
@@ -369,6 +437,32 @@ public class ActionServiceImpl2Test
});
}
private NodeRef addTempScript(final String scriptFileName, final String javaScript, final NodeRef parentRef)
{
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
return transactionHelper.doInTransaction(new RetryingTransactionCallback<NodeRef>()
{
public NodeRef execute() throws Throwable
{
// Create the script node reference
NodeRef script = nodeService.createNode(parentRef, ContentModel.ASSOC_CONTAINS,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, scriptFileName),
ContentModel.TYPE_CONTENT).getChildRef();
nodeService.setProperty(script, ContentModel.PROP_NAME, scriptFileName);
ContentWriter contentWriter = contentService.getWriter(script, ContentModel.PROP_CONTENT, true);
contentWriter.setMimetype(MimetypeMap.MIMETYPE_JAVASCRIPT);
contentWriter.setEncoding("UTF-8");
contentWriter.putContent(javaScript);
tempNodes.addNodeRef(script);
return script;
}
});
}
private NodeRef addTempScript(final String scriptFileName, final String javaScript)
{
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
@@ -386,20 +480,7 @@ public class ActionServiceImpl2Test
NodeRef scriptsRef = nodeService.getChildByName(dataDictionaryRef, ContentModel.ASSOC_CONTAINS,
"Scripts");
// Create the script node reference
NodeRef script = nodeService.createNode(scriptsRef, ContentModel.ASSOC_CONTAINS,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, scriptFileName),
ContentModel.TYPE_CONTENT).getChildRef();
nodeService.setProperty(script, ContentModel.PROP_NAME, scriptFileName);
ContentWriter contentWriter = contentService.getWriter(script, ContentModel.PROP_CONTENT, true);
contentWriter.setMimetype(MimetypeMap.MIMETYPE_JAVASCRIPT);
contentWriter.setEncoding("UTF-8");
contentWriter.putContent(javaScript);
tempNodes.addNodeRef(script);
return script;
return addTempScript(scriptFileName, javaScript, scriptsRef);
}
});
}

View File

@@ -805,46 +805,6 @@ public class ActionServiceImplTest extends BaseAlfrescoSpringTest
assertEquals(action4, savedAction2.getAction(2));
}
/**
* Test the action result parameter
*/
@Test
public void testActionResult()
{
// We need to run this test as Administrator. The ScriptAction has to run as a full user (instead of as System)
// so that we can setup the Person object in the ScriptNode
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
try
{
// Create the script node reference
NodeRef script = this.nodeService.createNode(
this.folder,
ContentModel.ASSOC_CONTAINS,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "testScript.js"),
ContentModel.TYPE_CONTENT).getChildRef();
this.nodeService.setProperty(script, ContentModel.PROP_NAME, "testScript.js");
ContentWriter contentWriter = this.contentService.getWriter(script, ContentModel.PROP_CONTENT, true);
contentWriter.setMimetype("text/plain");
contentWriter.setEncoding("UTF-8");
contentWriter.putContent("\"VALUE\";");
// Create the action
Action action1 = this.actionService.createAction(ScriptActionExecuter.NAME);
action1.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, script);
// Execute the action
this.actionService.executeAction(action1, this.nodeRef);
// Get the result
String result = (String)action1.getParameterValue(ActionExecuter.PARAM_RESULT);
assertNotNull(result);
assertEquals("VALUE", result);
}
finally
{
AuthenticationUtil.clearCurrentSecurityContext();
}
}
/** ===================================================================================
* Test asynchronous actions

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* Copyright (C) 2005 - 2021 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,125 +23,138 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import junit.framework.TestCase;
import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.test_category.OwnJVMTestsCategory;
import org.alfresco.util.DataModelTestApplicationContextHelper;
import org.apache.poi.util.IOUtils;
import org.junit.experimental.categories.Category;
import org.springframework.context.ApplicationContext;
/**
* Content specific tests for MimeTypeMap
*
* @see org.alfresco.repo.content.MimetypeMap
* @see org.alfresco.repo.content.MimetypeMapTest
*/
@Category(OwnJVMTestsCategory.class)
public class MimetypeMapContentTest extends TestCase
{
private static ApplicationContext ctx = DataModelTestApplicationContextHelper.getApplicationContext();
private MimetypeService mimetypeService;
@Override
public void setUp() throws Exception
{
mimetypeService = (MimetypeService)ctx.getBean("mimetypeService");
}
public void testGuessMimetypeForFile() throws Exception
{
// Correct ones
assertEquals(
"application/msword",
mimetypeService.guessMimetype("something.doc", openQuickTestFile("quick.doc"))
);
assertEquals(
"application/msword",
mimetypeService.guessMimetype("SOMETHING.DOC", openQuickTestFile("quick.doc"))
);
// Incorrect ones, Tika spots the mistake
assertEquals(
"application/msword",
mimetypeService.guessMimetype("something.pdf", openQuickTestFile("quick.doc"))
);
assertEquals(
"application/pdf",
mimetypeService.guessMimetype("something.doc", openQuickTestFile("quick.pdf"))
);
// Ones where we use a different mimetype to the canonical one
assertEquals(
"image/bmp", // Officially image/x-ms-bmp
mimetypeService.guessMimetype("image.bmp", openQuickTestFile("quick.bmp"))
);
// Ones where we know about the parent, and Tika knows about the details
assertEquals(
"application/dita+xml", // Full version: application/dita+xml;format=concept
mimetypeService.guessMimetype("concept.dita", openQuickTestFile("quickConcept.dita"))
);
// Alfresco Specific ones, that Tika doesn't know about
assertEquals(
"application/acp",
mimetypeService.guessMimetype("something.acp", openQuickTestFile("quick.acp"))
);
// Where the file is corrupted
File tmp = File.createTempFile("alfresco", ".tmp");
ContentReader reader = openQuickTestFile("quick.doc");
InputStream inp = reader.getContentInputStream();
byte[] trunc = new byte[512+256];
IOUtils.readFully(inp, trunc);
inp.close();
FileOutputStream out = new FileOutputStream(tmp);
out.write(trunc);
out.close();
ContentReader truncReader = new FileContentReader(tmp);
// Because the file is truncated, Tika won't be able to process the contents
// of the OLE2 structure
// So, it'll fall back to just OLE2, but it won't fail
assertEquals(
"application/x-tika-msoffice",
mimetypeService.guessMimetype(null, truncReader)
);
// But with the filename it'll be able to use the .doc extension
// to guess at it being a .Doc file
assertEquals(
"application/msword",
mimetypeService.guessMimetype("something.doc", truncReader)
);
// Lotus notes EML files (ALF-16381 / TIKA-1042)
assertEquals(
"message/rfc822",
mimetypeService.guessMimetype("something.eml", openQuickTestFile("quickLotus.eml"))
);
}
private ContentReader openQuickTestFile(String filename)
{
URL url = getClass().getClassLoader().getResource("quick/" + filename);
if(url == null)
{
fail("Quick test file \"" + filename + "\" wasn't found");
}
File file = new File(url.getFile());
return new FileContentReader(file);
}
}
package org.alfresco.repo.content;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import junit.framework.TestCase;
import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.test_category.OwnJVMTestsCategory;
import org.alfresco.util.ApplicationContextHelper;
import org.apache.poi.util.IOUtils;
import org.junit.experimental.categories.Category;
import org.springframework.context.ApplicationContext;
/**
* Content specific tests for MimeTypeMap
*
* @see org.alfresco.repo.content.MimetypeMap
* @see org.alfresco.repo.content.MimetypeMapTest
*/
@Category({OwnJVMTestsCategory.class})
public class MimetypeMapContentTest extends TestCase
{
private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
private MimetypeService mimetypeService;
@Override
public void setUp() throws Exception
{
mimetypeService = (MimetypeService)ctx.getBean("mimetypeService");
}
public void testGuessPdfMimetype() throws Exception
{
assertEquals(
"application/pdf",
mimetypeService.guessMimetype("something.doc", openQuickTestFile("quick.pdf"))
);
assertEquals(
"application/pdf",
mimetypeService.guessMimetype(null, openQuickTestFile("quick.pdf"))
);
}
public void testGuessMimetypeForFile() throws Exception
{
// Correct ones
assertEquals(
"application/msword",
mimetypeService.guessMimetype("something.doc", openQuickTestFile("quick.doc"))
);
assertEquals(
"application/msword",
mimetypeService.guessMimetype("SOMETHING.DOC", openQuickTestFile("quick.doc"))
);
// Incorrect ones, Tika spots the mistake
assertEquals(
"application/msword",
mimetypeService.guessMimetype("something.pdf", openQuickTestFile("quick.doc"))
);
// Ones where we use a different mimetype to the canonical one
assertEquals(
"image/bmp", // Officially image/x-ms-bmp
mimetypeService.guessMimetype("image.bmp", openQuickTestFile("quick.bmp"))
);
// Ones where we know about the parent, and Tika knows about the details
assertEquals(
"application/dita+xml", // Full version: application/dita+xml;format=concept
mimetypeService.guessMimetype("concept.dita", openQuickTestFile("quickConcept.dita"))
);
// Commented out when the test class was reintroduced after many years of not being run. Failed as the type was
// identified as a zip. Reintroduced to check guessMimetype works without pdfbox libraries.
//
// // Alfresco Specific ones, that Tika doesn't know about
// assertEquals(
// "application/acp",
// mimetypeService.guessMimetype("something.acp", openQuickTestFile("quick.acp"))
// );
// Where the file is corrupted
File tmp = File.createTempFile("alfresco", ".tmp");
ContentReader reader = openQuickTestFile("quick.doc");
InputStream inp = reader.getContentInputStream();
byte[] trunc = new byte[512+256];
IOUtils.readFully(inp, trunc);
inp.close();
FileOutputStream out = new FileOutputStream(tmp);
out.write(trunc);
out.close();
ContentReader truncReader = new FileContentReader(tmp);
// Because the file is truncated, Tika won't be able to process the contents
// of the OLE2 structure
// So, it'll fall back to just OLE2, but it won't fail
assertEquals(
"application/x-tika-msoffice",
mimetypeService.guessMimetype(null, truncReader)
);
// Commented out when the test class was reintroduced after many years of not being run. Failed to open a
// stream onto the channel. Reintroduced to check guessMimetype works without pdfbox libraries.
//
// // But with the filename it'll be able to use the .doc extension
// // to guess at it being a .Doc file
// assertEquals(
// "application/msword",
// mimetypeService.guessMimetype("something.doc", truncReader)
// );
// Lotus notes EML files (ALF-16381 / TIKA-1042)
assertEquals(
"message/rfc822",
mimetypeService.guessMimetype("something.eml", openQuickTestFile("quickLotus.eml"))
);
}
private ContentReader openQuickTestFile(String filename)
{
URL url = getClass().getClassLoader().getResource("quick/" + filename);
if(url == null)
{
fail("Quick test file \"" + filename + "\" wasn't found");
}
File file = new File(url.getFile());
return new FileContentReader(file);
}
}

View File

@@ -35,10 +35,14 @@ import java.util.Properties;
import javax.sql.DataSource;
import org.alfresco.repo.domain.dialect.Dialect;
import org.alfresco.repo.domain.dialect.MySQLInnoDBDialect;
import org.alfresco.util.ApplicationContextHelper;
import org.alfresco.util.testing.category.DBTests;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.mockito.Mockito;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
@@ -48,11 +52,13 @@ import org.springframework.jdbc.core.JdbcTemplate;
*
* @author Cristian Turlica
*/
@Category({DBTests.class})
public class DeleteNotExistsExecutorTest
{
private static ApplicationContext ctx;
private ScriptExecutor scriptExecutor;
private DataSource dataSource;
private Dialect dialect;
private JdbcTemplate jdbcTmpl;
@BeforeClass
@@ -67,9 +73,20 @@ public class DeleteNotExistsExecutorTest
{
scriptExecutor = ctx.getBean("simpleScriptExecutor", ScriptExecutorImpl.class);
dataSource = ctx.getBean("dataSource", DataSource.class);
dialect = ctx.getBean("dialect", Dialect.class);
jdbcTmpl = new JdbcTemplate(dataSource);
}
private DeleteNotExistsExecutor createDeleteNotExistsExecutor(Connection connection, String sql, int line, File scriptFile, Properties properties)
{
if (dialect instanceof MySQLInnoDBDialect)
{
return new MySQLDeleteNotExistsExecutor(connection, sql, line, scriptFile, properties, dataSource);
}
return new DeleteNotExistsExecutor(connection, sql, line, scriptFile, properties);
}
@Test()
public void testDefaultBehaviour() throws Exception
{
@@ -90,7 +107,7 @@ public class DeleteNotExistsExecutorTest
{
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_READ_ONLY)).thenReturn("true");
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_TIMEOUT_SECONDS)).thenReturn("-1");
DeleteNotExistsExecutor deleteNotExistsExecutor = new DeleteNotExistsExecutor(connection, sql, line, scriptFile, properties);
DeleteNotExistsExecutor deleteNotExistsExecutor = createDeleteNotExistsExecutor(connection, sql, line, scriptFile, properties);
deleteNotExistsExecutor.execute();
List<String> res = jdbcTmpl.queryForList(select, String.class);
@@ -100,7 +117,7 @@ public class DeleteNotExistsExecutorTest
{
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_READ_ONLY)).thenReturn("false");
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_TIMEOUT_SECONDS)).thenReturn("-1");
DeleteNotExistsExecutor deleteNotExistsExecutor = new DeleteNotExistsExecutor(connection, sql, line, scriptFile, properties);
DeleteNotExistsExecutor deleteNotExistsExecutor = createDeleteNotExistsExecutor(connection, sql, line, scriptFile, properties);
deleteNotExistsExecutor.execute();
List<String> res = jdbcTmpl.queryForList(select, String.class);
@@ -133,7 +150,7 @@ public class DeleteNotExistsExecutorTest
{
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_DELETE_BATCH_SIZE)).thenReturn("1");
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_READ_ONLY)).thenReturn("false");
DeleteNotExistsExecutor deleteNotExistsExecutor = new DeleteNotExistsExecutor(connection, sql, line, scriptFile, properties);
DeleteNotExistsExecutor deleteNotExistsExecutor = createDeleteNotExistsExecutor(connection, sql, line, scriptFile, properties);
deleteNotExistsExecutor.execute();
List<String> res = jdbcTmpl.queryForList(select, String.class);
@@ -167,7 +184,7 @@ public class DeleteNotExistsExecutorTest
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_BATCH_SIZE)).thenReturn("2");
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_READ_ONLY)).thenReturn("false");
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_TIMEOUT_SECONDS)).thenReturn("-1");
DeleteNotExistsExecutor deleteNotExistsExecutor = new DeleteNotExistsExecutor(connection, sql, line, scriptFile, properties);
DeleteNotExistsExecutor deleteNotExistsExecutor = createDeleteNotExistsExecutor(connection, sql, line, scriptFile, properties);
deleteNotExistsExecutor.execute();
List<String> res = jdbcTmpl.queryForList(select, String.class);

View File

@@ -1,31 +1,30 @@
/*
* #%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 - 2021 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.rendition;
import org.alfresco.repo.rendition.executer.HTMLRenderingEngineTest;
import org.alfresco.repo.thumbnail.ThumbnailServiceImplParameterTest;
import org.alfresco.repo.thumbnail.ThumbnailServiceImplTest;
import org.alfresco.repo.thumbnail.conditions.NodeEligibleForRethumbnailingEvaluatorTest;
@@ -49,7 +48,6 @@ import org.junit.runners.Suite;
RenditionServiceIntegrationTest.class,
RenditionServicePermissionsTest.class,
RenditionNodeManagerTest.class,
HTMLRenderingEngineTest.class,
MultiUserRenditionTest.class
})
public class AllRenditionTests

View File

@@ -1,543 +0,0 @@
/*
* #%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.rendition.executer;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.transform.AbstractContentTransformerTest;
import org.alfresco.repo.model.Repository;
import org.alfresco.repo.rendition.RenditionDefinitionPersisterImpl;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.rendition.RenditionDefinition;
import org.alfresco.service.cmr.rendition.RenditionService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
import org.alfresco.test_category.BaseSpringTestsCategory;
import org.alfresco.test_category.OwnJVMTestsCategory;
import org.alfresco.util.BaseAlfrescoSpringTest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.springframework.transaction.annotation.Transactional;
/**
* Unit tests for the HTML Rendering Engine
*
* @author Nick Burch
*
* @deprecated We are introducing the new async RenditionService2.
*/
@Deprecated
@Category(BaseSpringTestsCategory.class)
@Transactional
public class HTMLRenderingEngineTest extends BaseAlfrescoSpringTest
{
private final static Log log = LogFactory.getLog(HTMLRenderingEngineTest.class);
private NodeRef companyHome;
private DictionaryService dictionaryService;
private RenditionService renditionService;
private Repository repositoryHelper;
private NodeRef sourceDoc;
private NodeRef targetFolder;
private String targetFolderPath;
private RenditionDefinition def;
private static final String MIMETYPE_DOC = "application/msword";
private static final String MIMETYPE_DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
@Before
public void before() throws Exception
{
super.before();
this.nodeService = (NodeService) this.applicationContext.getBean("NodeService");
this.contentService = (ContentService) this.applicationContext.getBean("ContentService");
this.renditionService = (RenditionService) this.applicationContext.getBean("RenditionService");
this.repositoryHelper = (Repository) this.applicationContext.getBean("repositoryHelper");
this.dictionaryService = (DictionaryService) this.applicationContext.getBean("dictionaryService");
this.companyHome = repositoryHelper.getCompanyHome();
createTargetFolder();
// Setup the basic rendition definition
QName renditionName = QName.createQName("Test");
RenditionDefinition rd = renditionService.loadRenditionDefinition(renditionName);
if(rd != null)
{
RenditionDefinitionPersisterImpl rdp = new RenditionDefinitionPersisterImpl();
rdp.setNodeService(nodeService);
rdp.deleteRenditionDefinition(rd);
}
def = renditionService.createRenditionDefinition(renditionName, HTMLRenderingEngine.NAME);
}
@After
public void after() throws Exception
{
super.after();
tidyUpSourceDoc();
}
private void createTargetFolder()
{
// Set the current security context as admin
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
Map<QName,Serializable> properties = new HashMap<QName,Serializable>();
properties.put(ContentModel.PROP_NAME, "TestFolder");
targetFolder = nodeService.createNode(
companyHome, ContentModel.ASSOC_CONTAINS,
QName.createQName("TestFolder"),
ContentModel.TYPE_FOLDER,
properties
).getChildRef();
targetFolderPath = "/" +
(String) nodeService.getProperty(companyHome, ContentModel.PROP_NAME) +
"/" +
(String) nodeService.getProperty(targetFolder, ContentModel.PROP_NAME)
;
}
private void tidyUpSourceDoc()
{
// Set the current security context as admin
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
// Clean up the source
if(sourceDoc != null)
{
nodeService.deleteNode(sourceDoc);
}
// Clean up the target folder
nodeService.deleteNode(targetFolder);
targetFolder = null;
// All done
sourceDoc = null;
createTargetFolder();
}
private NodeRef createForDoc(String docname) throws IOException
{
// Create the node
Map<QName,Serializable> properties = new HashMap<QName,Serializable>();
properties.put(ContentModel.PROP_NAME, docname);
NodeRef node = nodeService.createNode(
companyHome, ContentModel.ASSOC_CONTAINS,
QName.createQName(docname),
ContentModel.TYPE_CONTENT,
properties
).getChildRef();
// Put the sample doc into it
File f = AbstractContentTransformerTest.loadNamedQuickTestFile(docname);
if(f == null) {
fail("Unable to find test file for " + docname);
}
ContentWriter writer = contentService.getWriter(
node, ContentModel.PROP_CONTENT, true
);
if(docname.endsWith(".doc")) {
writer.setMimetype(MIMETYPE_DOC);
}
if(docname.endsWith(".docx")) {
writer.setMimetype(MIMETYPE_DOCX);
}
writer.putContent(f);
if (log.isDebugEnabled())
{
log.debug("Created document with name: " + docname + ", nodeRef: " + node + ", mimetype: " + writer.getMimetype());
}
// All done
return node;
}
@Test
public void testBasics() throws Exception
{
def.setParameterValue(
RenditionService.PARAM_DESTINATION_PATH_TEMPLATE,
targetFolderPath + "/${name}.html"
);
sourceDoc = createForDoc("quick.doc");
ChildAssociationRef rendition = renditionService.render(sourceDoc, def);
assertNotNull(rendition);
// Check it was created
NodeRef htmlNode = rendition.getChildRef();
assertEquals(true, nodeService.exists(htmlNode));
// Check it got the right name
assertEquals(
"quick.html",
nodeService.getProperty(htmlNode, ContentModel.PROP_NAME)
);
// Check it got the right contents
ContentReader reader = contentService.getReader(
htmlNode, ContentModel.PROP_CONTENT
);
String html = reader.getContentString();
assertEquals("<?xml", html.substring(0, 5));
assertTrue("HTML wrong:\n"+html, html.contains("<html"));
assertTrue("HTML wrong:\n"+html, html.contains("<head>"));
assertTrue("HTML wrong:\n"+html, html.contains("<body>"));
assertTrue("HTML wrong:\n"+html, html.contains("<p>The quick brown fox"));
// Now do a body-only one, check that we still got the
// contents, but not the html surround
def.setParameterValue(
HTMLRenderingEngine.PARAM_BODY_CONTENTS_ONLY, Boolean.TRUE
);
rendition = renditionService.render(sourceDoc, def);
assertNotNull(rendition);
htmlNode = rendition.getChildRef();
assertEquals(true, nodeService.exists(htmlNode));
reader = contentService.getReader(
htmlNode, ContentModel.PROP_CONTENT
);
html = reader.getContentString();
assertFalse("Body wrong:\n"+html, html.contains("<?xml"));
assertFalse("Body wrong:\n"+html, html.contains("<html"));
assertFalse("Body wrong:\n"+html, html.contains("<head>"));
assertFalse("Body wrong:\n"+html, html.contains("<body>"));
assertTrue("HTML wrong:\n"+html, html.contains("<p>The quick brown fox"));
assertTrue("HTML wrong:\n"+html, html.contains("</p>"));
}
/**
* Test for a .doc and a .docx, neither of which have images
*/
@Test
public void testDocWithoutImages() throws Exception
{
def.setParameterValue(
RenditionService.PARAM_DESTINATION_PATH_TEMPLATE,
targetFolderPath + "/${name}.html"
);
for(String name : new String[] {"quick.doc","quick.docx"})
{
sourceDoc = createForDoc(name);
int numItemsStart = nodeService.getChildAssocs(targetFolder).size();
ChildAssociationRef rendition = renditionService.render(sourceDoc, def);
assertNotNull(rendition);
// Check it was created
NodeRef htmlNode = rendition.getChildRef();
assertEquals(true, nodeService.exists(htmlNode));
// Check it got the right name
assertEquals(
name.substring(0, name.lastIndexOf('.')) + ".html",
nodeService.getProperty(htmlNode, ContentModel.PROP_NAME)
);
// Check it ended up in the right place
assertEquals(
"Should have been in " + targetFolderPath + " but was in" +
nodeService.getPath(htmlNode),
targetFolder,
nodeService.getPrimaryParent(htmlNode).getParentRef()
);
// Check it got the right contents
ContentReader reader = contentService.getReader(
htmlNode, ContentModel.PROP_CONTENT
);
String html = reader.getContentString();
assertEquals("<?xml", html.substring(0, 5));
// Check we didn't get an image folder, only the html
int numItems = nodeService.getChildAssocs(targetFolder).size();
assertEquals(numItemsStart+1, numItems);
// Check that the html lacks img tags
assertEquals(
"Unexpected img tag in html:\n" + html,
false, html.contains("<img")
);
// Check we didn't get any images
for(ChildAssociationRef ref : nodeService.getChildAssocs(htmlNode))
{
// TODO Check against composite content associations when present
// if(ref.getTypeQName().equals(HTMLRenderingEngine.PRIMARY_IMAGE))
// fail("Found unexpected primary image of rendered html");
// if(ref.getTypeQName().equals(HTMLRenderingEngine.SECONDARY_IMAGE))
// fail("Found unexpected secondary image of rendered html");
}
// All done
tidyUpSourceDoc();
}
}
/**
* Test for a .doc and a .docx, both of which have
* images in them
*/
@Test
public void testDocWithImages() throws Exception
{
def.setParameterValue(
RenditionService.PARAM_DESTINATION_PATH_TEMPLATE,
targetFolderPath + "/${name}.html"
);
String[] files = new String[] {"quickImg1.doc","quickImg1.docx", "quickImg3.doc","quickImg3.docx"};
int[] imgCounts = new int[] {1,1, 3,3};
for(int i=0; i<files.length; i++)
{
String name = files[i];
sourceDoc = createForDoc(name);
String baseName = name.substring(0, name.lastIndexOf('.'));
int numItemsStart = nodeService.getChildAssocs(targetFolder).size();
ChildAssociationRef rendition = renditionService.render(sourceDoc, def);
assertNotNull(rendition);
// Check it was created
NodeRef htmlNode = rendition.getChildRef();
assertEquals(true, nodeService.exists(htmlNode));
// Check it got the right name
assertEquals(
baseName + ".html",
nodeService.getProperty(htmlNode, ContentModel.PROP_NAME)
);
// Check it ended up in the right place
assertEquals(
"Should have been in " + targetFolderPath + " but was in" +
nodeService.getPath(htmlNode),
targetFolder,
nodeService.getPrimaryParent(htmlNode).getParentRef()
);
// Check it got the right contents
ContentReader reader = contentService.getReader(
htmlNode, ContentModel.PROP_CONTENT
);
String html = reader.getContentString();
assertEquals("<?xml", html.substring(0, 5));
// Check that the html has the img tags
assertEquals(
"Couldn't find img tag in html:\n" + html,
true, html.contains("<img")
);
// Check that it has the right img src
String expSource = "src=\""+ baseName + "_files" + "/image";
assertEquals(
"Couldn't find correct img src in html:\n" + expSource + "\n" + html,
true, html.contains(expSource)
);
// Check we got an image folder
int numItems = nodeService.getChildAssocs(targetFolder).size();
assertEquals(numItemsStart+2, numItems);
// Check the name of the image folder
NodeRef imgFolder = null;
for(ChildAssociationRef ref : nodeService.getChildAssocs(targetFolder)) {
if(nodeService.getProperty(ref.getChildRef(), ContentModel.PROP_NAME).equals(
baseName + "_files"
)) {
imgFolder = ref.getChildRef();
}
}
assertNotNull("Couldn't find new folder named " + baseName + "_files", imgFolder);
// Check the contents
assertEquals(imgCounts[i], nodeService.getChildAssocs(imgFolder).size());
// TODO Check against composite content associations when present
// Check the associations if supported
// if(dictionaryService.getAssociation(HTMLRenderingEngine.PRIMARY_IMAGE) != null)
// {
// boolean hasPrimary = false;
// boolean hasSecondary = false;
// for(ChildAssociationRef ref : nodeService.getChildAssocs(htmlNode))
// {
// if(ref.getTypeQName().equals(HTMLRenderingEngine.PRIMARY_IMAGE))
// hasPrimary = true;
// if(ref.getTypeQName().equals(HTMLRenderingEngine.SECONDARY_IMAGE))
// hasSecondary = true;
// }
// assertEquals(true, hasPrimary);
// assertEquals(false, hasSecondary);
// }
// All done
tidyUpSourceDoc();
}
}
/**
* Test for the option to have the images written to the
* same folder as the html, with a name prefix to them.
*
* TODO Re-enable when we've figured out why the rendition service sulkts
*/
@Test
public void testImagesSameFolder() throws Exception
{
def.setParameterValue(
RenditionService.PARAM_DESTINATION_PATH_TEMPLATE,
targetFolderPath + "/${name}.html"
);
def.setParameterValue(
HTMLRenderingEngine.PARAM_IMAGES_SAME_FOLDER,
true
);
// The documents listed below have 3 embedded images each.
final int expectedImageCount = 3;
for(String name : new String[] {"quickImg3.doc","quickImg3.docx"})
{
sourceDoc = createForDoc(name);
String baseName = name.substring(0, name.lastIndexOf('.'));
int numItemsStart = nodeService.getChildAssocs(targetFolder).size();
if (log.isDebugEnabled())
{
log.debug("targetFolder " + targetFolder + " has " + numItemsStart + " children at start.");
}
ChildAssociationRef rendition = renditionService.render(sourceDoc, def);
assertNotNull(rendition);
// Check it was created
NodeRef htmlNode = rendition.getChildRef();
assertEquals(true, nodeService.exists(htmlNode));
// Check it got the right name
assertEquals(
baseName + ".html",
nodeService.getProperty(htmlNode, ContentModel.PROP_NAME)
);
// Check it ended up in the right place
assertEquals(
"Should have been in " + targetFolderPath + " but was in" +
nodeService.getPath(htmlNode),
targetFolder,
nodeService.getPrimaryParent(htmlNode).getParentRef()
);
// Check it got the right contents
ContentReader reader = contentService.getReader(
htmlNode, ContentModel.PROP_CONTENT
);
String html = reader.getContentString();
assertEquals("<?xml", html.substring(0, 5));
// Check that the html has the img tags
assertEquals(
"Couldn't find img tag in html:\n" + html,
true, html.contains("<img")
);
// Check that it has the right img src
String expSource = "src=\""+ baseName + "_image";
assertEquals(
"Couldn't find correct img src in html:\n" + expSource + "\n" + html,
true, html.contains(expSource)
);
// Check we got an image folder
int numItems = nodeService.getChildAssocs(targetFolder).size();
// We expect a number of images and one text/html node to be created.
final int additionalItems = expectedImageCount + 1;
assertEquals(numItemsStart+additionalItems, numItems);
// There shouldn't be an image folder created
for(ChildAssociationRef ref : nodeService.getChildAssocs(targetFolder)) {
if(nodeService.getProperty(ref.getChildRef(), ContentModel.PROP_NAME).equals(
baseName + "_files"
)) {
fail("Image folder was created but shouldn't be there");
}
}
// Check we got the images in the same directory as the html
int images = 0;
for(ChildAssociationRef ref : nodeService.getChildAssocs(targetFolder)) {
String childName = (String)nodeService.getProperty(ref.getChildRef(), ContentModel.PROP_NAME);
if(childName.startsWith(baseName + "_image")) {
images++;
}
}
assertEquals(expectedImageCount, images);
// Until the rendition service supports a forced overwrite of other renditions, we must
// delete the old rendition node & the images.
nodeService.deleteNode(rendition.getChildRef());
for (ChildAssociationRef chAssRef : nodeService.getChildAssocs(targetFolder))
{
nodeService.deleteNode(chAssRef.getChildRef());
}
}
}
}

View File

@@ -0,0 +1,260 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2021 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.search.impl.querymodel.impl.db;
import junit.framework.TestCase;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.cache.TransactionalCache;
import org.alfresco.repo.management.subsystems.SwitchableApplicationContextFactory;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.MutableAuthenticationDao;
import org.alfresco.repo.security.permissions.AccessControlList;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.*;
import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.test_category.OwnJVMTestsCategory;
import org.alfresco.util.ApplicationContextHelper;
import org.alfresco.util.testing.category.DBTests;
import org.junit.experimental.categories.Category;
import org.springframework.context.ApplicationContext;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@Category({OwnJVMTestsCategory.class, DBTests.class})
public class ACS1907Test extends TestCase
{
private ApplicationContext ctx;
private NodeService nodeService;
private AuthenticationComponent authenticationComponent;
private MutableAuthenticationService authenticationService;
private MutableAuthenticationDao authenticationDAO;
private SearchService pubSearchService;
private PermissionService pubPermissionService;
private TransactionService transactionService;
private RetryingTransactionHelper txnHelper;
private DBQueryEngine queryEngine;
private TransactionalCache<Serializable, AccessControlList> aclCache;
private TransactionalCache<Serializable, Object> aclEntityCache;
private TransactionalCache<Serializable, Object> permissionEntityCache;
private NodeRef rootNodeRef;
@Override
public void setUp() throws Exception
{
setupServices();
this.authenticationComponent.setSystemUserAsCurrentUser();
rootNodeRef = nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
setupTestUsers();
setupTestContent();
dropCaches();
}
@Override
protected void tearDown() throws Exception
{
authenticationComponent.clearCurrentSecurityContext();
}
private void setupServices()
{
ctx = ApplicationContextHelper.getApplicationContext();
nodeService = (NodeService) ctx.getBean("dbNodeService");
authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
authenticationService = (MutableAuthenticationService) ctx.getBean("authenticationService");
authenticationDAO = (MutableAuthenticationDao) ctx.getBean("authenticationDao");
pubSearchService = (SearchService) ctx.getBean("SearchService");
pubPermissionService = (PermissionService) ctx.getBean("PermissionService");
transactionService = (TransactionService) ctx.getBean("TransactionService");
aclCache = (TransactionalCache) ctx.getBean("aclCache");
aclEntityCache = (TransactionalCache) ctx.getBean("aclEntityCache");
permissionEntityCache = (TransactionalCache) ctx.getBean("permissionEntityCache");
SwitchableApplicationContextFactory searchContextFactory = (SwitchableApplicationContextFactory) ctx.getBean("Search");
ApplicationContext searchCtx = searchContextFactory.getApplicationContext();
queryEngine = (DBQueryEngine) searchCtx.getBean("search.dbQueryEngineImpl");
txnHelper = new RetryingTransactionHelper();
txnHelper.setTransactionService(transactionService);
txnHelper.setReadOnly(false);
txnHelper.setMaxRetries(1);
txnHelper.setMinRetryWaitMs(1);
txnHelper.setMaxRetryWaitMs(10);
txnHelper.setRetryWaitIncrementMs(1);
}
private void setupTestUser(String userName)
{
if (!authenticationDAO.userExists(userName))
{
authenticationService.createAuthentication(userName, userName.toCharArray());
}
}
private void setupTestUsers()
{
txnHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Object>() {
@Override
public Object execute() throws Throwable {
setupTestUser("userA");
setupTestUser("userB");
setupTestUser(AuthenticationUtil.getAdminUserName());
return null;
}
}, false, false);
}
private void setupTestContent()
{
for(int f = 0; f < 5; f++)
{
final int ff = f;
txnHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Object>() {
@Override
public Object execute() throws Throwable {
Map<QName, Serializable> testFolderProps = new HashMap<>();
testFolderProps.put(ContentModel.PROP_NAME, "folder"+ff);
NodeRef testFolder = nodeService.createNode(
rootNodeRef,
ContentModel.ASSOC_CHILDREN,
QName.createQName("https://example.com/test", "folder"+ff),
ContentModel.TYPE_FOLDER,
testFolderProps
).getChildRef();
for(int c = 0; c < 5; c++)
{
Map<QName, Serializable> testContentProps = new HashMap<>();
testContentProps.put(ContentModel.PROP_NAME, "content"+c);
NodeRef testContent = nodeService.createNode(
testFolder,
ContentModel.ASSOC_CONTAINS,
QName.createQName("https://example.com/test", "content"+c),
ContentModel.TYPE_CONTENT,
testContentProps
).getChildRef();
String user = c % 2 == 0 ? "userA" : "userB";
pubPermissionService.setPermission(testContent, user, "Read", true);
}
return null;
}
}, false, false);
}
}
private void dropCaches()
{
aclCache.clear();
aclEntityCache.clear();
permissionEntityCache.clear();
}
public void testACS1907()
{
txnHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Object>() {
@Override
public Object execute() throws Throwable {
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>() {
@Override
public Object doWork() throws Exception {
SearchParameters sp = new SearchParameters();
sp.addStore(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
sp.setLanguage(SearchService.LANGUAGE_FTS_ALFRESCO);
sp.setQueryConsistency(QueryConsistency.TRANSACTIONAL);
sp.setQuery("TYPE:\"cm:content\"");
ResultSet rs = pubSearchService.query(sp);
int cnt = 0;
for (ResultSetRow row : rs)
{
assertNotNull(row.getValue(ContentModel.PROP_NAME));
cnt++;
}
return null;
}
}, "userA");
return null;
}
}, false, false);
}
public void testPaging()
{
HashSet<NodeRef> resultPageSize2 = queryNodes(2);
HashSet<NodeRef> resultPageSize5 = queryNodes(5);
HashSet<NodeRef> resultPageSize10 = queryNodes(10);
HashSet<NodeRef> resultPageSizeAll = queryNodes(10000);
// all result sets must be equal, independent of page size used to retrieve them
assertTrue(resultPageSize2.size() >= 25);
assertTrue(resultPageSize5.size() >= 25);
assertTrue(resultPageSize10.size() >= 25);
assertTrue(resultPageSizeAll.size() >= 25);
assertTrue(resultPageSize2.containsAll(resultPageSize5));
assertTrue(resultPageSize2.containsAll(resultPageSize10));
assertTrue(resultPageSize2.containsAll(resultPageSizeAll));
assertTrue(resultPageSize5.containsAll(resultPageSize2));
assertTrue(resultPageSize5.containsAll(resultPageSize10));
assertTrue(resultPageSize5.containsAll(resultPageSizeAll));
assertTrue(resultPageSize10.containsAll(resultPageSize2));
assertTrue(resultPageSize10.containsAll(resultPageSize5));
assertTrue(resultPageSize10.containsAll(resultPageSizeAll));
assertTrue(resultPageSizeAll.containsAll(resultPageSize2));
assertTrue(resultPageSizeAll.containsAll(resultPageSize5));
assertTrue(resultPageSizeAll.containsAll(resultPageSize10));
// reset
queryEngine.setMinPagingBatchSize(2500);
queryEngine.setMaxPagingBatchSize(10000);
}
HashSet<NodeRef> queryNodes(int pageSize)
{
queryEngine.setMinPagingBatchSize(pageSize);
queryEngine.setMaxPagingBatchSize(pageSize);
HashSet<NodeRef> result = new HashSet<>();
SearchParameters sp = new SearchParameters();
sp.addStore(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
sp.setLanguage(SearchService.LANGUAGE_FTS_ALFRESCO);
sp.setQueryConsistency(QueryConsistency.TRANSACTIONAL);
sp.setQuery("TYPE:\"cm:content\"");
ResultSet rs = pubSearchService.query(sp);
int cnt = 0;
for (ResultSetRow row : rs)
{
result.add(row.getNodeRef());
}
return result;
}
}

View File

@@ -158,7 +158,20 @@ public class DBQueryEngineTest
assertNodePresent(6, result);
assertNodePresent(7, result);
}
@Test
public void shouldResultSetLengthMatchTheAmountOfAllAccessibleNodesWhenMaxPermissionCheckEnabled()
{
withMaxItems(5);
prepareTemplate(dbQuery, createNodes(10));
when(assessor.isIncluded(any(Node.class))).thenReturn(true);
engine.setMaxPermissionCheckEnabled(true);
FilteringResultSet result = engine.acceleratedNodeSelection(options, dbQuery, assessor);
assertEquals(10, result.length());
}
@Test
public void shouldNotConsiderInaccessibleNodesInResultSetWhenSkippingNodes()
{

View File

@@ -0,0 +1,155 @@
/*
* #%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.search.impl.solr;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.openMocks;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import org.alfresco.repo.search.QueryParserException;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.methods.PostMethod;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
/** Tests for the {@link AbstractSolrQueryHTTPClient}. */
public class AbstractSolrQueryHTTPClientTest
{
/** A URL for use in the tests. */
private static final String URL = "http://this/is/a/url";
/** The abstract class under test. */
private AbstractSolrQueryHTTPClient abstractSolrQueryHTTPClient = spy(AbstractSolrQueryHTTPClient.class);
@Mock
private HttpClient httpClient;
@Mock
private JSONObject body;
@Mock
private PostMethod postMethod;
@Mock
private Header header;
@Before
public void setUp() throws Exception
{
openMocks(this);
doReturn(postMethod).when(abstractSolrQueryHTTPClient).createNewPostMethod(URL);
when(postMethod.getResponseCharSet()).thenReturn("UTF-8");
}
/** Check postQuery works as expected for the success case. */
@Test
public void testPostQuery_success() throws Exception
{
when(body.toString()).thenReturn("Example body");
when(postMethod.getStatusCode()).thenReturn(HttpServletResponse.SC_OK);
when(postMethod.getResponseBodyAsStream()).thenReturn(convertStringToInputStream("{}"));
JSONObject response = abstractSolrQueryHTTPClient.postQuery(httpClient, URL, body);
assertEquals("Unexpected JSON response received.", "{}", response.toString());
}
/** Check that the status code is usually passed through from Solr. */
@Test
public void testPostQuery_failure() throws Exception
{
String failureMessage = "{\"error\": {\"trace\": \"ExceptionClass: Stacktrace\"}}";
when(body.toString()).thenReturn("Example body");
when(postMethod.getStatusCode()).thenReturn(HttpServletResponse.SC_NOT_FOUND);
when(postMethod.getResponseBodyAsStream()).thenReturn(convertStringToInputStream(failureMessage));
when(postMethod.getResponseBodyAsString()).thenReturn(failureMessage);
try
{
abstractSolrQueryHTTPClient.postQuery(httpClient, URL, body);
fail("Expected a QueryParserException to be thrown.");
}
catch (QueryParserException e)
{
assertEquals("Unexpected status code in exception.", e.getHttpStatusCode(), HttpServletResponse.SC_NOT_FOUND);
verify(postMethod).releaseConnection();
}
}
/** Check that the status code is replaced with "Not Implemented" for an unsupported query option. */
@Test
public void testPostQuery_unsupportedOperation() throws Exception
{
String failureMessage = "{\"error\": {\"trace\": \"java.lang.UnsupportedOperationException: Stacktrace\"}}";
when(body.toString()).thenReturn("Example body");
when(postMethod.getStatusCode()).thenReturn(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
when(postMethod.getResponseBodyAsStream()).thenReturn(convertStringToInputStream(failureMessage));
when(postMethod.getResponseBodyAsString()).thenReturn(failureMessage);
try
{
abstractSolrQueryHTTPClient.postQuery(httpClient, URL, body);
fail("Expected a QueryParserException to be thrown.");
}
catch (QueryParserException e)
{
assertEquals("Unexpected status code in exception.", e.getHttpStatusCode(), HttpServletResponse.SC_NOT_IMPLEMENTED);
}
}
/** Check that a redirect can be followed if the endpoint reports that it's moved. */
@Test
public void testPostQuery_moved() throws Exception
{
when(body.toString()).thenReturn("Example body");
// Report "moved" for the first invocation and then OK for subsequent requests.
when(postMethod.getStatusCode()).thenReturn(HttpServletResponse.SC_MOVED_PERMANENTLY).thenReturn(HttpServletResponse.SC_OK);
when(postMethod.getResponseBodyAsStream()).thenReturn(convertStringToInputStream("{}"));
when(postMethod.getResponseHeader("location")).thenReturn(header);
when(header.getValue()).thenReturn("http://new/URL");
JSONObject response = abstractSolrQueryHTTPClient.postQuery(httpClient, URL, body);
verify(postMethod).setURI(new URI("http://new/URL", true));
assertEquals("Unexpected JSON response received.", "{}", response.toString());
}
/** Create an input stream containing the given string. */
private ByteArrayInputStream convertStringToInputStream(String message)
{
return new ByteArrayInputStream(message.getBytes());
}
}

View File

@@ -25,9 +25,9 @@
*/
package org.alfresco.repo.usage;
import javax.transaction.UserTransaction;
import java.util.concurrent.TimeUnit;
import junit.framework.TestCase;
import javax.transaction.UserTransaction;
import org.alfresco.repo.lock.JobLockService;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
@@ -37,6 +37,7 @@ import org.alfresco.service.cmr.admin.RepoUsage;
import org.alfresco.service.cmr.admin.RepoUsage.LicenseMode;
import org.alfresco.service.cmr.admin.RepoUsage.UsageType;
import org.alfresco.service.cmr.admin.RepoUsageStatus;
import org.alfresco.service.cmr.admin.RepoUsageStatus.RepoUsageLevel;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.test_category.OwnJVMTestsCategory;
import org.alfresco.util.ApplicationContextHelper;
@@ -48,6 +49,8 @@ import org.junit.experimental.categories.Category;
import org.junit.runners.MethodSorters;
import org.springframework.context.ApplicationContext;
import junit.framework.TestCase;
/**
* Tests {@link RepoUsageComponent}
*
@@ -236,6 +239,123 @@ public class RepoUsageComponentTest extends TestCase
RepoUsage usage = getUsage();
}
public void testLicenceHoursBeforeExpiration() throws Exception
{
// Update usage
updateUsage(UsageType.USAGE_ALL);
// Set the restrictions for license to expire in 6 hours
RepoUsage restrictions = new RepoUsage(
System.currentTimeMillis(),
5000L,
100000L,
LicenseMode.TEAM,
System.currentTimeMillis() + TimeUnit.HOURS.toMillis(6),
false);
repoUsageComponent.setRestrictions(restrictions);
// Update use
updateUsage(UsageType.USAGE_ALL);
// Get the usage
RepoUsage usage = getUsage();
// Check
assertFalse("Usage is in read-only mode",usage.isReadOnly());
assertTrue("System is in read-only mode",transactionService.getAllowWrite());
RepoUsageStatus status = repoUsageComponent.getUsageStatus();
assertEquals("System is not at Warning All Level",status.getLevel(),RepoUsageLevel.WARN_ALL);
}
public void testLicenceMinutesAfterExpiration() throws Exception
{
// Update usage
updateUsage(UsageType.USAGE_ALL);
// Set the restrictions for license to expire in 6 hours
RepoUsage restrictions = new RepoUsage(
System.currentTimeMillis(),
5000L,
100000L,
LicenseMode.TEAM,
System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(1),
false);
repoUsageComponent.setRestrictions(restrictions);
// Update use
updateUsage(UsageType.USAGE_ALL);
// Get the usage
RepoUsage usage = getUsage();
// Check we are in read-only mode
assertTrue("Usage is not in read-only mode",usage.isReadOnly());
assertFalse("System is not in read-only mode",transactionService.getAllowWrite());
RepoUsageStatus status = repoUsageComponent.getUsageStatus();
assertEquals("System is not at Locked Level",status.getLevel(),RepoUsageLevel.LOCKED_DOWN);
}
public void testLicenceMonthsBeforeExpiration() throws Exception
{
// Update usage
updateUsage(UsageType.USAGE_ALL);
// Set the restrictions for license to expire in 60 days from now
RepoUsage restrictions = new RepoUsage(
System.currentTimeMillis(),
5000L,
100000L,
LicenseMode.TEAM,
System.currentTimeMillis() + TimeUnit.DAYS.toMillis(60),
false);
repoUsageComponent.setRestrictions(restrictions);
// Update use
updateUsage(UsageType.USAGE_ALL);
// Get the usage
RepoUsage usage = getUsage();
// Check
assertFalse("Usage is in read-only mode",usage.isReadOnly());
assertTrue("System is in read-only mode",transactionService.getAllowWrite());
RepoUsageStatus status = repoUsageComponent.getUsageStatus();
assertEquals("System is not at OK Level",status.getLevel(),RepoUsageLevel.OK);
}
public void testLicenceDaysAfterExpiration() throws Exception
{
// Update usage
updateUsage(UsageType.USAGE_ALL);
// Set the restrictions for license expired 5 days ago
RepoUsage restrictions = new RepoUsage(
System.currentTimeMillis(),
5000L,
100000L,
LicenseMode.TEAM,
System.currentTimeMillis() - TimeUnit.DAYS.toMillis(5),
false);
repoUsageComponent.setRestrictions(restrictions);
// Update use
updateUsage(UsageType.USAGE_ALL);
// Get the usage
RepoUsage usage = getUsage();
// Check we are in read-only mode
assertTrue("Usage is not in read-only mode",usage.isReadOnly());
assertFalse("System is not in read-only mode",transactionService.getAllowWrite());
RepoUsageStatus status = repoUsageComponent.getUsageStatus();
assertEquals("System is not at Locked Level",status.getLevel(),RepoUsageLevel.LOCKED_DOWN);
}
/**
* Check that concurrent updates are prevented
*