Compare commits

...

81 Commits

Author SHA1 Message Date
Suneet Gupta
f21056f7c1 Added http dependency 2021-10-23 11:22:23 +05:30
Suneet Gupta
249a01014e Added http dependency 2021-10-23 11:10:59 +05:30
Travis CI User
4fa0157594 [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-22 08:53:09 +00:00
Travis CI User
c1196ed8e9 [maven-release-plugin][skip ci] prepare release 14.19 2021-10-22 08:53:06 +00:00
mpichura
90a69173bd ACS-2147: Adding Experimental annotation. (#764) 2021-10-22 10:07:48 +02:00
Travis CI User
cb0a07d5da [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-22 06:47:39 +00:00
Travis CI User
77e721d66a [maven-release-plugin][skip ci] prepare release 14.18 2021-10-22 06:47:36 +00:00
Suneet Gupta
25d2a51254 Merge branch 'master' of github.com:Alfresco/alfresco-community-repo 2021-10-22 11:29:08 +05:30
Suneet Gupta
54fe4bb969 Added default.properties for test cases config 2021-10-22 11:25:43 +05:30
Travis CI User
7e719cae80 [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-21 15:59:24 +00:00
Travis CI User
157a6ba1c5 [maven-release-plugin][skip ci] prepare release 14.17 2021-10-21 15:59:21 +00:00
alandavis
4fc165150a Revert "Alfresco community repo migration from Mockito 1 to Mockito 3 (#745)"
This reverts commit b846ccd85e.
2021-10-21 15:21:34 +01:00
Travis CI User
d574d05066 [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-21 10:33:28 +00:00
Travis CI User
f66426bb60 [maven-release-plugin][skip ci] prepare release 14.16 2021-10-21 10:33:25 +00:00
Lev Belava
b846ccd85e Alfresco community repo migration from Mockito 1 to Mockito 3 (#745) 2021-10-21 11:45:35 +02:00
Travis CI User
09fc6f1e25 [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-19 16:27:33 +00:00
Travis CI User
630f553fce [maven-release-plugin][skip ci] prepare release 14.15 2021-10-19 16:27:30 +00:00
Tom Page
7242a78705 MNT-21985 Handle case where permissions in Solr and DB are out of sync. (#760)
* MNT-21985 Handle case where permissions in Solr and DB are out of sync.

* MNT-21985 Simplify return logic in error case.
2021-10-19 16:40:50 +01:00
Travis CI User
539a89537b [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-19 12:53:46 +00:00
Travis CI User
608c16d4a4 [maven-release-plugin][skip ci] prepare release 14.14 2021-10-19 12:53:43 +00:00
David Edwards
c00736c639 ACS-2064 DAU: Fix response content type always PDF (#754)
* ACS-2064 ContentStore.java to require mimetype

- Updates the ContentStore interface to also require a mimetype, deprecates old method signatures
- Original interface methods maintained so code should be backwards compatible
- Implementing classes updated to reflect changes
2021-10-19 13:10:17 +01:00
Travis CI User
15cb7ff44e [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-14 14:11:10 +00:00
Travis CI User
4776e37223 [maven-release-plugin][skip ci] prepare release 14.13 2021-10-14 14:11:07 +00:00
Lev Belava
cbd45fcb3e MNT-21706 NodeService setAssociations list of elements is now handled. (#746)
MNT-21706 NodeService setAssociations list of elements is now handled.
2021-10-14 15:27:41 +02:00
Travis CI User
655cadbda0 [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-12 17:01:08 +00:00
Travis CI User
6d7e3bb787 [maven-release-plugin][skip ci] prepare release 14.12 2021-10-12 17:01:05 +00:00
Nithin Nambiar
bb8d10074e ACS-1112 Upgrade the BatchProcessor counting mechanism to work with "long" Java type (#706)
* ACS-1112 update to long data type
2021-10-12 17:04:31 +01:00
alandavis
806880a86b Include the latest MariaDB and MySQL tests in PRs.
[skip ci]
2021-10-11 12:21:42 +01:00
Nithin Nambiar
e68f56270a ACS-849_incorrect_probes added db check (#692)
* ACS-849_incorrect_probes added db check
2021-10-11 12:08:43 +01:00
Travis CI User
8705d97407 [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-08 15:44:38 +00:00
Travis CI User
44e3242132 [maven-release-plugin][skip ci] prepare release 14.11 2021-10-08 15:44:36 +00:00
alandavis
8a3cdd55a7 Revert "Bump mysql-connector-java from 8.0.25 to 8.0.26 (#741)"
As tests on MySQL 5.7.23 failed - not in the PR build

This reverts commit 3b41308ecc.
2021-10-08 15:37:35 +01:00
alandavis
cff2a70b17 Use a common property for json-path as it is used in community and enterprise repo and packaging 2021-10-08 15:24:36 +01:00
dependabot[bot]
3b41308ecc Bump mysql-connector-java from 8.0.25 to 8.0.26 (#741) 2021-10-08 13:40:53 +00:00
dependabot[bot]
8a60e26ff0 Bump lombok from 1.18.20 to 1.18.22 (#742) 2021-10-08 13:38:37 +00:00
Ryan Wilson
accfc4662d Community contribution: fix spelling within permissionDefinition.xml (#469)
There were a number of locations within comments that contained incorrect spelling. [skip ci]
2021-10-08 14:30:43 +01:00
Travis CI User
1e0fcfcc14 [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-08 11:06:13 +00:00
Travis CI User
837a706514 [maven-release-plugin][skip ci] prepare release 14.10 2021-10-08 11:06:10 +00:00
dependabot[bot]
db290c98f2 Bump cmis from 1.30 to 1.31 (#711) 2021-10-08 09:58:24 +00:00
dependabot[bot]
12682ddcff Bump dependency.spring.version from 5.3.9 to 5.3.10 (#715) 2021-10-08 09:39:26 +00:00
dependabot[bot]
0ed2e9b3a7 Bump joda-time from 2.10.10 to 2.10.12 (#716) 2021-10-08 09:37:42 +00:00
dependabot[bot]
3442e91575 Bump maven-war-plugin from 3.2.2 to 3.3.2 (#719) 2021-10-08 09:34:46 +00:00
Travis CI User
59b636e0ba [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-07 18:15:14 +00:00
Travis CI User
0333fe05b5 [maven-release-plugin][skip ci] prepare release 14.9 2021-10-07 18:15:11 +00:00
alandavis
9b592bfc13 Revert "Bump mysql-connector-java from 8.0.25 to 8.0.26 (#609)"
As DbNodeServiceImplTest>BaseNodeServiceTest.testLargeStrings:1061 » AlfrescoRuntime now fails

This reverts commit 386696d58b.
2021-10-07 18:26:05 +01:00
dependabot-preview[bot]
386696d58b Bump mysql-connector-java from 8.0.25 to 8.0.26 (#609)
Bumps [mysql-connector-java](https://github.com/mysql/mysql-connector-j) from 8.0.25 to 8.0.26.
- [Release notes](https://github.com/mysql/mysql-connector-j/releases)
- [Changelog](https://github.com/mysql/mysql-connector-j/blob/release/8.0/CHANGES)
- [Commits](https://github.com/mysql/mysql-connector-j/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
Co-authored-by: Alan Davis <alan.davis@alfresco.com>
2021-10-07 15:23:38 +01:00
dependabot[bot]
1f243d629e Bump xmlsec from 1.5.8 to 2.2.3 (#732) 2021-10-07 14:16:40 +00:00
dependabot[bot]
dee7625998 Bump postgresql from 42.2.20 to 42.2.24 (#734) 2021-10-07 14:15:04 +00:00
dependabot[bot]
1c541281db Bump maven-javadoc-plugin from 3.3.0 to 3.3.1 (#733) 2021-10-07 14:11:08 +00:00
dependabot-preview[bot]
c991290c01 Bump dependency.slf4j.version from 1.7.30 to 1.7.32 (#611) 2021-10-07 14:01:24 +00:00
Travis CI User
9b62808ed7 [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-07 13:00:53 +00:00
Travis CI User
d4e8bba9f5 [maven-release-plugin][skip ci] prepare release 14.8 2021-10-07 13:00:50 +00:00
dependabot[bot]
5ae240c392 Bump docker-java from 3.2.11 to 3.2.12 (#735) 2021-10-07 11:31:07 +00:00
dependabot[bot]
a5b35b7d96 Bump spring-security-core from 5.5.1 to 5.5.2 (#737) 2021-10-07 11:30:32 +00:00
dependabot[bot]
d2544b7a4d Bump docker-maven-plugin from 0.34.1 to 0.37.0 (#724) 2021-10-07 11:14:27 +00:00
dependabot[bot]
b9abc05eda Bump maven-artifact from 3.8.1 to 3.8.3 (#727) 2021-10-07 11:11:15 +00:00
dependabot[bot]
04e3743f01 Bump jsoup from 1.14.2 to 1.14.3 (#730) 2021-10-07 11:08:54 +00:00
Travis CI User
745295c4ba [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-07 10:30:48 +00:00
Travis CI User
c9b08594de [maven-release-plugin][skip ci] prepare release 14.7 2021-10-07 10:30:45 +00:00
dependabot[bot]
1d8044076c Bump dependency.webscripts.version from 8.23 to 8.24 (#710) 2021-10-07 09:10:15 +00:00
dependabot[bot]
377b082ef8 Bump mariadb-java-client from 2.7.2 to 2.7.4 (#709) 2021-10-07 09:07:17 +00:00
dependabot[bot]
ad2525bf17 Bump dependency.cxf.version from 3.4.4 to 3.4.5 (#708) 2021-10-07 09:04:57 +00:00
dependabot[bot]
888b26ef72 Bump groovy from 2.5.9 to 3.0.9 (#713)
Bumps [groovy](https://github.com/apache/groovy) from 2.5.9 to 3.0.9.
- [Release notes](https://github.com/apache/groovy/releases)
- [Commits](https://github.com/apache/groovy/commits)

---
updated-dependencies:
- dependency-name: org.codehaus.groovy:groovy
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-07 09:51:16 +01:00
alandavis
aa4a5a6063 Try to give dependabot access to Nexus 2021-10-05 11:12:24 +01:00
dependabot-preview[bot]
7ea91ea702 Upgrade to GitHub-native Dependabot (#424)
Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2021-10-05 09:31:58 +02:00
Travis CI User
b3e8051f08 [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-01 14:32:21 +00:00
Travis CI User
4ba0d3a899 [maven-release-plugin][skip ci] prepare release 14.6 2021-10-01 14:32:18 +00:00
kcichonczyk
8d78b257aa [PRODSEC-4829] Bumped versions of libraries to prevent security vulnerabilities: (#703)
* 'keycloak' version to 15.0.2
2021-10-01 14:38:58 +02:00
Travis CI User
df67011596 [maven-release-plugin][skip ci] prepare for next development iteration 2021-09-29 20:23:22 +00:00
Travis CI User
871bd40d6d [maven-release-plugin][skip ci] prepare release 14.5 2021-09-29 20:23:19 +00:00
montgolfiere
2ef97e0b23 ACS-2067: Fix probes for when DAU enabled (#700) 2021-09-29 19:32:10 +01:00
Vítor Moreira
f1d48f7aab MNT-22428: configurable unsecure jsonp callback CMIS operation (#698) (#704)
* MNT-22428: configurable unsecure jsonp callback CMIS operation

(cherry picked from commit 5807e756bd)
2021-09-29 17:44:06 +01:00
Travis CI User
b5f24f5d58 [maven-release-plugin][skip ci] prepare for next development iteration 2021-09-29 12:17:15 +00:00
Travis CI User
14668044f4 [maven-release-plugin][skip ci] prepare release 14.4 2021-09-29 12:17:12 +00:00
evasques
c5281d7f10 MNT-22600 Nodes with security marks appear unfiltered on CMIS DB queries (#702)
* Change isUnfiltered to protected so we can extend it in enterprise
* Added test method to be able to do a cmis query test

Original commit in governance-services: e4e3235328
2021-09-29 12:07:06 +01:00
Travis CI User
00565f3bc9 [maven-release-plugin][skip ci] prepare for next development iteration 2021-09-29 10:03:49 +00:00
Travis CI User
f15c4d7a8f [maven-release-plugin][skip ci] prepare release 14.3 2021-09-29 10:03:47 +00:00
Piotr Żurek
85a3c71849 MNT-22611 - Fix bulk import parameters parsing (#699) 2021-09-29 10:50:54 +02:00
Travis CI User
4db8ca16e1 [maven-release-plugin][skip ci] prepare for next development iteration 2021-09-29 04:44:40 +00:00
Travis CI User
52e71719d1 [maven-release-plugin][skip ci] prepare release 14.2 2021-09-29 04:44:37 +00:00
alandavis
507161a1d0 Get master ready for 7.2.0 development 2021-09-28 22:56:03 +01:00
81 changed files with 2919 additions and 1411 deletions

181
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,181 @@
version: 2
registries:
maven-repository-artifacts-alfresco-com-nexus-content-groups-int:
type: maven-repository
url: https://artifacts.alfresco.com/nexus/content/groups/internal
username: ${{secrets.NEXUS_USERNAME}}
password: ${{secrets.NEXUS_PASSWORD}}
updates:
- package-ecosystem: maven
directory: "/"
schedule:
interval: daily
time: "22:00"
timezone: Africa/Abidjan
open-pull-requests-limit: 99
ignore:
- dependency-name: com.google.code.gson:gson
versions:
- "> 2.8.6"
- dependency-name: io.fabric8:fabric8-maven-plugin
versions:
- "> 4.4.0"
- dependency-name: javax.servlet:javax.servlet-api
versions:
- "> 3.0.1"
- dependency-name: org.acegisecurity:acegi-security
versions:
- "> 0.8.2_patched"
- dependency-name: org.activiti:activiti-engine
versions:
- "> 5.23.0"
- dependency-name: org.activiti:activiti-engine
versions:
- ">= 7.1.a, < 7.2"
- dependency-name: org.activiti:activiti-spring
versions:
- "> 5.23.0"
- dependency-name: org.activiti:activiti-spring
versions:
- ">= 7.1.a, < 7.2"
- dependency-name: org.apache.camel:camel-activemq
versions:
- "> 3.7.1"
- dependency-name: org.apache.camel:camel-amqp
versions:
- "> 3.7.1"
- dependency-name: org.apache.camel:camel-direct
versions:
- "> 3.7.1"
- dependency-name: org.apache.camel:camel-directvm
versions:
- "> 3.7.1"
- dependency-name: org.apache.camel:camel-jackson
versions:
- "> 3.7.1"
- dependency-name: org.apache.camel:camel-mock
versions:
- "> 3.7.1"
- dependency-name: org.apache.camel:camel-spring
versions:
- "> 3.7.1"
- dependency-name: org.apache.chemistry.opencmis:chemistry-opencmis-client-impl
versions:
- "> 1.0.0"
- dependency-name: org.apache.chemistry.opencmis:chemistry-opencmis-commons-impl
versions:
- "> 1.0.0"
- dependency-name: org.apache.chemistry.opencmis:chemistry-opencmis-server-bindings
versions:
- "> 1.0.0"
- dependency-name: org.apache.chemistry.opencmis:chemistry-opencmis-test-tck
versions:
- "> 1.0.0"
- dependency-name: org.freemarker:freemarker
versions:
- "> 2.3.20-alfresco-patched-20200421"
- dependency-name: org.keycloak:keycloak-adapter-core
versions:
- "> 12.0.2"
- dependency-name: org.keycloak:keycloak-adapter-spi
versions:
- "> 12.0.2"
- dependency-name: org.keycloak:keycloak-authz-client
versions:
- "> 12.0.2"
- dependency-name: org.keycloak:keycloak-common
versions:
- "> 12.0.2"
- dependency-name: org.keycloak:keycloak-core
versions:
- "> 12.0.2"
- dependency-name: org.keycloak:keycloak-servlet-adapter-spi
versions:
- "> 12.0.2"
- dependency-name: org.eclipse.jetty:jetty-server
versions:
- 9.4.38.v20210224
- dependency-name: org.alfresco.tas:cmis
versions:
- "1.28"
- dependency-name: org.springframework:spring-webmvc
versions:
- 5.3.4
- 5.3.5
- dependency-name: org.springframework:spring-web
versions:
- 5.3.4
- 5.3.5
- dependency-name: org.springframework:spring-tx
versions:
- 5.3.4
- 5.3.5
- dependency-name: org.springframework:spring-orm
versions:
- 5.3.4
- 5.3.5
- dependency-name: org.springframework:spring-test
versions:
- 5.3.4
- 5.3.5
- dependency-name: org.springframework:spring-jms
versions:
- 5.3.4
- 5.3.5
- dependency-name: org.springframework:spring-jdbc
versions:
- 5.3.4
- 5.3.5
- dependency-name: org.springframework:spring-expression
versions:
- 5.3.4
- 5.3.5
- dependency-name: org.springframework:spring-core
versions:
- 5.3.4
- 5.3.5
- dependency-name: org.springframework:spring-context-support
versions:
- 5.3.4
- 5.3.5
- dependency-name: org.springframework:spring-context
versions:
- 5.3.4
- 5.3.5
- dependency-name: org.springframework:spring-beans
versions:
- 5.3.4
- 5.3.5
- dependency-name: org.springframework:spring-aop
versions:
- 5.3.4
- 5.3.5
- dependency-name: org.alfresco.tas:restapi
versions:
- "1.55"
- dependency-name: org.eclipse.jetty:jetty-security
versions:
- 11.0.1
- dependency-name: org.alfresco.aos-module:alfresco-vti-bin
versions:
- 1.4.0-M1
- dependency-name: org.alfresco.aos-module:alfresco-aos-module-distributionzip
versions:
- 1.4.0-M1
- dependency-name: org.alfresco.aos-module:alfresco-aos-module
versions:
- 1.4.0-M1
- dependency-name: org.alfresco.surf:spring-webscripts-api
versions:
- "8.16"
- dependency-name: org.alfresco.surf:spring-webscripts:tests
versions:
- "8.16"
- dependency-name: org.alfresco.surf:spring-webscripts
versions:
- "8.16"
- dependency-name: org.alfresco.surf:spring-surf-core-configservice
versions:
- "8.16"
registries:
- maven-repository-artifacts-alfresco-com-nexus-content-groups-int

View File

@@ -145,7 +145,8 @@ jobs:
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.6 tests"
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/ OR commit_message =~ /\[latest db\]/
# We run tests on the latest version of MariaDB on pull requests plus the normal master and release branches - ignored on feature branches
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ ) 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.6 --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
@@ -159,7 +160,8 @@ jobs:
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: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/ OR commit_message =~ /\[latest db\]/
# We run tests on the latest version of MySQL on pull requests plus the normal master and release branches - ignored on feature branches
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ ) 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

View File

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

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId>
<version>11.141-SNAPSHOT</version>
<version>14.20-SNAPSHOT</version>
</parent>
<modules>
@@ -37,6 +37,11 @@
<skipTests>${skip.automationtests}</skipTests>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</plugin>
</plugins>
</build>
</project>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
<version>11.141-SNAPSHOT</version>
<version>14.20-SNAPSHOT</version>
</parent>
@@ -40,7 +40,7 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.26</version>
<version>1.7.32</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -82,7 +82,7 @@
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java</artifactId>
<version>3.2.11</version>
<version>3.2.12</version>
</dependency>
</dependencies>
</project>

View File

@@ -619,11 +619,27 @@ public class BaseRMRestTest extends RestTest
* @return
*/
public List<String> searchForContentAsUser(UserModel user, String term)
{
String query = "cm:name:*" + term + "*";
return searchForContentAsUser(user,query,"afts");
}
/**
* Returns search results for the given search term
*
* @param user
* @param term
* @param query language
* @return
* @throws Exception
*/
public List<String> searchForContentAsUser(UserModel user, String q, String queryLanguage)
{
getRestAPIFactory().getRmRestWrapper().authenticateUser(user);
RestRequestQueryModel queryReq = new RestRequestQueryModel();
SearchRequest query = new SearchRequest(queryReq);
queryReq.setQuery("cm:name:*" + term + "*");
queryReq.setQuery(q);
queryReq.setLanguage(queryLanguage);
List<String> names = new ArrayList<>();
// wait for solr indexing

View File

@@ -0,0 +1,89 @@
# dataprep related
alfresco.scheme=http
alfresco.server=localhost
alfresco.port=8082
# sync service related
sync.scheme=http
sync.server=localhost
sync.port=9090
# Solr Server Settings
solr.scheme=http
solr.server=localhost
solr.port=8083
#Solr Indexing Time
solrWaitTimeInSeconds=20
# credentials
admin.user=admin
admin.password=admin
# Identity Service configuration
# set this property to run tests using AIS
# identity-service.auth-server-url=http://localhost:8999/auth
# in containers we cannot access directly JMX, so we will use http://jolokia.org agent
# disabling this we will use direct JMX calls to server
jmx.useJolokiaAgent=false
# Server Health section
# in ServerHealth#isServerReachable() - could also be shown.
# enable this option to view if on server there are tenants or not
serverHealth.showTenants=false
# TEST MANAGEMENT SECTION - Test Rail
#
# (currently supporting Test Rail v5.2.1.3472 integration)
#
# Example of configuration:
# ------------------------------------------------------
# if testManagement.enabled=true we enabled TestRailExecutorListener (if used in your suite xml file)
# testManagement.updateTestExecutionResultsOnly=true (this will just update the results of a test: no step will be updated - good for performance)
# testManagement.endPoint=https://alfresco.testrail.com/
# testManagement.username=<username>
# testManagement.apiKey=<api-key>
# testManagement.project=<id-of-your-project
# testManagement.testRun=<test-run-name>
# testManagement.includeOnlyTestCasesExecuted=true #if you want to include in your run ONLY the test cases that you run, then set this value to false
# testManagement.rateLimitInSeconds=1 #is the default rate limit after what minimum time, should we upload the next request. http://docs.gurock.com/testrail-api2/introduction #Rate Limit
# testManagement.suiteId=23 (the id of the Master suite)
# ------------------------------------------------------
testManagement.enabled=false
testManagement.endPoint=https://alfresco.testrail.com/
testManagement.username=
testManagement.apiKey=
testManagement.project=7
testManagement.includeOnlyTestCasesExecuted=true
testManagement.rateLimitInSeconds=1
testManagement.testRun=MyTestRunInTestRail
testManagement.suiteId=12
# The location of the reports path
reports.path=./target/reports
#
# Database Section
# You should provide here the database URL, that can be a differed server as alfresco.
# https://docs.oracle.com/javase/tutorial/jdbc/basics/connecting.html
#
# Current supported db.url:
#
# MySQL:
# db.url = jdbc:mysql://${alfresco.server}:3306/alfresco
#
# PostgreSQL:
# db.url = jdbc:postgresql://<your-DB-IP>:3306/alfresco
#
# Oracle:
# db.url = jdbc:oracle://<your-DB-IP>:3306/alfresco
#
# MariaDB:
# db.url = jdbc:mariadb://<your-DB-IP>:3306/alfresco
#
db.url = jdbc:mysql://${alfresco.server}:3306/alfresco
db.username = alfresco
db.password = alfresco
environment=default

View File

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

View File

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

View File

@@ -306,7 +306,7 @@ public class RMAfterInvocationProvider extends RMSecurityCommon
}
}
private boolean isUnfiltered(NodeRef nodeRef)
protected boolean isUnfiltered(NodeRef nodeRef)
{
return !nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -269,9 +269,25 @@ public interface ContentStore
* @return A direct access {@code URL} object for the content
* @throws UnsupportedOperationException if the store is unable to provide the information
*/
@Deprecated
default DirectAccessUrl requestContentDirectUrl(String contentUrl, boolean attachment, String fileName)
{
return requestContentDirectUrl(contentUrl, attachment, fileName, null);
return requestContentDirectUrl(contentUrl, attachment, fileName, null, null);
}
/**
* Gets a presigned URL to directly access the content. It is up to the actual store
* implementation if it can fulfil this request with an expiry time or not.
*
* @param contentUrl A content store {@code URL}
* @param attachment {@code true} if an attachment URL is requested, {@code false} for an embedded {@code URL}.
* @param fileName File name of the content
* @return A direct access {@code URL} object for the content
* @throws UnsupportedOperationException if the store is unable to provide the information
*/
default DirectAccessUrl requestContentDirectUrl(String contentUrl, boolean attachment, String fileName, String mimetype)
{
return requestContentDirectUrl(contentUrl, attachment, fileName, mimetype, null);
}
/**
@@ -285,7 +301,25 @@ public interface ContentStore
* @return A direct access {@code URL} object for the content.
* @throws UnsupportedOperationException if the store is unable to provide the information
*/
@Deprecated
default DirectAccessUrl requestContentDirectUrl(String contentUrl, boolean attachment, String fileName, Long validFor)
{
return requestContentDirectUrl(contentUrl, attachment, fileName, null, validFor);
}
/**
* Gets a presigned URL to directly access the content. It is up to the actual store
* implementation if it can fulfil this request with an expiry time or not.
*
* @param contentUrl A content store {@code URL}
* @param attachment {@code true} if an attachment URL is requested, {@code false} for an embedded {@code URL}.
* @param fileName File name of the content
* @param mimetype Mimetype of the content
* @param validFor The time at which the direct access {@code URL} will expire.
* @return A direct access {@code URL} object for the content.
* @throws UnsupportedOperationException if the store is unable to provide the information
*/
default DirectAccessUrl requestContentDirectUrl(String contentUrl, boolean attachment, String fileName, String mimetype, Long validFor)
{
throw new UnsupportedOperationException(
"Retrieving direct access URLs is not supported by this content store.");

View File

@@ -0,0 +1,55 @@
/*
* #%L
* Alfresco Data model classes
* %%
* 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.service;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to mark a type/method/field as experimental.
* <p>
* If this annotation is present on an element it marks it as experimental and subject to change without further notice.
* The element may even be deleted or renamed without any notice.
* Experimental element may likely become a valid one (not experimental anymore) in future releases but there is no guarantee when
* and if that happens.
*
* @author mpichura
*/
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
@Documented
public @interface Experimental {
/**
* Further description that can optionally be added to clarify possible future changes of annotated object.
*
* @return a String, the default is an empty String.
*/
String description() default "";
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>11.141-SNAPSHOT</version>
<version>14.20-SNAPSHOT</version>
</parent>
<developers>
@@ -93,7 +93,7 @@
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.5.0</version>
<version>${dependency.jakarta-json-path.version}</version>
</dependency>
</dependencies>

View File

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

View File

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

View File

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

37
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>11.141-SNAPSHOT</version>
<version>14.20-SNAPSHOT</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>1</acs.version.minor>
<acs.version.minor>2</acs.version.minor>
<acs.version.revision>0</acs.version.revision>
<acs.version.label />
<amp.min.version>${acs.version.major}.0.0</amp.min.version>
@@ -55,13 +55,13 @@
<dependency.alfresco-greenmail.version>6.2</dependency.alfresco-greenmail.version>
<dependency.acs-event-model.version>0.0.13</dependency.acs-event-model.version>
<dependency.spring.version>5.3.9</dependency.spring.version>
<dependency.spring.version>5.3.10</dependency.spring.version>
<dependency.antlr.version>3.5.2</dependency.antlr.version>
<dependency.jackson.version>2.12.3</dependency.jackson.version>
<dependency.jackson-databind.version>2.12.4</dependency.jackson-databind.version>
<dependency.cxf.version>3.4.4</dependency.cxf.version>
<dependency.cxf.version>3.4.5</dependency.cxf.version>
<dependency.opencmis.version>1.0.0</dependency.opencmis.version>
<dependency.webscripts.version>8.23</dependency.webscripts.version>
<dependency.webscripts.version>8.24</dependency.webscripts.version>
<dependency.bouncycastle.version>1.69</dependency.bouncycastle.version>
<dependency.mockito-core.version>3.11.2</dependency.mockito-core.version>
<dependency.mockito-all.version>1.10.19</dependency.mockito-all.version>
@@ -73,15 +73,15 @@
<dependency.httpcore.version>4.4.14</dependency.httpcore.version>
<dependency.commons-httpclient.version>3.1-HTTPCLIENT-1265</dependency.commons-httpclient.version>
<dependency.xercesImpl.version>2.12.1</dependency.xercesImpl.version>
<dependency.slf4j.version>1.7.30</dependency.slf4j.version>
<dependency.slf4j.version>1.7.32</dependency.slf4j.version>
<dependency.gytheio.version>0.12</dependency.gytheio.version>
<dependency.groovy.version>2.5.9</dependency.groovy.version>
<dependency.groovy.version>3.0.9</dependency.groovy.version>
<dependency.tika.version>1.27</dependency.tika.version>
<dependency.spring-security.version>5.5.1</dependency.spring-security.version>
<dependency.spring-security.version>5.5.2</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>13.0.1</dependency.keycloak.version>
<dependency.keycloak.version>15.0.2</dependency.keycloak.version>
<dependency.jboss.logging.version>3.4.2.Final</dependency.jboss.logging.version>
<dependency.camel.version>3.7.4</dependency.camel.version>
<dependency.activemq.version>5.16.1</dependency.activemq.version>
@@ -101,6 +101,7 @@
<dependency.jakarta-jws-api.version>2.1.0</dependency.jakarta-jws-api.version>
<dependency.jakarta-mail-api.version>1.6.5</dependency.jakarta-mail-api.version>
<dependency.jakarta-json-api.version>1.1.6</dependency.jakarta-json-api.version>
<dependency.jakarta-json-path.version>2.5.0</dependency.jakarta-json-path.version>
<dependency.jakarta-rpc-api.version>1.1.4</dependency.jakarta-rpc-api.version>
<alfresco.googledrive.version>3.2.1.3</alfresco.googledrive.version>
@@ -108,14 +109,14 @@
<alfresco.api-explorer.version>7.1.0.1</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
<alfresco.maven-plugin.version>2.2.0</alfresco.maven-plugin.version>
<dependency.postgresql.version>42.2.20</dependency.postgresql.version>
<dependency.postgresql.version>42.2.24</dependency.postgresql.version>
<dependency.mysql.version>8.0.25</dependency.mysql.version>
<dependency.mysql-image.version>8</dependency.mysql-image.version>
<dependency.mariadb.version>2.7.2</dependency.mariadb.version>
<dependency.mariadb.version>2.7.4</dependency.mariadb.version>
<dependency.tas-utility.version>3.0.45</dependency.tas-utility.version>
<dependency.rest-assured.version>3.3.0</dependency.rest-assured.version>
<dependency.tas-restapi.version>1.64</dependency.tas-restapi.version>
<dependency.tas-cmis.version>1.30</dependency.tas-cmis.version>
<dependency.tas-cmis.version>1.31</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>
@@ -638,7 +639,7 @@
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.14.2</version>
<version>1.14.3</version>
</dependency>
<!-- upgrade dependency from TIKA -->
<dependency>
@@ -711,7 +712,7 @@
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.10</version>
<version>2.10.12</version>
</dependency>
<!-- provided dependencies -->
@@ -850,7 +851,7 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -870,7 +871,7 @@
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.34.1</version>
<version>0.37.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
@@ -886,12 +887,12 @@
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<version>3.3.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.3.0</version>
<version>3.3.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>11.141-SNAPSHOT</version>
<version>14.20-SNAPSHOT</version>
</parent>
<dependencies>
@@ -47,7 +47,7 @@
<dependency>
<groupId>org.apache.santuario</groupId>
<artifactId>xmlsec</artifactId>
<version>1.5.8</version>
<version>2.2.3</version>
</dependency>
<!-- newer version, see REPO-3133 -->
<dependency>

View File

@@ -27,17 +27,14 @@ package org.alfresco.opencmis;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -48,19 +45,17 @@ import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRegistration;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import javax.servlet.descriptor.JspConfigDescriptor;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.opencmis.CMISDispatcherRegistry.Binding;
import org.alfresco.opencmis.CMISDispatcherRegistry.Endpoint;
import org.alfresco.repo.tenant.TenantAdminService;
import org.alfresco.rest.framework.core.exceptions.JsonpCallbackNotAllowedException;
import org.alfresco.service.descriptor.Descriptor;
import org.alfresco.service.descriptor.DescriptorService;
import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
@@ -69,7 +64,6 @@ import org.apache.chemistry.opencmis.server.impl.CmisRepositoryContextListener;
import org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;
import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime;
/**
* Dispatches OpenCMIS requests to a servlet e.g. the OpenCMIS AtomPub servlet.
@@ -90,6 +84,8 @@ public abstract class CMISServletDispatcher implements CMISDispatcher
protected CmisVersion cmisVersion;
protected TenantAdminService tenantAdminService;
private boolean allowUnsecureCallbackJSONP;
private Set<String> nonAttachContentTypes = Collections.emptySet(); // pre-configured whitelist, eg. images & pdf
public void setTenantAdminService(TenantAdminService tenantAdminService)
@@ -151,7 +147,17 @@ public abstract class CMISServletDispatcher implements CMISDispatcher
return this.currentDescriptor;
}
public void setAllowUnsecureCallbackJSONP(boolean allowUnsecureCallbackJSONP)
{
this.allowUnsecureCallbackJSONP = allowUnsecureCallbackJSONP;
}
public boolean isAllowUnsecureCallbackJSONP()
{
return allowUnsecureCallbackJSONP;
}
public void init()
{
Endpoint endpoint = new Endpoint(getBinding(), version);
@@ -219,12 +225,22 @@ public abstract class CMISServletDispatcher implements CMISDispatcher
CMISHttpServletResponse httpResWrapper = getHttpResponse(res);
CMISHttpServletRequest httpReqWrapper = getHttpRequest(req);
servlet.service(httpReqWrapper, httpResWrapper);
// check for "callback" query param
if (!allowUnsecureCallbackJSONP && httpReqWrapper.getParameter("callback") != null)
{
throw new JsonpCallbackNotAllowedException();
}
servlet.service(httpReqWrapper, httpResWrapper);
}
catch(ServletException e)
{
throw new AlfrescoRuntimeException("", e);
}
catch (JsonpCallbackNotAllowedException e)
{
res.setStatus(403);
res.getWriter().append(e.getMessage());
}
}
/**

View File

@@ -30,8 +30,19 @@ import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.OptionalInt;
import java.util.function.Function;
import java.util.function.Supplier;
import com.google.common.primitives.Ints;
import org.alfresco.repo.bulkimport.BulkFilesystemImporter;
import org.alfresco.repo.bulkimport.BulkImportParameters;
import org.alfresco.repo.bulkimport.NodeImporter;
import org.alfresco.repo.bulkimport.impl.MultiThreadedBulkFilesystemImporter;
import org.alfresco.repo.model.Repository;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
@@ -39,8 +50,12 @@ import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* contains common fields and methods for the import web scripts.
@@ -60,10 +75,10 @@ public class AbstractBulkFileSystemImportWebScript extends DeclarativeWebScript
// Web scripts parameters (common)
protected static final String PARAMETER_REPLACE_EXISTING = "replaceExisting";
protected static final String PARAMETER_EXISTING_FILE_MODE = "existingFileMode";
protected static final String PARAMETER_VALUE_REPLACE_EXISTING = "replaceExisting";
protected static final String PARAMETER_VALUE_REPLACE_EXISTING = "true";
protected static final String PARAMETER_SOURCE_DIRECTORY = "sourceDirectory";
protected static final String PARAMETER_DISABLE_RULES = "disableRules";
protected static final String PARAMETER_VALUE_DISABLE_RULES = "disableRules";
protected static final String PARAMETER_VALUE_DISABLE_RULES = "true";
protected static final String IMPORT_ALREADY_IN_PROGRESS_MODEL_KEY = "importInProgress";
protected static final String IMPORT_ALREADY_IN_PROGRESS_ERROR_KEY ="bfsit.error.importAlreadyInProgress";
@@ -75,7 +90,7 @@ public class AbstractBulkFileSystemImportWebScript extends DeclarativeWebScript
protected Repository repository;
protected volatile boolean importInProgress;
protected NodeRef getTargetNodeRef(String targetNodeRefStr, String targetPath) throws FileNotFoundException
{
NodeRef targetNodeRef;
@@ -219,4 +234,198 @@ public class AbstractBulkFileSystemImportWebScript extends DeclarativeWebScript
this.repository = repository;
}
protected class MultithreadedImportWebScriptLogic
{
private final MultiThreadedBulkFilesystemImporter bulkImporter;
private final Supplier<NodeImporter> nodeImporterFactory;
private final WebScriptRequest request;
private final Status status;
private final Cache cache;
public MultithreadedImportWebScriptLogic(MultiThreadedBulkFilesystemImporter bulkImporter, Supplier<NodeImporter> nodeImporterFactory, WebScriptRequest request, Status status, Cache cache)
{
this.bulkImporter = Objects.requireNonNull(bulkImporter);
this.nodeImporterFactory = Objects.requireNonNull(nodeImporterFactory);
this.request = Objects.requireNonNull(request);
this.status = Objects.requireNonNull(status);
this.cache = Objects.requireNonNull(cache);
}
public Map<String, Object> executeImport()
{
Map<String, Object> model = new HashMap<>();
cache.setNeverCache(true);
String targetPath = null;
try
{
targetPath = request.getParameter(PARAMETER_TARGET_PATH);
if (isRunning())
{
model.put(IMPORT_ALREADY_IN_PROGRESS_MODEL_KEY, I18NUtil.getMessage(IMPORT_ALREADY_IN_PROGRESS_ERROR_KEY));
return model;
}
final BulkImportParameters bulkImportParameters = getBulkImportParameters();
final NodeImporter nodeImporter = nodeImporterFactory.get();
bulkImporter.asyncBulkImport(bulkImportParameters, nodeImporter);
waitForImportToBegin();
// redirect to the status Web Script
status.setCode(Status.STATUS_MOVED_TEMPORARILY);
status.setRedirect(true);
status.setLocation(request.getServiceContextPath() + WEB_SCRIPT_URI_BULK_FILESYSTEM_IMPORT_STATUS);
}
catch (WebScriptException | IllegalArgumentException e)
{
status.setCode(Status.STATUS_BAD_REQUEST, e.getMessage());
status.setRedirect(true);
}
catch (FileNotFoundException fnfe)
{
status.setCode(Status.STATUS_BAD_REQUEST,"The repository path '" + targetPath + "' does not exist !");
status.setRedirect(true);
}
catch (Throwable t)
{
throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, buildTextMessage(t), t);
}
return model;
}
private void waitForImportToBegin() throws InterruptedException
{
// ACE-3047 fix, since bulk import is started asynchronously there is a chance that client
// will get into the status page before import is actually started.
// In this case wrong information (for previous import) will be displayed.
// So lets ensure that import started before redirecting client to status page.
int i = 0;
while (!bulkImporter.getStatus().inProgress() && i < 10)
{
Thread.sleep(100);
i++;
}
}
private BulkImportParameters getBulkImportParameters() throws FileNotFoundException
{
final BulkImportParametersExtractor extractor = new BulkImportParametersExtractor(request::getParameter,
AbstractBulkFileSystemImportWebScript.this::getTargetNodeRef,
bulkImporter.getDefaultBatchSize(),
bulkImporter.getDefaultNumThreads());
return extractor.extract();
}
private boolean isRunning()
{
return bulkImporter.getStatus().inProgress();
}
}
protected static class BulkImportParametersExtractor
{
private final Function<String, String> paramsProvider;
private final NodeRefCreator nodeRefCreator;
private final int defaultBatchSize;
private final int defaultNumThreads;
public BulkImportParametersExtractor(final Function<String, String> paramsProvider, final NodeRefCreator nodeRefCreator,
final int defaultBatchSize, final int defaultNumThreads)
{
this.paramsProvider = Objects.requireNonNull(paramsProvider);
this.nodeRefCreator = Objects.requireNonNull(nodeRefCreator);
this.defaultBatchSize = defaultBatchSize;
this.defaultNumThreads = defaultNumThreads;
}
public BulkImportParameters extract() throws FileNotFoundException
{
BulkImportParameters result = new BulkImportParameters();
result.setTarget(getTargetNodeRef());
setExistingFileMode(result);
result.setNumThreads(getOptionalPositiveInteger(PARAMETER_NUM_THREADS).orElse(defaultNumThreads));
result.setBatchSize(getOptionalPositiveInteger(PARAMETER_BATCH_SIZE).orElse(defaultBatchSize));
setDisableRules(result);
return result;
}
private void setExistingFileMode(BulkImportParameters params)
{
String replaceExistingStr = getParamStringValue(PARAMETER_REPLACE_EXISTING);
String existingFileModeStr = getParamStringValue(PARAMETER_EXISTING_FILE_MODE);
if (!isNullOrEmpty(replaceExistingStr) && !isNullOrEmpty(existingFileModeStr))
{
// Check that we haven't had both the deprecated and new (existingFileMode)
// parameters supplied.
throw new IllegalStateException(
String.format("Only one of these parameters may be used, not both: %s, %s",
PARAMETER_REPLACE_EXISTING,
PARAMETER_EXISTING_FILE_MODE));
}
if (!isNullOrEmpty(existingFileModeStr))
{
params.setExistingFileMode(BulkImportParameters.ExistingFileMode.valueOf(existingFileModeStr));
}
else
{
params.setReplaceExisting(PARAMETER_VALUE_REPLACE_EXISTING.equals(replaceExistingStr));
}
}
private void setDisableRules(final BulkImportParameters params)
{
final String disableRulesStr = getParamStringValue(PARAMETER_DISABLE_RULES);
params.setDisableRulesService(!isNullOrEmpty(disableRulesStr) && PARAMETER_VALUE_DISABLE_RULES.equals(disableRulesStr));
}
private NodeRef getTargetNodeRef() throws FileNotFoundException
{
String targetNodeRefStr = getParamStringValue(PARAMETER_TARGET_NODEREF);
String targetPath = getParamStringValue(PARAMETER_TARGET_PATH);
return nodeRefCreator.fromNodeRefAndPath(targetNodeRefStr, targetPath);
}
private OptionalInt getOptionalPositiveInteger(final String paramName)
{
final String strValue = getParamStringValue(paramName);
if (isNullOrEmpty(strValue))
{
return OptionalInt.empty();
}
final Integer asInt = Ints.tryParse(strValue);
if (asInt == null || asInt < 1)
{
throw new WebScriptException("Error: parameter '" + paramName + "' must be an integer > 0.");
}
return OptionalInt.of(asInt);
}
private String getParamStringValue(String paramName)
{
Objects.requireNonNull(paramName);
return paramsProvider.apply(paramName);
}
private boolean isNullOrEmpty(String str)
{
return str == null || str.trim().length() == 0;
}
@FunctionalInterface
protected interface NodeRefCreator
{
NodeRef fromNodeRefAndPath(String nodeRef, String path) throws FileNotFoundException;
}
}
}

View File

@@ -27,17 +27,12 @@
package org.alfresco.repo.web.scripts.bulkimport.copy;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.repo.bulkimport.BulkImportParameters;
import org.alfresco.repo.bulkimport.NodeImporter;
import org.alfresco.repo.bulkimport.impl.MultiThreadedBulkFilesystemImporter;
import org.alfresco.repo.bulkimport.impl.StreamingNodeImporterFactory;
import org.alfresco.repo.web.scripts.bulkimport.AbstractBulkFileSystemImportWebScript;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.springframework.extensions.surf.util.I18NUtil;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
@@ -69,170 +64,22 @@ public class BulkFilesystemImportWebScript extends AbstractBulkFileSystemImportW
@Override
protected Map<String, Object> executeImpl(final WebScriptRequest request, final Status status, final Cache cache)
{
Map<String, Object> model = new HashMap<String, Object>();
String targetNodeRefStr = null;
String targetPath = null;
String sourceDirectoryStr = null;
@Deprecated String replaceExistingStr = null;
String existingFileModeStr = null;
String batchSizeStr = null;
String numThreadsStr = null;
String disableRulesStr = null;
final MultithreadedImportWebScriptLogic importLogic = new MultithreadedImportWebScriptLogic(bulkImporter,
() -> createNodeImporter(request), request, status, cache);
return importLogic.executeImport();
}
cache.setNeverCache(true);
try
private NodeImporter createNodeImporter(WebScriptRequest request)
{
final String sourceDirectoryStr = request.getParameter(PARAMETER_SOURCE_DIRECTORY);
if (sourceDirectoryStr == null || sourceDirectoryStr.trim().length() == 0)
{
if(!bulkImporter.getStatus().inProgress())
{
NodeRef targetNodeRef = null;
File sourceDirectory = null;
boolean replaceExisting = false;
BulkImportParameters.ExistingFileMode existingFileMode = null;
int batchSize = bulkImporter.getDefaultBatchSize();
int numThreads = bulkImporter.getDefaultNumThreads();
boolean disableRules = false;
// Retrieve, validate and convert parameters
targetNodeRefStr = request.getParameter(PARAMETER_TARGET_NODEREF);
targetPath = request.getParameter(PARAMETER_TARGET_PATH);
sourceDirectoryStr = request.getParameter(PARAMETER_SOURCE_DIRECTORY);
replaceExistingStr = request.getParameter(PARAMETER_REPLACE_EXISTING);
existingFileModeStr = request.getParameter(PARAMETER_EXISTING_FILE_MODE);
batchSizeStr = request.getParameter(PARAMETER_BATCH_SIZE);
numThreadsStr = request.getParameter(PARAMETER_NUM_THREADS);
disableRulesStr = request.getParameter(PARAMETER_DISABLE_RULES);
targetNodeRef = getTargetNodeRef(targetNodeRefStr, targetPath);
if (sourceDirectoryStr == null || sourceDirectoryStr.trim().length() == 0)
{
throw new RuntimeException("Error: mandatory parameter '" + PARAMETER_SOURCE_DIRECTORY + "' was not provided.");
}
sourceDirectory = new File(sourceDirectoryStr.trim());
if (replaceExistingStr != null && existingFileModeStr != null)
{
// Check that we haven't had both the deprecated and new (existingFileMode)
// parameters supplied.
throw new IllegalStateException(
String.format("Only one of these parameters may be used, not both: %s, %s",
PARAMETER_REPLACE_EXISTING,
PARAMETER_EXISTING_FILE_MODE));
}
if (replaceExistingStr != null && replaceExistingStr.trim().length() > 0)
{
replaceExisting = PARAMETER_VALUE_REPLACE_EXISTING.equals(replaceExistingStr);
}
if (existingFileModeStr != null && existingFileModeStr.trim().length() > 0)
{
existingFileMode = BulkImportParameters.ExistingFileMode.valueOf(existingFileModeStr);
}
if (disableRulesStr != null && disableRulesStr.trim().length() > 0)
{
disableRules = PARAMETER_VALUE_DISABLE_RULES.equals(disableRulesStr);
}
// Initiate the import
NodeImporter nodeImporter = nodeImporterFactory.getNodeImporter(sourceDirectory);
BulkImportParameters bulkImportParameters = new BulkImportParameters();
if (numThreadsStr != null && numThreadsStr.trim().length() > 0)
{
try
{
numThreads = Integer.parseInt(numThreadsStr);
if(numThreads < 1)
{
throw new RuntimeException("Error: parameter '" + PARAMETER_NUM_THREADS + "' must be an integer > 0.");
}
bulkImportParameters.setNumThreads(numThreads);
}
catch(NumberFormatException e)
{
throw new RuntimeException("Error: parameter '" + PARAMETER_NUM_THREADS + "' must be an integer > 0.");
}
}
if (batchSizeStr != null && batchSizeStr.trim().length() > 0)
{
try
{
batchSize = Integer.parseInt(batchSizeStr);
if(batchSize < 1)
{
throw new RuntimeException("Error: parameter '" + PARAMETER_BATCH_SIZE + "' must be an integer > 0.");
}
bulkImportParameters.setBatchSize(batchSize);
}
catch(NumberFormatException e)
{
throw new RuntimeException("Error: parameter '" + PARAMETER_BATCH_SIZE + "' must be an integer > 0.");
}
}
if (existingFileMode != null)
{
bulkImportParameters.setExistingFileMode(existingFileMode);
}
else
{
// Fall back to the old/deprecated way.
bulkImportParameters.setReplaceExisting(replaceExisting);
}
bulkImportParameters.setTarget(targetNodeRef);
bulkImportParameters.setDisableRulesService(disableRules);
bulkImporter.asyncBulkImport(bulkImportParameters, nodeImporter);
// ACE-3047 fix, since bulk import is started asynchronously there is a chance that client
// will get into the status page before import is actually started.
// In this case wrong information (for previous import) will be displayed.
// So lets ensure that import started before redirecting client to status page.
int i = 0;
while (!bulkImporter.getStatus().inProgress() && i < 10)
{
Thread.sleep(100);
i++;
}
// redirect to the status Web Script
status.setCode(Status.STATUS_MOVED_TEMPORARILY);
status.setRedirect(true);
status.setLocation(request.getServiceContextPath() + WEB_SCRIPT_URI_BULK_FILESYSTEM_IMPORT_STATUS);
}
else
{
model.put(IMPORT_ALREADY_IN_PROGRESS_MODEL_KEY, I18NUtil.getMessage(IMPORT_ALREADY_IN_PROGRESS_ERROR_KEY));
}
throw new WebScriptException("Error: mandatory parameter '" + PARAMETER_SOURCE_DIRECTORY + "' was not provided.");
}
catch (WebScriptException wse)
{
status.setCode(Status.STATUS_BAD_REQUEST, wse.getMessage());
status.setRedirect(true);
}
catch (FileNotFoundException fnfe)
{
status.setCode(Status.STATUS_BAD_REQUEST,"The repository path '" + targetPath + "' does not exist !");
status.setRedirect(true);
}
catch(IllegalArgumentException iae)
{
status.setCode(Status.STATUS_BAD_REQUEST,iae.getMessage());
status.setRedirect(true);
}
catch (Throwable t)
{
throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, buildTextMessage(t), t);
}
return model;
final File sourceDirectory = new File(sourceDirectoryStr.trim());
return nodeImporterFactory.getNodeImporter(sourceDirectory);
}
}

View File

@@ -23,8 +23,10 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.probes;
import org.alfresco.repo.admin.RepoHealthChecker;
import org.alfresco.rest.api.discovery.DiscoveryApiWebscript;
import org.alfresco.rest.api.model.Probe;
import org.alfresco.rest.framework.WebApiDescription;
@@ -35,29 +37,26 @@ import org.alfresco.rest.framework.core.exceptions.ServiceUnavailableException;
import org.alfresco.rest.framework.resource.EntityResource;
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* An implementation of an Entity Resource for Probes.
*/
@EntityResource(name="probes", title = "Probes")
public class ProbeEntityResource implements EntityResourceAction.ReadById<Probe>
@EntityResource(name = "probes", title = "Probes") public class ProbeEntityResource
implements EntityResourceAction.ReadById<Probe>
{
public static final String LIVE = "-live-";
public static final String READY = "-ready-";
public static final long CHECK_PERIOD = 10 * 1000; // Maximum of only one checkResult every 10 seconds.
protected static Log logger = LogFactory.getLog(ProbeEntityResource.class);;
private long nextCheckTime = 0;
private final static Logger logger = LoggerFactory.getLogger(ProbeEntityResource.class);
private final Object lock = new Object();
private final Probe liveProbe = new Probe("liveProbe: Success - Tested");
private long lastCheckTime = 0;
private Boolean checkResult;
private Boolean checking = false;
private boolean readySent;
private DiscoveryApiWebscript discovery;
private RepoHealthChecker repoHealthChecker;
public DiscoveryApiWebscript setDiscovery(DiscoveryApiWebscript discovery)
{
DiscoveryApiWebscript result = this.discovery;
@@ -65,145 +64,141 @@ public class ProbeEntityResource implements EntityResourceAction.ReadById<Probe>
return result;
}
public void setRepoHealthChecker(RepoHealthChecker repoHealthChecker)
{
this.repoHealthChecker = repoHealthChecker;
}
/**
* Returns a status code of 200 for okay. The probe contains little information for security reasons.
*
* Note: does *not* require authenticated access, so limits the amount of work performed to avoid a DDOS.
*/
@Override
@WebApiDescription(title="Get probe status", description = "Returns 200 if valid")
@WebApiParam(name = "probeName", title = "The probe's name")
@WebApiNoAuth
public Probe readById(String name, Parameters parameters)
@Override @WebApiDescription(title = "Get probe status", description = "Returns 200 if valid") @WebApiParam(name = "probeName", title = "The probe's name") @WebApiNoAuth public Probe readById(
String name, Parameters parameters)
{
boolean isLiveProbe = LIVE.equalsIgnoreCase(name);
if (!isLiveProbe && !READY.equalsIgnoreCase(name))
ProbeType probeType = ProbeType.fromString(name);
Probe probeResponse = null;
switch (probeType)
{
throw new InvalidArgumentException("Bad probe name");
case LIVE:
probeResponse = liveProbe;
break;
case READY:
String message = doReadyCheck();
probeResponse = new Probe(message);
break;
case UNKNOWN:
throw new InvalidArgumentException("Bad probe name");
}
String message = doCheckOrNothing(isLiveProbe);
return new Probe(message);
return probeResponse;
}
// We don't want to be doing checks all the time or holding monitors for a long time to avoid a DDOS.
public String doCheckOrNothing(boolean isLiveProbe)
public String doReadyCheck()
{
boolean doCheck = false;
long now = 0;
boolean result;
String message = "No test";
boolean logInfo = false;
synchronized(checking)
synchronized (lock)
{
// Initially ready needs to be false so we don't get requests and live true so the pod is not killed.
if (checkResult == null)
String message;
long now = System.currentTimeMillis();
if (checkResult == null || isAfterCheckPeriod(now))
{
result = isLiveProbe;
try
{
performReadinessCheck();
checkResult = true;
}
catch (Exception e)
{
checkResult = false;
logger.debug("Exception during readiness check", e);
}
finally
{
setLastCheckTime(now);
message = getMessage(checkResult, "Tested");
logger.info(message);
}
}
else
{
result = checkResult;
// if no check is performed, use previous check result
message = getMessage(checkResult, "No test");
logger.debug(message);
}
if (checkResult)
{
return message;
}
if (checking) // Is another thread is checking?
{
if (!readySent && result && !isLiveProbe)
{
readySent = true;
logInfo = true;
}
}
else // This thread will do a check
{
now = System.currentTimeMillis();
if (checkResult == null || nextCheckTime <= now)
{
doCheck = true;
checking = true;
}
}
throw new ServiceUnavailableException(message);
}
if (doCheck)
{
try
{
message = "Tested";
doCheck(isLiveProbe);
result = true;
}
catch (Exception e)
{
result = false;
}
finally
{
synchronized (checking)
{
checking = false;
checkResult = result;
setNextCheckTime(now);
if (result && !readySent && !isLiveProbe) // Are we initially ready
{
readySent = true;
logInfo = true;
}
else if (!result && (isLiveProbe || readySent)) // Are we sick
{
logInfo = true;
}
}
}
}
message = getMessage(isLiveProbe, result, message);
if (logInfo)
{
logger.info(message);
}
else
{
logger.debug(message);
}
if (result)
{
return message;
}
throw new ServiceUnavailableException(message);
}
private String getMessage(boolean isLiveProbe, boolean result, String message)
private String getMessage(boolean result, String message)
{
return (isLiveProbe ? "liveProbe" : "readyProbe")+": "+
(result ? "Success" : "Failure") +
" - "+message;
return "readyProbe: " + (result ? "Success" : "Failure") + " - " + message;
}
private void doCheck(boolean isLiveProbe)
private void performReadinessCheck()
{
discovery.getRepositoryInfo();
repoHealthChecker.checkDatabase();
logger.debug("All checks complete");
}
private void setNextCheckTime(long now)
private void setLastCheckTime(long time)
{
long oldValue = nextCheckTime;
if (nextCheckTime == 0)
this.lastCheckTime = time;
long nextCheckTime = lastCheckTime + CHECK_PERIOD;
logger.trace("nextCheckTime: {} (+{} secs)", nextCheckTime, ((CHECK_PERIOD) / 1000));
}
private boolean isAfterCheckPeriod(long currentTime)
{
return ((currentTime - lastCheckTime) >= CHECK_PERIOD);
}
public enum ProbeType
{
LIVE("-live-"), READY("-ready-"), UNKNOWN("");
String value;
ProbeType(String strValue)
{
nextCheckTime = (now / 60000) * 60000;
value = strValue;
}
do
public static ProbeType fromString(String text)
{
nextCheckTime += CHECK_PERIOD;
for (ProbeType p : ProbeType.values())
{
if (p.value.equalsIgnoreCase(text))
{
return p;
}
}
return UNKNOWN;
}
while (nextCheckTime <= now);
if (logger.isTraceEnabled())
public String getValue()
{
logger.trace("nextCheckTime: " + nextCheckTime + " (+" + ((nextCheckTime - oldValue) / 1000) + " secs)");
return value;
}
}
}

View File

@@ -78,6 +78,7 @@ import org.alfresco.rest.api.search.model.SearchSQLQuery;
import org.alfresco.rest.api.search.model.TupleEntry;
import org.alfresco.rest.api.search.model.TupleList;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Paging;
import org.alfresco.rest.framework.resource.parameters.Params;
@@ -152,7 +153,7 @@ public class ResultMapper
* Turns the results into a CollectionWithPagingInfo
* @param params
* @param searchQuery
*@param results @return CollectionWithPagingInfo<Node>
* @param results @return CollectionWithPagingInfo<Node>
*/
public CollectionWithPagingInfo<Node> toCollectionWithPagingInfo(Params params, SearchRequestContext searchRequestContext, SearchQuery searchQuery, ResultSet results)
{
@@ -205,61 +206,69 @@ public class ResultMapper
* @param params
* @param mapUserInfo
* @param isHistory
* @return Node
* @return The node object or null if the user does not have permission to view it.
*/
public Node getNode(ResultSetRow aRow, Params params, Map<String, UserInfo> mapUserInfo, boolean isHistory)
{
String nodeStore = storeMapper.getStore(aRow.getNodeRef());
if (isHistory) nodeStore = HISTORY;
String nodeStore = isHistory ? HISTORY : storeMapper.getStore(aRow.getNodeRef());
Node aNode = null;
switch (nodeStore)
try
{
case LIVE_NODES:
aNode = nodes.getFolderOrDocument(aRow.getNodeRef(), null, null, params.getInclude(), mapUserInfo);
break;
case HISTORY:
aNode = nodes.getFolderOrDocument(aRow.getNodeRef(), null, null, params.getInclude(), mapUserInfo);
break;
case VERSIONS:
Map<QName, Serializable> properties = serviceRegistry.getNodeService().getProperties(aRow.getNodeRef());
NodeRef frozenNodeRef = ((NodeRef) properties.get(Version2Model.PROP_QNAME_FROZEN_NODE_REF));
String versionLabelId = (String) properties.get(Version2Model.PROP_QNAME_VERSION_LABEL);
Version v = null;
try
{
if (frozenNodeRef != null && versionLabelId != null)
switch (nodeStore)
{
case LIVE_NODES:
aNode = nodes.getFolderOrDocument(aRow.getNodeRef(), null, null, params.getInclude(), mapUserInfo);
break;
case HISTORY:
aNode = nodes.getFolderOrDocument(aRow.getNodeRef(), null, null, params.getInclude(), mapUserInfo);
break;
case VERSIONS:
Map<QName, Serializable> properties = serviceRegistry.getNodeService().getProperties(aRow.getNodeRef());
NodeRef frozenNodeRef = ((NodeRef) properties.get(Version2Model.PROP_QNAME_FROZEN_NODE_REF));
String versionLabelId = (String) properties.get(Version2Model.PROP_QNAME_VERSION_LABEL);
Version v = null;
try
{
v = nodeVersions.findVersion(frozenNodeRef.getId(),versionLabelId);
aNode = nodes.getFolderOrDocument(v.getFrozenStateNodeRef(), null, null, params.getInclude(), mapUserInfo);
if (frozenNodeRef != null && versionLabelId != null)
{
v = nodeVersions.findVersion(frozenNodeRef.getId(), versionLabelId);
aNode = nodes.getFolderOrDocument(v.getFrozenStateNodeRef(), null, null, params.getInclude(), mapUserInfo);
}
}
}
catch (EntityNotFoundException|InvalidNodeRefException e)
{
//Solr says there is a node but we can't find it
logger.debug("Failed to find a versioned node with id of "+frozenNodeRef
catch (EntityNotFoundException | InvalidNodeRefException e)
{
//Solr says there is a node but we can't find it
logger.debug("Failed to find a versioned node with id of " + frozenNodeRef
+ " this is probably because the original node has been deleted.");
}
}
if (v != null && aNode != null)
{
nodeVersions.mapVersionInfo(v, aNode, aRow.getNodeRef());
aNode.setNodeId(frozenNodeRef.getId());
aNode.setVersionLabel(versionLabelId);
}
break;
case DELETED:
try
{
aNode = deletedNodes.getDeletedNode(aRow.getNodeRef().getId(), params, false, mapUserInfo);
}
catch (EntityNotFoundException enfe)
{
//Solr says there is a deleted node but we can't find it, we want the rest of the search to return so lets ignore it.
logger.debug("Failed to find a deleted node with id of "+aRow.getNodeRef().getId());
}
break;
if (v != null && aNode != null)
{
nodeVersions.mapVersionInfo(v, aNode, aRow.getNodeRef());
aNode.setNodeId(frozenNodeRef.getId());
aNode.setVersionLabel(versionLabelId);
}
break;
case DELETED:
try
{
aNode = deletedNodes.getDeletedNode(aRow.getNodeRef().getId(), params, false, mapUserInfo);
}
catch (EntityNotFoundException enfe)
{
//Solr says there is a deleted node but we can't find it, we want the rest of the search to return so lets ignore it.
logger.debug("Failed to find a deleted node with id of " + aRow.getNodeRef().getId());
}
break;
}
}
catch (PermissionDeniedException e)
{
logger.debug("Unable to access node: " + aRow.toString());
return null;
}
if (aNode != null)
{
aNode.setLocation(nodeStore);

View File

@@ -0,0 +1,49 @@
/*
* #%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;
/**
* JSONP callback not allowed
*
* @author Vitor Moreira
*/
public class JsonpCallbackNotAllowedException extends ApiException
{
private static final long serialVersionUID = 7198491358180044895L;
public static String DEFAULT_MESSAGE_ID = "framework.exception.JsonpCallbackNotAllowed";
public JsonpCallbackNotAllowedException()
{
super(DEFAULT_MESSAGE_ID);
}
public JsonpCallbackNotAllowedException(String msgId)
{
super(msgId);
}
}

View File

@@ -14,4 +14,6 @@ framework.exception.UnsupportedResourceOperation=The operation is unsupported
framework.exception.DeletedResource=In this version of the REST API resource {0} has been deleted
framework.exception.RequestEntityTooLarge=The file can't be uploaded because it's larger than the maximum upload size
framework.exception.InsufficientStorage=The file upload exceeds the content storage allowance
framework.exception.JsonpCallbackNotAllowed=For security reasons the callback parameter is not allowed
framework.no.stacktrace=For security reasons the stack trace is no longer displayed, but the property is kept for previous versions

View File

@@ -1070,11 +1070,12 @@
<property name="enabled" value="${system.api.discovery.enabled}" />
<property name="thumbnailService" ref="ThumbnailService" />
<property name="restApiDirectUrlConfig" ref="restApiDirectUrlConfig" />
<property name="contentService" ref="ContentService" />
<property name="contentService" ref="contentService" />
</bean>
<bean id="org.alfresco.rest.api.probes.ProbeEntityResource.get" class="org.alfresco.rest.api.probes.ProbeEntityResource">
<property name="discovery" ref="webscript.org.alfresco.api.DiscoveryApiWebscript.get" />
<property name="repoHealthChecker" ref="repoHealthChecker" />
</bean>
<!-- REST API direct access URL configuration settings -->
@@ -1138,6 +1139,7 @@
<property name="cmisVersion" value="1.1"/>
<property name="tenantAdminService" ref="tenantAdminService"/>
<property name="nonAttachContentTypes" ref="nodes.nonAttachContentTypes"/>
<property name="allowUnsecureCallbackJSONP" value="${allow.unsecure.callback.jsonp}"/>
</bean>
<bean id="webscript.org.alfresco.api.opencmis.OpenCMIS.get"

View File

@@ -42,6 +42,7 @@ import org.junit.runners.Suite;
org.alfresco.rest.api.tests.TestPublicApiAtomPub10TCK.class,
org.alfresco.rest.api.tests.TestPublicApiAtomPub11TCK.class,
org.alfresco.rest.api.tests.TestPublicApiBrowser11TCK.class,
org.alfresco.repo.web.scripts.bulkimport.BulkImportParametersExtractorTest.class
})
public class AppContext01TestSuite
{

View File

@@ -0,0 +1,252 @@
/*
* #%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.repo.web.scripts.bulkimport;
import static org.alfresco.repo.web.scripts.bulkimport.AbstractBulkFileSystemImportWebScript.PARAMETER_BATCH_SIZE;
import static org.alfresco.repo.web.scripts.bulkimport.AbstractBulkFileSystemImportWebScript.PARAMETER_DISABLE_RULES;
import static org.alfresco.repo.web.scripts.bulkimport.AbstractBulkFileSystemImportWebScript.PARAMETER_NUM_THREADS;
import static org.alfresco.repo.web.scripts.bulkimport.AbstractBulkFileSystemImportWebScript.PARAMETER_TARGET_NODEREF;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Map;
import org.alfresco.repo.bulkimport.BulkImportParameters;
import org.alfresco.repo.bulkimport.BulkImportParameters.ExistingFileMode;
import org.alfresco.repo.web.scripts.bulkimport.AbstractBulkFileSystemImportWebScript.BulkImportParametersExtractor;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.junit.Test;
import org.springframework.extensions.webscripts.WebScriptException;
public class BulkImportParametersExtractorTest
{
private static final String TEST_NODE_REF = "workspace://SpacesStore/this-is-just-a-test-ref";
private static final String TEST_MISSING_NODE_REF = "workspace://SpacesStore/this-is-just-a-not-existing-test-ref";
private static final Integer DEFAULT_BATCH_SIZE = 1234;
private static final Integer DEFAULT_NUMBER_OF_THREADS = 4321;
@Test
public void shouldExtractTargetRef() throws FileNotFoundException
{
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
PARAMETER_TARGET_NODEREF, TEST_NODE_REF));
final BulkImportParameters params = extractor.extract();
assertNotNull(params);
assertNotNull(params.getTarget());
assertEquals(TEST_NODE_REF, params.getTarget().toString());
}
@Test
public void shouldFallbackToDefaultValues() throws FileNotFoundException
{
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
PARAMETER_TARGET_NODEREF, TEST_NODE_REF));
final BulkImportParameters params = extractor.extract();
assertEquals(DEFAULT_BATCH_SIZE, params.getBatchSize());
assertEquals(DEFAULT_NUMBER_OF_THREADS, params.getNumThreads());
assertFalse(params.isDisableRulesService());
assertEquals(ExistingFileMode.SKIP, params.getExistingFileMode());
assertNull(params.getLoggingInterval());
}
@Test
public void shouldExtractDisableFolderRulesFlagWhenSetToTrue() throws FileNotFoundException
{
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
PARAMETER_DISABLE_RULES, "true"
));
final BulkImportParameters params = extractor.extract();
assertTrue(params.isDisableRulesService());
}
@Test
public void shouldExtractDisableFolderRulesFlagWhenSetToFalse() throws FileNotFoundException
{
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
PARAMETER_DISABLE_RULES, "false"
));
final BulkImportParameters params = extractor.extract();
assertFalse(params.isDisableRulesService());
}
@Test
public void shouldExtractDisableFolderRulesFlagWhenSetToNotBooleanValue() throws FileNotFoundException
{
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
PARAMETER_DISABLE_RULES, "unknown"
));
final BulkImportParameters params = extractor.extract();
assertFalse(params.isDisableRulesService());
}
@Test
public void shouldPropagateFileNotFoundExceptionWhenTargetIsNotFound()
{
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
PARAMETER_TARGET_NODEREF, TEST_MISSING_NODE_REF));
assertThrows(FileNotFoundException.class, extractor::extract);
}
@Test
public void shouldExtractValidBatchSize() throws FileNotFoundException
{
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
PARAMETER_BATCH_SIZE, "1"));
final BulkImportParameters params = extractor.extract();
assertEquals(Integer.valueOf(1), params.getBatchSize());
}
@Test
public void shouldFailWithWebScriptExceptionWhenInvalidBatchSizeIsRequested() throws FileNotFoundException
{
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
PARAMETER_BATCH_SIZE, "not-a-number"));
try
{
extractor.extract();
} catch (WebScriptException e)
{
assertNotNull(e.getMessage());
assertTrue(e.getMessage().contains(PARAMETER_BATCH_SIZE));
return;
}
fail("Expected exception to be thrown.");
}
@Test
public void shouldFailWithWebScriptExceptionWhenNegativeBatchSizeIsRequested() throws FileNotFoundException
{
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
PARAMETER_BATCH_SIZE, "-1"));
try
{
extractor.extract();
} catch (WebScriptException e)
{
assertNotNull(e.getMessage());
assertTrue(e.getMessage().contains(PARAMETER_BATCH_SIZE));
return;
}
fail("Expected exception to be thrown.");
}
@Test
public void shouldExtractValidNumberOfThreads() throws FileNotFoundException
{
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
PARAMETER_NUM_THREADS, "1"));
final BulkImportParameters params = extractor.extract();
assertEquals(Integer.valueOf(1), params.getNumThreads());
}
@Test
public void shouldFailWithWebScriptExceptionWhenInvalidNumberOfThreadsIsRequested() throws FileNotFoundException
{
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
PARAMETER_NUM_THREADS, "not-a-number"));
try
{
extractor.extract();
} catch (WebScriptException e)
{
assertNotNull(e.getMessage());
assertTrue(e.getMessage().contains(PARAMETER_NUM_THREADS));
return;
}
fail("Expected exception to be thrown.");
}
@Test
public void shouldFailWithWebScriptExceptionWhenNegativeNumberOfThreadsIsRequested() throws FileNotFoundException
{
final BulkImportParametersExtractor extractor = givenExtractor(Map.of(
PARAMETER_TARGET_NODEREF, TEST_NODE_REF,
PARAMETER_NUM_THREADS, "-1"));
try
{
extractor.extract();
} catch (WebScriptException e)
{
assertNotNull(e.getMessage());
assertTrue(e.getMessage().contains(PARAMETER_NUM_THREADS));
return;
}
fail("Expected exception to be thrown.");
}
private BulkImportParametersExtractor givenExtractor(Map<String, String> params)
{
return new BulkImportParametersExtractor(params::get, this::testRefCreator, DEFAULT_BATCH_SIZE, DEFAULT_NUMBER_OF_THREADS);
}
private NodeRef testRefCreator(String nodeRef, String path) throws FileNotFoundException
{
if (TEST_MISSING_NODE_REF.equals(nodeRef))
{
throw new FileNotFoundException(new NodeRef(nodeRef));
}
return new NodeRef(nodeRef);
}
}

View File

@@ -25,24 +25,27 @@
*/
package org.alfresco.rest.api.search;
import static java.util.Arrays.asList;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertNull;
import static junit.framework.TestCase.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.notNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -85,6 +88,7 @@ import org.alfresco.rest.api.search.model.SearchQuery;
import org.alfresco.rest.api.search.model.SearchSQLQuery;
import org.alfresco.rest.api.search.model.TupleList;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.rest.framework.resource.parameters.Params;
@@ -96,6 +100,7 @@ import org.alfresco.service.cmr.search.FieldHighlightParameters;
import org.alfresco.service.cmr.search.GeneralHighlightParameters;
import org.alfresco.service.cmr.search.LimitBy;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.ResultSetRow;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
@@ -103,14 +108,11 @@ import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.GUID;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* Tests the ResultMapper class
@@ -138,21 +140,22 @@ public class ResultMapperTests
+ "},"
+ "\"stats\":{\"stats_fields\":{\"numericLabel\":{\"sumOfSquares\":0,\"min\":null,\"max\":null,\"mean\":\"NaN\",\"percentiles\":[\"0.0\",12,\"0.99\",20.0685], \"count\":0,\"missing\":0,\"sum\":0,\"distinctValues\":[12,13,14,15,16,17,1],\"stddev\":0}, \"creator\":{\"min\":\"System\",\"max\":\"mjackson\",\"count\":\"990\",\"missing\":\"290\"}, \"created\":{\"sumOfSquares\":2.1513045770343806E27,\"min\":\"2011-02-15T20:16:27.080Z\",\"max\":\"2017-04-10T15:06:30.143Z\",\"mean\":\"2016-09-05T04:20:12.898Z\",\"count\":990,\"missing\":290,\"sum\":1.458318720769983E15,\"stddev\":5.6250677994522545E10}}},"
+ "\"processedDenies\":true, \"lastIndexedTx\":34}";
public static final Params EMPTY_PARAMS = Params.valueOf((String)null,(String)null,(WebScriptRequest) null);
public static final Params EMPTY_PARAMS = Params.valueOf((String) null, null, null);
public static final String FROZEN_ID = "frozen";
public static final String FROZEN_VER = "1.1";
private static final long VERSIONED_ID = 521l;
private static SerializerTestHelper helper;
private static NodesImpl nodes;
@BeforeClass
public static void setupTests() throws Exception
public static void setupTests()
{
Map<String, UserInfo> mapUserInfo = new HashMap<>();
mapUserInfo.put(AuthenticationUtil.getSystemUserName(), new UserInfo(AuthenticationUtil.getSystemUserName(), "sys", "sys"));
Map<QName, Serializable> nodeProps = new HashMap<>();
NodesImpl nodes = mock(NodesImpl.class);
nodes = mock(NodesImpl.class);
ServiceRegistry sr = mock(ServiceRegistry.class);
DeletedNodes deletedNodes = mock(DeletedNodes.class);
nodes.setServiceRegistry(sr);
@@ -163,17 +166,10 @@ public class ResultMapperTests
versionProperties.put(Version.PROP_DESCRIPTION, "ver desc");
versionProperties.put(Version2Model.PROP_VERSION_TYPE, "v type");
when(versionHistory.getVersion(anyString())).thenAnswer(invocation ->
{
return new VersionImpl(versionProperties,new NodeRef(StoreMapper.STORE_REF_VERSION2_SPACESSTORE, GUID.generate()));
});
new VersionImpl(versionProperties, new NodeRef(StoreMapper.STORE_REF_VERSION2_SPACESSTORE, GUID.generate())));
NodeService nodeService = mock(NodeService.class);
when(versionService.getVersionHistory(any(NodeRef.class))).thenAnswer(invocation ->
{
Object[] args = invocation.getArguments();
NodeRef aNode = (NodeRef)args[0];
return versionHistory;
});
when(versionService.getVersionHistory(any(NodeRef.class))).thenReturn(versionHistory);
when(nodeService.getProperties(any(NodeRef.class))).thenAnswer(invocation ->
{
@@ -204,31 +200,26 @@ public class ResultMapperTests
}
});
// // NodeRef nodeRef = nodes.validateOrLookupNode(nodeId, null);
when(nodes.getFolderOrDocument(any(NodeRef.class), nullable(NodeRef.class), nullable(QName.class), nullable(List.class), nullable(Map.class))).thenAnswer(new Answer<Node>() {
@Override
public Node answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
NodeRef aNode = (NodeRef)args[0];
if (StoreRef.STORE_REF_ARCHIVE_SPACESSTORE.equals(aNode.getStoreRef()))
{
//Return NULL if its from the archive store.
return null;
}
return new Node(aNode, (NodeRef)args[1], nodeProps, mapUserInfo, sr);
when(nodes.getFolderOrDocument(any(NodeRef.class), nullable(NodeRef.class), nullable(QName.class), nullable(List.class), nullable(Map.class))).thenAnswer((Answer<Node>) invocation ->
{
Object[] args = invocation.getArguments();
NodeRef aNode = (NodeRef)args[0];
if (StoreRef.STORE_REF_ARCHIVE_SPACESSTORE.equals(aNode.getStoreRef()))
{
//Return NULL if its from the archive store.
return null;
}
return new Node(aNode, (NodeRef)args[1], nodeProps, mapUserInfo, sr);
});
when(deletedNodes.getDeletedNode(nullable(String.class), nullable(
Parameters.class), anyBoolean(), nullable(Map.class))).thenAnswer(new Answer<Node>() {
@Override
public Node answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String nodeId = (String)args[0];
if (FROZEN_ID.equals(nodeId)) throw new EntityNotFoundException(nodeId);
NodeRef aNode = new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE, nodeId);
return new Node(aNode, new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE,"unknown"), nodeProps, mapUserInfo, sr);
}
Parameters.class), anyBoolean(), nullable(Map.class))).thenAnswer((Answer<Node>) invocation ->
{
Object[] args = invocation.getArguments();
String nodeId = (String)args[0];
if (FROZEN_ID.equals(nodeId)) throw new EntityNotFoundException(nodeId);
NodeRef aNode = new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE, nodeId);
return new Node(aNode, new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE,"unknown"), nodeProps, mapUserInfo, sr);
});
PersonPropertyLookup propertyLookups = mock(PersonPropertyLookup.class);
@@ -236,11 +227,10 @@ public class ResultMapperTests
when(propertyLookups.lookup(notNull(String.class))).thenAnswer(invocation -> {
Object[] args = invocation.getArguments();
String value = (String)args[0];
if ("mjackson".equals(value)) return "Michael Jackson";
return null;
return "mjackson".equals(value) ? "Michael Jackson" : null;
});
PropertyLookupRegistry propertyLookupRegistry = new PropertyLookupRegistry();
propertyLookupRegistry.setLookups(Arrays.asList(propertyLookups));
propertyLookupRegistry.setLookups(asList(propertyLookups));
mapper = new ResultMapper();
mapper.setNodes(nodes);
mapper.setStoreMapper(new StoreMapper());
@@ -258,7 +248,7 @@ public class ResultMapperTests
}
@Test
public void testNoResults() throws Exception
public void testNoResults()
{
SearchRequestContext searchRequest = SearchRequestContext.from(SearchQuery.EMPTY);
CollectionWithPagingInfo<Node> collection = mapper.toCollectionWithPagingInfo(EMPTY_PARAMS, searchRequest, null, new EmptyResultSet());
@@ -269,9 +259,9 @@ public class ResultMapperTests
}
@Test
public void testToCollectionWithPagingInfo() throws Exception
public void testToCollectionWithPagingInfo()
{
ResultSet results = mockResultset(Arrays.asList(514l), Arrays.asList(566l, VERSIONED_ID));
ResultSet results = mockResultSet(asList(514l), asList(566l, VERSIONED_ID));
SearchRequestContext searchRequest = SearchRequestContext.from(SearchQuery.EMPTY);
CollectionWithPagingInfo<Node> collectionWithPage = mapper.toCollectionWithPagingInfo(EMPTY_PARAMS, searchRequest, SearchQuery.EMPTY, results);
assertNotNull(collectionWithPage);
@@ -298,12 +288,12 @@ public class ResultMapperTests
}
@Test
public void testToSearchContext() throws Exception
public void testToSearchContext()
{
ResultSet results = mockResultset(Collections.emptyList(),Collections.emptyList());
ResultSet results = mockResultSet(Collections.emptyList(),Collections.emptyList());
SearchQuery searchQuery = helper.searchQueryFromJson();
SearchRequestContext searchRequest = SearchRequestContext.from(searchQuery);
SearchParameters searchParams = searchMapper.toSearchParameters(EMPTY_PARAMS, searchQuery, searchRequest);
searchMapper.toSearchParameters(EMPTY_PARAMS, searchQuery, searchRequest);
SearchContext searchContext = mapper.toSearchContext((SearchEngineResultSet) results, searchRequest, searchQuery);
assertEquals(34l, searchContext.getConsistency().getlastTxId());
assertEquals(6, searchContext.getFacetQueries().size());
@@ -384,9 +374,9 @@ public class ResultMapperTests
assertTrue(statsMetrics.contains(new SimpleMetric(METRIC_TYPE.missing, 0)));
assertTrue(statsMetrics.contains(new SimpleMetric(METRIC_TYPE.sum, 0)));
assertTrue(statsMetrics.contains(new SimpleMetric(METRIC_TYPE.stddev, 0)));
JSONArray dVals = new JSONArray(Arrays.asList(12, 13, 14, 15, 16, 17, 1));
JSONArray dVals = new JSONArray(asList(12, 13, 14, 15, 16, 17, 1));
assertTrue(statsMetrics.contains(new ListMetric(METRIC_TYPE.distinctValues, dVals)));
JSONArray pers = new JSONArray(Arrays.asList("0.99",20.0685, "0.0", 12.0));
JSONArray pers = new JSONArray(asList("0.99",20.0685, "0.0", 12.0));
assertTrue(statsMetrics.contains(new PercentileMetric(METRIC_TYPE.percentiles, pers)));
assertEquals("min must be excluded because its null",0,statsMetrics.stream().filter(metric -> METRIC_TYPE.min.equals(metric.getType())).count());
@@ -395,18 +385,18 @@ public class ResultMapperTests
}
@Test
public void testIsNullContext() throws Exception
public void testIsNullContext()
{
assertTrue(mapper.isNullContext(new SearchContext(0l,null,null,null,null, null)));
assertFalse(mapper.isNullContext(new SearchContext(1l,null,null,null,null, null)));
assertFalse(mapper.isNullContext(new SearchContext(0l,null,null,null,new SpellCheckContext(null, null), null)));
assertFalse(mapper.isNullContext(new SearchContext(0l,null, Arrays.asList(new FacetQueryContext(null, null, 0)),null,null, null)));
assertFalse(mapper.isNullContext(new SearchContext(0l,null,null,Arrays.asList(new FacetFieldContext(null, null)),null, null)));
assertFalse(mapper.isNullContext(new SearchContext(0l,Arrays.asList(new GenericFacetResponse(null,null, null)),null,null, null, null)));
assertFalse(mapper.isNullContext(new SearchContext(0l,null, asList(new FacetQueryContext(null, null, 0)),null,null, null)));
assertFalse(mapper.isNullContext(new SearchContext(0l,null,null, asList(new FacetFieldContext(null, null)),null, null)));
assertFalse(mapper.isNullContext(new SearchContext(0l, asList(new GenericFacetResponse(null,null, null)),null,null, null, null)));
}
@Test
public void testHighlight() throws Exception
public void testHighlight()
{
SearchParameters sp = new SearchParameters();
sp.setBulkFetchEnabled(false);
@@ -432,12 +422,11 @@ public class ResultMapperTests
@Test
public void testInterval() throws Exception
public void testInterval()
{
ResultSet results = mockResultset(Collections.emptyList(),Collections.emptyList());
ResultSet results = mockResultSet(Collections.emptyList(),Collections.emptyList());
SearchQuery searchQuery = helper.searchQueryFromJson();
SearchRequestContext searchRequest = SearchRequestContext.from(searchQuery);
SearchParameters searchParams = searchMapper.toSearchParameters(EMPTY_PARAMS, searchQuery, searchRequest);
SearchContext searchContext = mapper.toSearchContext((SearchEngineResultSet) results, searchRequest, searchQuery);
//Facet intervals
@@ -471,13 +460,13 @@ public class ResultMapperTests
assertEquals(METRIC_TYPE.count,((SimpleMetric) metrics[0]).getType());
assertEquals("854",((SimpleMetric) metrics[0]).getValue().get("count"));
}
@Test
public void testRange() throws Exception
public void testRange()
{
ResultSet results = mockResultset(Collections.emptyList(),Collections.emptyList());
ResultSet results = mockResultSet(Collections.emptyList(),Collections.emptyList());
SearchQuery searchQuery = helper.searchQueryFromJson();
SearchRequestContext searchRequest = SearchRequestContext.from(searchQuery);
SearchParameters searchParams = searchMapper.toSearchParameters(EMPTY_PARAMS, searchQuery, searchRequest);
SearchContext searchContext = mapper.toSearchContext((SearchEngineResultSet) results, searchRequest, searchQuery);
//Numeric facet range
@@ -524,14 +513,14 @@ public class ResultMapperTests
assertEquals("300",facetInfo.get("end"));
assertEquals("content.size:[\"200\" TO \"300\">", rangeFacets.get(1).getBuckets().get(2).getFilterQuery());
}
@Test
public void testRangeExclusiec() throws Exception
public void testRangeExclusiec()
{
ResultSet results = mockResultset(Collections.emptyList(),Collections.emptyList());
ResultSet results = mockResultSet(Collections.emptyList(),Collections.emptyList());
String updatedJSON = helper.JSON.replace("lower", "upper");
SearchQuery searchQuery = helper.extractFromJson(updatedJSON);
SearchRequestContext searchRequest = SearchRequestContext.from(searchQuery);
SearchParameters searchParams = searchMapper.toSearchParameters(EMPTY_PARAMS, searchQuery, searchRequest);
SearchContext searchContext = mapper.toSearchContext((SearchEngineResultSet) results, searchRequest, searchQuery);
//Numeric facet range
@@ -554,26 +543,25 @@ public class ResultMapperTests
}
@Test
/**
* Test facet group with out facet fields
* @throws Exception
*/
public void testFacetingGroupResponse() throws Exception
@Test
public void testFacetingGroupResponse()
{
String jsonQuery = "{\"query\": {\"query\": \"alfresco\"},"
+ "\"facetQueries\": ["
+ "{\"query\": \"content.size:[o TO 102400]\", \"label\": \"small\",\"group\":\"foo\"},"
+ "{\"query\": \"content.size:[102400 TO 1048576]\", \"label\": \"medium\",\"group\":\"foo\"},"
+ "{\"query\": \"content.size:[1048576 TO 16777216]\", \"label\": \"large\",\"group\":\"foo\"}]"
+ "}";
String expectedResponse = "{\"responseHeader\":{\"status\":0,\"QTime\":9},\"_original_parameters_\":\"org.apache.solr.common.params.DefaultSolrParams:{params(df=TEXT&alternativeDic=DEFAULT_DICTIONARY&fl=DBID,score&start=0&fq={!afts}AUTHORITY_FILTER_FROM_JSON&fq={!afts}TENANT_FILTER_FROM_JSON&rows=1000&locale=en_US&wt=json),defaults(carrot.url=id&spellcheck.collateExtendedResults=true&carrot.produceSummary=true&spellcheck.maxCollations=3&spellcheck.maxCollationTries=5&spellcheck.alternativeTermCount=2&spellcheck.extendedResults=false&defType=afts&spellcheck.maxResultsForSuggest=5&spellcheck=false&carrot.outputSubClusters=false&spellcheck.count=5&carrot.title=mltext@m___t@{http://www.alfresco.org/model/content/1.0}title&carrot.snippet=content@s___t@{http://www.alfresco.org/model/content/1.0}content&spellcheck.collate=true)}\",\"_field_mappings_\":{},\"_date_mappings_\":{},\"_range_mappings_\":{},\"_pivot_mappings_\":{},\"_interval_mappings_\":{},\"_stats_field_mappings_\":{},\"_stats_facet_mappings_\":{},\"_facet_function_mappings_\":{},\"response\":{\"numFound\":6,\"start\":0,\"maxScore\":0.7849362,\"docs\":[{\"DBID\":565,\"score\":0.7849362},{\"DBID\":566,\"score\":0.7849362},{\"DBID\":521,\"score\":0.3540957},{\"DBID\":514,\"score\":0.33025497},{\"DBID\":420,\"score\":0.32440513},{\"DBID\":415,\"score\":0.2780319}]},"
+ "\"spellcheck\":{\"searchInsteadFor\":\"alfresco\"},"
+ "\"facet_counts\":{\"facet_queries\": {\"small\": 52,\"large\": 0,\"medium\": 0}},"
+ "\"processedDenies\":true, \"lastIndexedTx\":34}";
+ "\"facetQueries\": ["
+ "{\"query\": \"content.size:[o TO 102400]\", \"label\": \"small\",\"group\":\"foo\"},"
+ "{\"query\": \"content.size:[102400 TO 1048576]\", \"label\": \"medium\",\"group\":\"foo\"},"
+ "{\"query\": \"content.size:[1048576 TO 16777216]\", \"label\": \"large\",\"group\":\"foo\"}]"
+ "}";
ResultSet results = mockResultset(expectedResponse);
String expectedResponse = "{\"responseHeader\":{\"status\":0,\"QTime\":9},\"_original_parameters_\":\"org.apache.solr.common.params.DefaultSolrParams:{params(df=TEXT&alternativeDic=DEFAULT_DICTIONARY&fl=DBID,score&start=0&fq={!afts}AUTHORITY_FILTER_FROM_JSON&fq={!afts}TENANT_FILTER_FROM_JSON&rows=1000&locale=en_US&wt=json),defaults(carrot.url=id&spellcheck.collateExtendedResults=true&carrot.produceSummary=true&spellcheck.maxCollations=3&spellcheck.maxCollationTries=5&spellcheck.alternativeTermCount=2&spellcheck.extendedResults=false&defType=afts&spellcheck.maxResultsForSuggest=5&spellcheck=false&carrot.outputSubClusters=false&spellcheck.count=5&carrot.title=mltext@m___t@{http://www.alfresco.org/model/content/1.0}title&carrot.snippet=content@s___t@{http://www.alfresco.org/model/content/1.0}content&spellcheck.collate=true)}\",\"_field_mappings_\":{},\"_date_mappings_\":{},\"_range_mappings_\":{},\"_pivot_mappings_\":{},\"_interval_mappings_\":{},\"_stats_field_mappings_\":{},\"_stats_facet_mappings_\":{},\"_facet_function_mappings_\":{},\"response\":{\"numFound\":6,\"start\":0,\"maxScore\":0.7849362,\"docs\":[{\"DBID\":565,\"score\":0.7849362},{\"DBID\":566,\"score\":0.7849362},{\"DBID\":521,\"score\":0.3540957},{\"DBID\":514,\"score\":0.33025497},{\"DBID\":420,\"score\":0.32440513},{\"DBID\":415,\"score\":0.2780319}]},"
+ "\"spellcheck\":{\"searchInsteadFor\":\"alfresco\"},"
+ "\"facet_counts\":{\"facet_queries\": {\"small\": 52,\"large\": 0,\"medium\": 0}},"
+ "\"processedDenies\":true, \"lastIndexedTx\":34}";
ResultSet results = mockResultSet(expectedResponse);
SearchQuery searchQuery = helper.extractFromJson(jsonQuery);
SearchRequestContext searchRequest = SearchRequestContext.from(searchQuery);
SearchContext searchContext = mapper.toSearchContext((SearchEngineResultSet) results, searchRequest, searchQuery);
@@ -587,28 +575,28 @@ public class ResultMapperTests
Metric[] metrics = searchContext.getFacets().get(0).getBuckets().get(0).getMetrics().toArray(new Metric[searchContext.getFacets().get(0).getBuckets().get(0).getMetrics().size()]);
assertEquals(METRIC_TYPE.count, metrics[0].getType());
assertEquals("{count=52}", metrics[0].getValue().toString());
}
@Test
/**
* Test facet group with out facet fields
* @throws Exception
*/
public void testFacetingGroupResponseV1() throws Exception
@Test
public void testFacetingGroupResponseV1()
{
String jsonQuery = "{\"query\": {\"query\": \"alfresco\"}, \"facetFormat\":\"V1\","
+ "\"facetQueries\": ["
+ "\"facetQueries\": ["
+ "{\"query\": \"content.size:[o TO 102400]\", \"label\": \"small\"},"
+ "{\"query\": \"content.size:[102400 TO 1048576]\", \"label\": \"medium\",\"group\":\"foo\"},"
+ "{\"query\": \"content.size:[102400 TO 1048576]\", \"label\": \"medium\",\"group\":\"foo\"},"
+ "{\"query\": \"content.size:[1048576 TO 16777216]\", \"label\": \"large\"}]"
+ "}";
String expectedResponse = "{\"responseHeader\":{\"status\":0,\"QTime\":9},\"_original_parameters_\":\"org.apache.solr.common.params.DefaultSolrParams:{params(df=TEXT&alternativeDic=DEFAULT_DICTIONARY&fl=DBID,score&start=0&fq={!afts}AUTHORITY_FILTER_FROM_JSON&fq={!afts}TENANT_FILTER_FROM_JSON&rows=1000&locale=en_US&wt=json),defaults(carrot.url=id&spellcheck.collateExtendedResults=true&carrot.produceSummary=true&spellcheck.maxCollations=3&spellcheck.maxCollationTries=5&spellcheck.alternativeTermCount=2&spellcheck.extendedResults=false&defType=afts&spellcheck.maxResultsForSuggest=5&spellcheck=false&carrot.outputSubClusters=false&spellcheck.count=5&carrot.title=mltext@m___t@{http://www.alfresco.org/model/content/1.0}title&carrot.snippet=content@s___t@{http://www.alfresco.org/model/content/1.0}content&spellcheck.collate=true)}\",\"_field_mappings_\":{},\"_date_mappings_\":{},\"_range_mappings_\":{},\"_pivot_mappings_\":{},\"_interval_mappings_\":{},\"_stats_field_mappings_\":{},\"_stats_facet_mappings_\":{},\"_facet_function_mappings_\":{},\"response\":{\"numFound\":6,\"start\":0,\"maxScore\":0.7849362,\"docs\":[{\"DBID\":565,\"score\":0.7849362},{\"DBID\":566,\"score\":0.7849362},{\"DBID\":521,\"score\":0.3540957},{\"DBID\":514,\"score\":0.33025497},{\"DBID\":420,\"score\":0.32440513},{\"DBID\":415,\"score\":0.2780319}]},"
+ "\"spellcheck\":{\"searchInsteadFor\":\"alfresco\"},"
+ "\"facet_counts\":{\"facet_queries\": {\"small\": 52,\"large\": 0,\"medium\": 0}},"
+ "\"processedDenies\":true, \"lastIndexedTx\":34}";
ResultSet results = mockResultset(expectedResponse);
ResultSet results = mockResultSet(expectedResponse);
SearchQuery searchQuery = helper.extractFromJson(jsonQuery);
SearchRequestContext searchRequest = SearchRequestContext.from(searchQuery);
SearchContext searchContext = mapper.toSearchContext((SearchEngineResultSet) results, searchRequest, searchQuery);
@@ -622,17 +610,15 @@ public class ResultMapperTests
Metric[] metrics = searchContext.getFacets().get(0).getBuckets().get(0).getMetrics().toArray(new Metric[searchContext.getFacets().get(0).getBuckets().get(0).getMetrics().size()]);
assertEquals(METRIC_TYPE.count, metrics[0].getType());
assertEquals("{count=52}", metrics[0].getValue().toString());
}
@Test
/**
* Test facet fields with out group label in the query.
* This is to support original api methods query for facet query.
*
*
* @throws Exception
*/
public void testFacetQueryWithoutGroupResponse() throws Exception
@Test
public void testFacetQueryWithoutGroupResponse()
{
String jsonQuery = "{\"query\": {\"query\": \"alfresco\"},"
+ "\"facetQueries\": ["
@@ -646,7 +632,7 @@ public class ResultMapperTests
+ "\"facet_counts\":{\"facet_queries\": {\"small\": 52,\"large\": 0,\"medium\": 0}},"
+ "\"processedDenies\":true, \"lastIndexedTx\":34}";
ResultSet results = mockResultset(expectedResponse);
ResultSet results = mockResultSet(expectedResponse);
SearchQuery searchQuery = helper.extractFromJson(jsonQuery);
SearchRequestContext searchRequest = SearchRequestContext.from(searchQuery);
SearchContext searchContext = mapper.toSearchContext((SearchEngineResultSet) results, searchRequest, searchQuery);
@@ -663,7 +649,8 @@ public class ResultMapperTests
assertEquals("content.size:[102400 TO 1048576]",searchContext.getFacetQueries().get(2).getFilterQuery());
assertEquals(0, searchContext.getFacetQueries().get(2).getCount());
}
private ResultSet mockResultset(String json) throws Exception
private ResultSet mockResultSet(String json)
{
NodeService nodeService = mock(NodeService.class);
JSONObject jsonObj = new JSONObject(new JSONTokener(json));
@@ -678,19 +665,17 @@ public class ResultMapperTests
return results;
}
private ResultSet mockResultset(List<Long> archivedNodes, List<Long> versionNodes) throws JSONException
private ResultSet mockResultSet(List<Long> archivedNodes, List<Long> versionNodes)
{
NodeService nodeService = mock(NodeService.class);
when(nodeService.getNodeRef(any())).thenAnswer(new Answer<NodeRef>() {
@Override
public NodeRef answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
//If the DBID is in the list archivedNodes, instead of returning a noderef return achivestore noderef
if (archivedNodes.contains(args[0])) return new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE, GUID.generate());
if (versionNodes.contains(args[0])) return new NodeRef(StoreMapper.STORE_REF_VERSION2_SPACESSTORE, GUID.generate()+args[0]);
return new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, GUID.generate());
}
when(nodeService.getNodeRef(any())).thenAnswer((Answer<NodeRef>) invocation ->
{
Object[] args = invocation.getArguments();
//If the DBID is in the list archivedNodes, instead of returning a noderef return achivestore noderef
if (archivedNodes.contains(args[0])) return new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE, GUID.generate());
if (versionNodes.contains(args[0])) return new NodeRef(StoreMapper.STORE_REF_VERSION2_SPACESSTORE, GUID.generate()+args[0]);
return new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, GUID.generate());
});
SearchParameters sp = new SearchParameters();
@@ -700,12 +685,12 @@ public class ResultMapperTests
return results;
}
@Test
/**
* Validates that when facetFormat is specified then all facets are returned
* in the generic facet response format AKA V2.
*/
public void facetFormatTest() throws Exception
@Test
public void facetFormatTest()
{
String jsonQuery = "{\"query\": {\"query\": \"alfresco\"},"
+ "\"facetQueries\": ["
@@ -720,7 +705,7 @@ public class ResultMapperTests
+ "\"facet_counts\":{\"facet_queries\": {\"small\": 52,\"large\": 0,\"medium\": 0}},"
+ "\"processedDenies\":true, \"lastIndexedTx\":34}";
ResultSet results = mockResultset(expectedResponse);
ResultSet results = mockResultSet(expectedResponse);
SearchQuery searchQuery = helper.extractFromJson(jsonQuery);
SearchRequestContext searchRequest = SearchRequestContext.from(searchQuery);
SearchContext searchContext = mapper.toSearchContext((SearchEngineResultSet) results, searchRequest, searchQuery);
@@ -737,7 +722,7 @@ public class ResultMapperTests
jsonQuery = jsonQuery.replace("V2", "V1");
searchQuery = helper.extractFromJson(jsonQuery);
results = mockResultset(expectedResponse);
results = mockResultSet(expectedResponse);
searchRequest = SearchRequestContext.from(searchQuery);
searchContext = mapper.toSearchContext((SearchEngineResultSet) results, searchRequest, searchQuery);
assertEquals(34l, searchContext.getConsistency().getlastTxId());
@@ -758,7 +743,7 @@ public class ResultMapperTests
+ "\"spellcheck\":{\"searchInsteadFor\":\"alfresco\"},"
+ "\"facet_counts\":{\"facet_fields\":{\"creator\":[\"System\",124,\"mjackson\",11,\"abeecher\",4],\"modifier\":[\"System\",124,\"mjackson\",8,\"admin\",7]}},"
+ "\"processedDenies\":true, \"lastIndexedTx\":34}";
results = mockResultset(expectedResponse);
results = mockResultSet(expectedResponse);
searchQuery = helper.extractFromJson(jsonQuery);
searchContext = mapper.toSearchContext((SearchEngineResultSet) results, searchRequest, searchQuery);
assertFalse(searchContext.getFacetsFields().isEmpty());
@@ -784,7 +769,7 @@ public class ResultMapperTests
}
@Test
public void hasGroupTest() throws IOException
public void hasGroupTest()
{
String jsonQuery = "{\"query\": {\"query\": \"alfresco\"},"
+ "\"facetQueries\": ["
@@ -809,7 +794,7 @@ public class ResultMapperTests
SearchQuery searchQuery3 = helper.extractFromJson(noFacetQueries);
assertFalse(ResultMapper.hasGroup(searchQuery3));
}
@Test
/**
* When the following is passed
* "facetQueries": [
@@ -817,9 +802,9 @@ public class ResultMapperTests
* {"query": "content.size:[102400 TO 1048576]", "label": "medium", "group": "two"},
* {"query": "content.size:[1048576 TO 16777216]", "label": "large"}
* We expect to see 3 groups of 1,2,null.
* @throws Exception
*/
public void testFacetingWithPartialGroup() throws Exception
@Test
public void testFacetingWithPartialGroup()
{
String jsonQuery = "{\"query\": {\"query\": \"alfresco\"},"
+ "\"facetQueries\": ["
@@ -833,7 +818,7 @@ public class ResultMapperTests
+ "\"facet_counts\":{\"facet_queries\": {\"small\": 52,\"large\": 0,\"medium\": 0}},"
+ "\"processedDenies\":true, \"lastIndexedTx\":34}";
ResultSet results = mockResultset(expectedResponse);
ResultSet results = mockResultSet(expectedResponse);
SearchQuery searchQuery = helper.extractFromJson(jsonQuery);
SearchRequestContext searchRequest = SearchRequestContext.from(searchQuery);
SearchContext searchContext = mapper.toSearchContext((SearchEngineResultSet) results, searchRequest, searchQuery);
@@ -853,8 +838,9 @@ public class ResultMapperTests
assertEquals("{count=52}", metrics[0].getValue().toString());
}
@Test
public void testSqlResponse() throws IOException, JSONException
public void testSqlResponse()
{
JSONObject response = new JSONObject("{\"docs\":[{\"SITE\":\"_REPOSITORY_\"},{\"SITE\":\"surf-config\"},{\"SITE\":\"swsdp\"},{\"EOF\":true,\"RESPONSE_TIME\":96}]}");
JSONArray docs = response.getJSONArray("docs");
@@ -888,4 +874,18 @@ public class ResultMapperTests
assertEquals("SearchSQLQuery is required", e.getMessage());
}
}
/** Check that when a node is returned from the index the permissions are still checked in the DB. */
@Test
public void testGetNode()
{
ResultSetRow mockRow = mock(ResultSetRow.class);
NodeRef nodeRef = new NodeRef("workspace://SpacesStore/testNode");
when(mockRow.getNodeRef()).thenReturn(nodeRef);
when(nodes.getFolderOrDocument(eq(nodeRef), any(), any(), any(), any())).thenThrow(new PermissionDeniedException());
Node node = mapper.getNode(mockRow, EMPTY_PARAMS, null, false);
assertNull("Expected node to be filtered due to permission exception.", node);
}
}

View File

@@ -52,7 +52,7 @@ import java.io.StringReader;
public class SerializerTestHelper implements RequestReader
{
JacksonHelper jsonHelper = null;
JacksonHelper jsonHelper;
public static final String JSON = "{ \"query\": {\"query\": \"g*\",\"userQuery\": \"great\",\"language\": \"afts\"}, "
+ "\"paging\": {\"maxItems\": \"99\",\"skipCount\": \"4\"},"
@@ -99,16 +99,23 @@ public class SerializerTestHelper implements RequestReader
}
}
public SearchQuery extractFromJson(String json) throws IOException
public SearchQuery extractFromJson(String json)
{
Content content = mock(Content.class);
when(content.getReader()).thenReturn(new StringReader(json));
try
{
when(content.getReader()).thenReturn(new StringReader(json));
}
catch (IOException e)
{
throw new IllegalStateException("Unexpectedly received exception when configuring mock.", e);
}
WebScriptRequest request = mock(WebScriptRequest.class);
when(request.getContent()).thenReturn(content);
return extractJsonContent(request, jsonHelper, SearchQuery.class);
}
public SearchQuery searchQueryFromJson() throws IOException
public SearchQuery searchQueryFromJson()
{
return extractFromJson(JSON);
}

View File

@@ -26,21 +26,26 @@
package org.alfresco.rest.api.tests;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.admin.RepoHealthChecker;
import org.alfresco.rest.api.discovery.DiscoveryApiWebscript;
import org.alfresco.rest.api.probes.ProbeEntityResource;
import org.alfresco.rest.api.tests.client.HttpResponse;
import org.json.simple.JSONObject;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import static org.alfresco.rest.api.probes.ProbeEntityResource.*;
import static org.alfresco.rest.api.probes.ProbeEntityResource.ProbeType.LIVE;
import static org.alfresco.rest.api.probes.ProbeEntityResource.ProbeType.READY;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.lenient;
/**
* V1 REST API tests for Probes (Live and Ready)
@@ -53,7 +58,6 @@ import static org.mockito.Mockito.when;
public class ProbeApiTest extends AbstractBaseApiTest
{
private static final boolean OK = true;
private static final boolean ERROR = false;
private ProbeEntityResource probe;
private DiscoveryApiWebscript origDiscovery;
@@ -64,6 +68,9 @@ public class ProbeApiTest extends AbstractBaseApiTest
@Mock
private DiscoveryApiWebscript badDiscovery;
@Mock
private RepoHealthChecker repoHealthChecker;
@Before
@Override
public void setup() throws Exception
@@ -73,7 +80,9 @@ public class ProbeApiTest extends AbstractBaseApiTest
String beanName = ProbeEntityResource.class.getCanonicalName()+".get";
probe = applicationContext.getBean(beanName, ProbeEntityResource.class);
when(badDiscovery.getRepositoryInfo()).thenThrow(AlfrescoRuntimeException.class);
lenient().when(badDiscovery.getRepositoryInfo()).thenThrow(AlfrescoRuntimeException.class);
Mockito.doNothing().when(repoHealthChecker).checkDatabase();
probe.setRepoHealthChecker(repoHealthChecker);
origDiscovery = probe.setDiscovery(badDiscovery);
}
@@ -91,7 +100,7 @@ public class ProbeApiTest extends AbstractBaseApiTest
return "public";
}
private void assertResponse(String probeName, Boolean ready, String expected, int expectedStatus) throws Exception
private void assertResponse(ProbeType probeType, Boolean ready, String expected, int expectedStatus) throws Exception
{
String[] keys = expectedStatus == 200
? new String[]{"entry", "message"}
@@ -103,7 +112,7 @@ public class ProbeApiTest extends AbstractBaseApiTest
? goodDiscovery
: badDiscovery);
HttpResponse response = getSingle(ProbeEntityResource.class, probeName, null, expectedStatus);
HttpResponse response = getSingle(ProbeEntityResource.class, probeType.getValue(), null, expectedStatus);
Object object = response.getJsonResponse();
for (String key: keys)
{
@@ -128,32 +137,29 @@ public class ProbeApiTest extends AbstractBaseApiTest
public void testProbes() throws Exception
{
// Live first
assertResponse(LIVE, ERROR, "liveProbe: Failure - Tested", 503);
assertResponse(LIVE, null, "liveProbe: Failure - No test", 503); // Need to wait 10 seconds.
assertResponse(LIVE, null, "liveProbe: Failure - No test", 503);
assertResponse(READY, null, "readyProbe: Failure - No test", 503);
assertResponse(LIVE, OK, "liveProbe: Success - Tested", 200);
assertResponse(READY, null, "readyProbe: Failure - Tested", 503);
Thread.currentThread().sleep(CHECK_PERIOD);
assertResponse(READY, OK, "readyProbe: Success - Tested", 200);
assertResponse(READY, null, "readyProbe: Success - No test", 200);
Thread.currentThread().sleep(CHECK_PERIOD);
assertResponse(LIVE, OK, "liveProbe: Success - Tested", 200);
assertResponse(LIVE, null, "liveProbe: Success - No test", 200);
assertResponse(READY, null, "readyProbe: Success - No test", 200);
assertResponse(LIVE, null, "liveProbe: Success - No test", 200);
Thread.currentThread().sleep(CHECK_PERIOD);
assertResponse(LIVE, ERROR, "liveProbe: Failure - Tested", 503);
assertResponse(LIVE, null, "liveProbe: Failure - No test", 503);
assertResponse(READY, null, "readyProbe: Failure - No test", 503);
assertResponse(READY, null, "readyProbe: Failure - Tested", 503);
// Ready first
Thread.currentThread().sleep(CHECK_PERIOD);
assertResponse(READY, OK, "readyProbe: Success - Tested", 200);
assertResponse(LIVE, null, "liveProbe: Success - No test", 200);
assertResponse(LIVE, OK, "liveProbe: Success - Tested", 200);
assertResponse(READY, null, "readyProbe: Success - No test", 200);
// check db failure
Thread.currentThread().sleep(CHECK_PERIOD);
assertResponse(READY, ERROR, "readyProbe: Failure - Tested", 503);
assertResponse(LIVE, null, "liveProbe: Failure - No test", 503);
Mockito.doThrow(AlfrescoRuntimeException.class).when(repoHealthChecker).checkDatabase();
assertResponse(READY, OK, "readyProbe: Failure - Tested", 503);
assertResponse(READY, OK, "readyProbe: Failure - No test", 503);
}
}

View File

@@ -60,8 +60,11 @@ import org.alfresco.cmis.client.impl.AlfrescoObjectFactoryImpl;
import org.alfresco.cmis.client.type.AlfrescoType;
import org.alfresco.model.ContentModel;
import org.alfresco.model.RenditionModel;
import org.alfresco.opencmis.CMISDispatcher;
import org.alfresco.opencmis.CMISDispatcherRegistry.Binding;
import org.alfresco.opencmis.CMISServletDispatcher;
import org.alfresco.opencmis.PublicApiAlfrescoCmisServiceFactory;
import org.alfresco.opencmis.PublicApiBrowserCMISDispatcher;
import org.alfresco.opencmis.dictionary.CMISStrictDictionaryService;
import org.alfresco.opencmis.dictionary.QNameFilter;
import org.alfresco.opencmis.dictionary.QNameFilterImpl;
@@ -99,6 +102,7 @@ import org.alfresco.rest.api.tests.client.data.NodeRating.Aggregate;
import org.alfresco.rest.api.tests.client.data.Person;
import org.alfresco.rest.api.tests.client.data.SiteRole;
import org.alfresco.rest.api.tests.client.data.Tag;
import org.alfresco.rest.framework.core.exceptions.JsonpCallbackNotAllowedException;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.lock.LockType;
import org.alfresco.service.cmr.model.FileFolderService;
@@ -153,6 +157,7 @@ import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.springframework.context.ApplicationContext;
import org.springframework.extensions.surf.util.I18NUtil;
import org.springframework.extensions.surf.util.URLEncoder;
public class TestCMIS extends EnterpriseTestApi
@@ -517,6 +522,73 @@ public class TestCMIS extends EnterpriseTestApi
assertEquals(200, response.getStatusCode());
}
/**
* MNT-22428 Check the return from http://localhost:8080/alfresco/api/-default-/public/cmis/versions/1.1/browser/root&callback= when jsonp callback is disabled
*
* @throws Exception
*/
@Test
public void testBrowserDisabledJSONPCallback() throws Exception
{
// disables unsecure callback jsonp
final PublicApiBrowserCMISDispatcher dispatcher = ctx.getBean(PublicApiBrowserCMISDispatcher.class);
dispatcher.setAllowUnsecureCallbackJSONP(false);
final TestNetwork network1 = getTestFixture().getRandomNetwork();
Iterator<String> personIt = network1.getPersonIds().iterator();
final String personId = personIt.next();
assertNotNull(personId);
Person person = repoService.getPerson(personId);
assertNotNull(person);
publicApiClient.setRequestContext(new RequestContext(network1.getId(), personId));
// request with a callback parameter
HttpResponse response;
final Map<String, String> params = Map.of("callback", "");
response = publicApiClient.get(network1.getId() + "/public/cmis/versions/1.1/browser/root", params);
assertEquals(403, response.getStatusCode());
String exceptionMessage = I18NUtil.getMessage(JsonpCallbackNotAllowedException.DEFAULT_MESSAGE_ID, params);
assertTrue(response.getResponse().endsWith(exceptionMessage));
// request without a callback parameter
response = publicApiClient.get(network1.getId() + "/public/cmis/versions/1.1/browser/root", null);
assertEquals(200, response.getStatusCode());
}
/*
* MNT-22428 Check the return from http://localhost:8080/alfresco/api/-default-/public/cmis/versions/1.1/browser/root&callback= when jsonp callback is enabled
*
* @throws Exception
*/
@Test
public void testBrowserEnabledJSONPCallback() throws Exception
{
// enables unsecure callback jsonp
final PublicApiBrowserCMISDispatcher dispatcher = ctx.getBean(PublicApiBrowserCMISDispatcher.class);
dispatcher.setAllowUnsecureCallbackJSONP(true);
final TestNetwork network1 = getTestFixture().getRandomNetwork();
Iterator<String> personIt = network1.getPersonIds().iterator();
final String personId = personIt.next();
assertNotNull(personId);
Person person = repoService.getPerson(personId);
assertNotNull(person);
publicApiClient.setRequestContext(new RequestContext(network1.getId(), personId));
// request with a callback parameter
HttpResponse response;
final Map<String, String> params = Map.of("callback", "someFunction");
response = publicApiClient.get(network1.getId() + "/public/cmis/versions/1.1/browser/root", params);
assertEquals(200, response.getStatusCode());
// request without a callback parameter
response = publicApiClient.get(network1.getId() + "/public/cmis/versions/1.1/browser/root", null);
assertEquals(200, response.getStatusCode());
}
/**
* REPO-2041 / MNT-16236 Upload via cmis binding atom and browser files with different maxContentSize
*/

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>11.141-SNAPSHOT</version>
<version>14.20-SNAPSHOT</version>
</parent>
<dependencies>
@@ -191,7 +191,7 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>3.8.1</version>
<version>3.8.3</version>
</dependency>
<dependency>
<groupId>de.schlichtherle.truezip</groupId>

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.encryption;
import java.io.Serializable;
@@ -241,6 +241,12 @@ public class ReEncryptor implements ApplicationContextAware
return properties.size();
}
@Override
public long getTotalEstimatedWorkSizeLong()
{
return properties.size();
}
@Override
public Collection<NodePropertyEntity> getNextWork()
{

View File

@@ -1959,6 +1959,12 @@ public class AlfrescoCmisServiceImpl extends AbstractCmisService implements Alfr
return size;
}
@Override
public synchronized long getTotalEstimatedWorkSizeLong()
{
return size;
}
@Override
public synchronized Collection<BulkEntry> getNextWork()
{

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.activities.feed;
import java.util.Collection;
@@ -427,6 +427,12 @@ public class FeedNotifierImpl implements FeedNotifier, ApplicationContextAware
return personService.countPeople();
}
@Override
public long getTotalEstimatedWorkSizeLong()
{
return personService.countPeople();
}
@Override
public Collection<PersonInfo> getNextWork()
{

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.activities.feed.local;
import java.util.ArrayList;
@@ -155,13 +155,25 @@ public class LocalFeedGenerator extends AbstractFeedGenerator
@Override
public int getTotalEstimatedWorkSize()
{
return (int) calculateEstimatedWorkSize();
}
@Override
public long getTotalEstimatedWorkSizeLong()
{
return calculateEstimatedWorkSize();
}
private long calculateEstimatedWorkSize()
{
long size = maxSequence - minSequence + 1;
long remain = size % batchSize;
long workSize = (remain == 0) ? (size / batchSize) : (size / batchSize + 1);
return (int) workSize;
return workSize;
}
@Override
public Collection<JobSettings> getNextWork()
{

View File

@@ -0,0 +1,47 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2018 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.admin;
import org.alfresco.repo.domain.schema.DataSourceCheck;
/**
* A utility service to do the database and other health checks.
*/
public class RepoHealthChecker
{
private final DataSourceCheck dataSourceCheck;
public RepoHealthChecker(DataSourceCheck dataSourceCheck)
{
this.dataSourceCheck = dataSourceCheck;
}
public void checkDatabase()
{
dataSourceCheck.init();
}
}

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.admin.patch;
import java.io.PrintWriter;
@@ -486,6 +486,11 @@ public abstract class AbstractPatch implements Patch, ApplicationEventPublisher
return tenants.size();
}
public long getTotalEstimatedWorkSizeLong()
{
return tenants.size();
}
@Override
public Collection<Tenant> getNextWork()
{
@@ -554,13 +559,13 @@ public abstract class AbstractPatch implements Patch, ApplicationEventPublisher
logger.debug("batch worker finished processing id:" + id);
}
if (batchProcessor.getTotalErrors() > 0)
if (batchProcessor.getTotalErrorsLong() > 0)
{
sb.append("\n" + " and failure during update of tennants total success: " + batchProcessor.getSuccessfullyProcessedEntries() + " number of errors: " +batchProcessor.getTotalErrors() + " lastError" + batchProcessor.getLastError());
sb.append("\n" + " and failure during update of tennants total success: " + batchProcessor.getSuccessfullyProcessedEntriesLong() + " number of errors: " +batchProcessor.getTotalErrorsLong() + " lastError" + batchProcessor.getLastError());
}
else
{
sb.append("\n" + " and successful batch update of " + batchProcessor.getTotalResults() + "tennants");
sb.append("\n" + " and successful batch update of " + batchProcessor.getTotalResultsLong() + "tennants");
}
}

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.admin.patch.impl;
import java.util.ArrayList;
@@ -90,6 +90,12 @@ public class AddUnmovableAspectToSitesPatch extends AsynchronousPatch
return sites.size();
}
@Override
public long getTotalEstimatedWorkSizeLong()
{
return sites.size();
}
@Override
public Collection<ChildAssociationRef> getNextWork()
{

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.admin.patch.impl;
import java.util.ArrayList;
@@ -93,6 +93,11 @@ public class AliasableAspectPatch extends AbstractPatch
return result.size();
}
public long getTotalEstimatedWorkSizeLong()
{
return result.size();
}
public Collection<NodeRef> getNextWork()
{
if(val != null)

View File

@@ -237,6 +237,12 @@ public class FixBpmPackagesPatch extends AbstractPatch
return assocCount;
}
@Override
public synchronized long getTotalEstimatedWorkSizeLong()
{
return assocCount;
}
@Override
public synchronized Collection<ChildAssociationRef> getNextWork()
{

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.admin.patch.impl;
import java.util.ArrayList;
@@ -76,6 +76,11 @@ public class ImapUnsubscribedAspectPatch extends AbstractPatch
return result.size();
}
public long getTotalEstimatedWorkSizeLong()
{
return result.size();
}
public Collection<NodeRef> getNextWork()
{
result.clear();

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.admin.patch.impl;
import java.util.ArrayList;
@@ -143,6 +143,12 @@ public class RenameSiteAuthorityDisplayName extends AbstractPatch
{
return siteInfos.size();
}
@Override
public long getTotalEstimatedWorkSizeLong()
{
return siteInfos.size();
}
@Override
public Collection<SiteInfo> getNextWork()

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.admin.patch.impl;
@@ -449,6 +449,12 @@ public class SurfConfigFolderPatch extends AsynchronousPatch
@Override
public synchronized int getTotalEstimatedWorkSize()
{
return (int)getTotalEstimatedWorkSizeLong();
}
@Override
public synchronized long getTotalEstimatedWorkSizeLong()
{
if (maxId == Long.MAX_VALUE)
{
@@ -459,6 +465,7 @@ public class SurfConfigFolderPatch extends AsynchronousPatch
}
}
return 0;
}
@Override

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.batch;
import java.util.Date;
@@ -50,10 +50,10 @@ public interface BatchMonitor
/**
* Gets the total number of results.
*
* @deprecated use {@link #getTotalResultsLong()} instead
* @return the total number of results
*/
public int getTotalResults();
@Deprecated public int getTotalResults();
/**
* Gets the ID of the entry being processed
@@ -64,10 +64,10 @@ public interface BatchMonitor
/**
* Gets the number of successfully processed entries.
*
* @deprecated use {@link #getSuccessfullyProcessedEntriesLong()} instead
* @return the successfully processed entries
*/
public int getSuccessfullyProcessedEntries();
@Deprecated public int getSuccessfullyProcessedEntries();
/**
* Gets the progress expressed as a percentage.
@@ -78,10 +78,10 @@ public interface BatchMonitor
/**
* Gets the total number of errors.
*
* @deprecated use {@link #getTotalErrorsLong()} instead
* @return the total number of errors
*/
public int getTotalErrors();
@Deprecated public int getTotalErrors();
/**
* Gets the stack trace of the last error.
@@ -103,4 +103,35 @@ public interface BatchMonitor
* @return the end time
*/
public Date getEndTime();
/**
* Gets the total number of results.
*
* @return the total number of results
*/
public default long getTotalResultsLong()
{
throw new UnsupportedOperationException("getTotalResultsLong need to be implemented");
}
/**
* Gets the total number of errors.
*
* @return the total number of errors
*/
public default long getTotalErrorsLong()
{
throw new UnsupportedOperationException("getTotalErrorsLong need to be implemented");
}
/**
* Gets the number of successfully processed entries.
*
* @return the successfully processed entries
*/
public default long getSuccessfullyProcessedEntriesLong()
{
throw new UnsupportedOperationException("getSuccessfullyProcessedEntriesLong need to be implemented");
}
}

View File

@@ -43,10 +43,10 @@ public interface BatchProcessWorkProvider<T>
* Instances can provide accurate answers on each call, but only if the answer can be
* provided quickly and efficiently; usually it is enough to to cache the result after
* providing an initial estimate.
*
* @deprecated use {@link #getTotalEstimatedWorkSizeLong()} instead.
* @return a total work size estimate
*/
int getTotalEstimatedWorkSize();
@Deprecated int getTotalEstimatedWorkSize();
/**
* Get the next lot of work for the batch processor. Implementations should return
@@ -58,4 +58,18 @@ public interface BatchProcessWorkProvider<T>
* if there is no more work remaining.
*/
Collection<T> getNextWork();
/**
* Get an estimate of the total number of objects that will be provided by this instance.
* Instances can provide accurate answers on each call, but only if the answer can be
* provided quickly and efficiently; usually it is enough to to cache the result after
* providing an initial estimate.
*
* @return a total work size estimate
*/
default long getTotalEstimatedWorkSizeLong()
{
throw new UnsupportedOperationException("getTotalEstimatedWorkSizeLong need to implemented");
}
}

View File

@@ -110,10 +110,10 @@ public class BatchProcessor<T> implements BatchMonitor
private String lastErrorEntryId;
/** The total number of errors. */
private int totalErrors;
private long totalErrors;
/** The number of successfully processed entries. */
private int successfullyProcessedEntries;
private long successfullyProcessedEntries;
/** The start time. */
private Date startTime;
@@ -280,7 +280,15 @@ public class BatchProcessor<T> implements BatchMonitor
/**
* {@inheritDoc}
*/
public synchronized int getSuccessfullyProcessedEntries()
@Deprecated public synchronized int getSuccessfullyProcessedEntries()
{
return Math.toIntExact(this.successfullyProcessedEntries);
}
/**
* {@inheritDoc}
*/
public synchronized long getSuccessfullyProcessedEntriesLong()
{
return this.successfullyProcessedEntries;
}
@@ -290,8 +298,8 @@ public class BatchProcessor<T> implements BatchMonitor
*/
public synchronized String getPercentComplete()
{
int totalResults = this.workProvider.getTotalEstimatedWorkSize();
int processed = this.successfullyProcessedEntries + this.totalErrors;
long totalResults = this.workProvider.getTotalEstimatedWorkSizeLong();
long processed = this.successfullyProcessedEntries + this.totalErrors;
return processed <= totalResults ? NumberFormat.getPercentInstance().format(
totalResults == 0 ? 1.0F : (float) processed / totalResults) : "Unknown";
}
@@ -299,7 +307,23 @@ public class BatchProcessor<T> implements BatchMonitor
/**
* {@inheritDoc}
*/
public synchronized int getTotalErrors()
@Deprecated public synchronized int getTotalErrors()
{
return Math.toIntExact(this.totalErrors);
}
/**
* {@inheritDoc}
*/
@Deprecated public int getTotalResults()
{
return this.workProvider.getTotalEstimatedWorkSize();
}
/**
* {@inheritDoc}
*/
public synchronized long getTotalErrorsLong()
{
return this.totalErrors;
}
@@ -307,9 +331,9 @@ public class BatchProcessor<T> implements BatchMonitor
/**
* {@inheritDoc}
*/
public int getTotalResults()
public long getTotalResultsLong()
{
return this.workProvider.getTotalEstimatedWorkSize();
return this.workProvider.getTotalEstimatedWorkSizeLong();
}
/**
@@ -340,12 +364,42 @@ public class BatchProcessor<T> implements BatchMonitor
* increased performance. If <code>false</code>, all invocations are performed in the current
* transaction. This is required if calling synchronously (e.g. in response to an authentication event in
* the same transaction).
* @deprecated use {@link #processLong(BatchProcessWorker, boolean)} instead
* @return the number of invocations
*/
@SuppressWarnings("serial")
public int process(final BatchProcessWorker<T> worker, final boolean splitTxns)
@Deprecated public int process(final BatchProcessWorker<T> worker, final boolean splitTxns)
{
int count = workProvider.getTotalEstimatedWorkSize();
return (int)process(worker, splitTxns, count);
}
/**
* Invokes the worker for each entry in the collection, managing transactions and collating success / failure
* information.
*
* @param worker
* the worker
* @param splitTxns
* Can the modifications to Alfresco be split across multiple transactions for maximum performance? If
* <code>true</code>, worker invocations are isolated in separate transactions in batches for
* increased performance. If <code>false</code>, all invocations are performed in the current
* transaction. This is required if calling synchronously (e.g. in response to an authentication event in
* the same transaction).
* @return the number of invocations
*/
@SuppressWarnings("serial")
public long processLong(final BatchProcessWorker<T> worker, final boolean splitTxns)
{
long count = workProvider.getTotalEstimatedWorkSizeLong();
return process(worker, splitTxns, count);
}
private long process(final BatchProcessWorker<T> worker, final boolean splitTxns, long count)
{
synchronized (this)
{
this.startTime = new Date();
@@ -365,27 +419,27 @@ public class BatchProcessor<T> implements BatchMonitor
// Create a thread pool executor with the specified number of threads and a finite blocking queue of jobs
ExecutorService executorService = splitTxns && this.workerThreads > 1 ?
new ThreadPoolExecutor(
this.workerThreads, this.workerThreads, 0L, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(this.workerThreads * this.batchSize * 10)
{
// Add blocking behaviour to work queue
@Override
public boolean offer(Runnable o)
{
try
{
put(o);
}
catch (InterruptedException e)
{
return false;
}
return true;
}
new ThreadPoolExecutor(
this.workerThreads, this.workerThreads, 0L, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(this.workerThreads * this.batchSize * 10)
{
// Add blocking behaviour to work queue
@Override
public boolean offer(Runnable o)
{
try
{
put(o);
}
catch (InterruptedException e)
{
return false;
}
return true;
}
},
threadFactory) : null;
},
threadFactory) : null;
try
{
Iterator<T> iterator = new WorkProviderIterator<T>(this.workProvider);
@@ -402,7 +456,7 @@ public class BatchProcessor<T> implements BatchMonitor
{
batch = new ArrayList<T>(this.batchSize);
}
if (executorService == null)
{
callback.run();
@@ -447,13 +501,12 @@ public class BatchProcessor<T> implements BatchMonitor
if (this.totalErrors > 0 && this.logger.isErrorEnabled())
{
this.logger.error(getProcessName() + ": " + this.totalErrors
+ " error(s) detected. Last error from entry \"" + this.lastErrorEntryId + "\"",
this.lastError);
+ " error(s) detected. Last error from entry \"" + this.lastErrorEntryId + "\"",
this.lastError);
}
}
}
}
/**
* Reports the current progress.
*
@@ -464,12 +517,20 @@ public class BatchProcessor<T> implements BatchMonitor
*/
private synchronized void reportProgress(boolean last)
{
int processed = this.successfullyProcessedEntries + this.totalErrors;
long processed = this.successfullyProcessedEntries + this.totalErrors;
if (processed % this.loggingInterval == 0 ^ last)
{
StringBuilder message = new StringBuilder(100).append(getProcessName()).append(": Processed ").append(
processed).append(" entries");
int totalResults = this.workProvider.getTotalEstimatedWorkSize();
long totalResults = 0;
try
{
totalResults = this.workProvider.getTotalEstimatedWorkSizeLong();
}
catch (UnsupportedOperationException uoe)
{
totalResults = this.workProvider.getTotalEstimatedWorkSize();
}
if (totalResults >= processed)
{
message.append(" out of ").append(totalResults).append(". ").append(
@@ -830,11 +891,11 @@ public class BatchProcessor<T> implements BatchMonitor
{
if (this.txnErrors > 0)
{
int processed = BatchProcessor.this.successfullyProcessedEntries + BatchProcessor.this.totalErrors;
int currentIncrement = processed % BatchProcessor.this.loggingInterval;
int newErrors = BatchProcessor.this.totalErrors + this.txnErrors;
long processed = BatchProcessor.this.successfullyProcessedEntries + BatchProcessor.this.totalErrors;
long currentIncrement = processed % BatchProcessor.this.loggingInterval;
long newErrors = BatchProcessor.this.totalErrors + this.txnErrors;
// Work out the number of logging intervals we will cross and report them
int intervals = (this.txnErrors + currentIncrement) / BatchProcessor.this.loggingInterval;
long intervals = (this.txnErrors + currentIncrement) / BatchProcessor.this.loggingInterval;
if (intervals > 0)
{
BatchProcessor.this.totalErrors += BatchProcessor.this.loggingInterval - currentIncrement;
@@ -850,11 +911,11 @@ public class BatchProcessor<T> implements BatchMonitor
if (this.txnSuccesses > 0)
{
int processed = BatchProcessor.this.successfullyProcessedEntries + BatchProcessor.this.totalErrors;
int currentIncrement = processed % BatchProcessor.this.loggingInterval;
int newSuccess = BatchProcessor.this.successfullyProcessedEntries + this.txnSuccesses;
long processed = BatchProcessor.this.successfullyProcessedEntries + BatchProcessor.this.totalErrors;
long currentIncrement = processed % BatchProcessor.this.loggingInterval;
long newSuccess = BatchProcessor.this.successfullyProcessedEntries + this.txnSuccesses;
// Work out the number of logging intervals we will cross and report them
int intervals = (this.txnSuccesses + currentIncrement) / BatchProcessor.this.loggingInterval;
long intervals = (this.txnSuccesses + currentIncrement) / BatchProcessor.this.loggingInterval;
if (intervals > 0)
{
BatchProcessor.this.successfullyProcessedEntries += BatchProcessor.this.loggingInterval

View File

@@ -1,20 +1,20 @@
/*
* #%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,
* #%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.
@@ -195,6 +195,12 @@ public class StripingFilesystemTracker extends AbstractFilesystemTracker
return count();
}
@Override
public long getTotalEstimatedWorkSizeLong()
{
return count();
}
@Override
public Collection<ImportableItem> getNextWork()
{

View File

@@ -605,7 +605,7 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
throw new IllegalArgumentException("The supplied nodeRef " + nodeRef + " has no content.");
}
contentDirectUrlEnabled = (store.isContentDirectUrlEnabled(getContentUrl(nodeRef)));
contentDirectUrlEnabled = (store.isContentDirectUrlEnabled(contentData.getContentUrl()));
}
return contentDirectUrlEnabled;
@@ -621,8 +621,17 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
throw new DirectAccessUrlDisabledException("Direct access url isn't available.");
}
String contentUrl = getContentUrl(nodeRef);
ContentData contentData = getContentData(nodeRef, ContentModel.PROP_CONTENT);
// check that the content & URL is available
if (contentData == null || contentData.getContentUrl() == null)
{
throw new IllegalArgumentException("The supplied nodeRef " + nodeRef + " has no content.");
}
String contentUrl = contentData.getContentUrl();
String contentMimetype = contentData.getMimetype();
String fileName = getFileName(nodeRef);
validFor = adjustValidFor(validFor);
DirectAccessUrl directAccessUrl = null;
@@ -630,7 +639,7 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
{
try
{
directAccessUrl = store.requestContentDirectUrl(contentUrl, attachment, fileName, validFor);
directAccessUrl = store.requestContentDirectUrl(contentUrl, attachment, fileName, contentMimetype, validFor);
}
catch (UnsupportedOperationException ex)
{
@@ -640,19 +649,6 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
return directAccessUrl;
}
protected String getContentUrl(NodeRef nodeRef)
{
ContentData contentData = getContentData(nodeRef, ContentModel.PROP_CONTENT);
// check that the URL is available
if (contentData == null || contentData.getContentUrl() == null)
{
throw new IllegalArgumentException("The supplied nodeRef " + nodeRef + " has no content.");
}
return contentData.getContentUrl();
}
protected String getFileName(NodeRef nodeRef)
{
String fileName = null;

View File

@@ -509,4 +509,12 @@ public class CachingContentStore implements ContentStore, ApplicationEventPublis
{
return backingStore.requestContentDirectUrl(contentUrl, attachment, fileName, validFor);
}
/**
* {@inheritDoc}
*/
public DirectAccessUrl requestContentDirectUrl(String contentUrl, boolean attachment, String fileName, String mimeType, Long validFor)
{
return backingStore.requestContentDirectUrl(contentUrl, attachment, fileName, mimeType, validFor);
}
}

View File

@@ -317,7 +317,7 @@ public class AggregatingContentStore extends AbstractContentStore
return isContentDirectUrlEnabled;
}
public DirectAccessUrl requestContentDirectUrl(String contentUrl, boolean attachment, String fileName, Long validFor)
public DirectAccessUrl requestContentDirectUrl(String contentUrl, boolean attachment, String fileName, String mimetype, Long validFor)
{
if (primaryStore == null)
{
@@ -337,7 +337,7 @@ public class AggregatingContentStore extends AbstractContentStore
// Check the primary store
try
{
directAccessUrl = primaryStore.requestContentDirectUrl(contentUrl, attachment, fileName, validFor);
directAccessUrl = primaryStore.requestContentDirectUrl(contentUrl, attachment, fileName, mimetype, validFor);
}
catch (UnsupportedOperationException e)
{
@@ -360,7 +360,7 @@ public class AggregatingContentStore extends AbstractContentStore
{
try
{
directAccessUrl = store.requestContentDirectUrl(contentUrl, attachment, fileName, validFor);
directAccessUrl = store.requestContentDirectUrl(contentUrl, attachment, fileName, mimetype, validFor);
}
catch (UnsupportedOperationException e)
{

View File

@@ -241,9 +241,14 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
@Override
public int getTotalEstimatedWorkSize()
{
int workSize = getNodesWithAspects.getWorkSize();
return workSize;
return (int)getTotalEstimatedWorkSizeLong();
}
@Override
public long getTotalEstimatedWorkSizeLong()
{
return getNodesWithAspects.getWorkSize();
}
@Override
public Collection<NodeRef> getNextWork()

View File

@@ -244,6 +244,15 @@ public class NodeArchiveServiceImpl implements NodeArchiveService
{
return 0;
}
/**
* @return Returns 0, always
*/
public synchronized long getTotalEstimatedWorkSizeLong()
{
return 0;
}
public synchronized Collection<NodeRef> getNextWork()
{
if (vmShutdownLister.isVmShuttingDown())

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.node.db;
import java.util.Collection;
@@ -240,6 +240,12 @@ public class NodeStringLengthWorker implements ApplicationContextAware
return -1;
}
@Override
public long getTotalEstimatedWorkSizeLong()
{
return -1;
}
@Override
public Collection<NodePropertyEntity> getNextWork()
{

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.security.authentication;
import java.io.Serializable;
@@ -403,6 +403,15 @@ public class UpgradePasswordHashWorker implements ApplicationContextAware, Initi
return (int)totalUserCount;
}
@Override
public long getTotalEstimatedWorkSizeLong()
{
// execute a query to get total number of user nodes in the system.
long totalUserCount = patchDAO.getCountNodesWithTypId(ContentModel.TYPE_USER);
return totalUserCount;
}
@Override
public Collection<Long> getNextWork()
{

View File

@@ -1,30 +1,33 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 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.security.permissions.impl.acegi;
import static org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtils.getNodeRef;
import static org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtils.shouldAbstainOrDeny;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -46,8 +49,6 @@ import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.OwnableService;
@@ -59,6 +60,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
/**
* @author andyh
*/
@@ -395,61 +397,53 @@ public class ACLEntryVoter implements AccessDecisionVoter, InitializingBean
{
throw new ACLEntryVoterException("The specified parameter is not a NodeRef or ChildAssociationRef");
}
else if (StoreRef.class.isAssignableFrom(params[cad.parameter[0]]))
if (List.class.isAssignableFrom(params[cad.parameter[0]]))
{
StoreRef storeRef = getArgument(invocation, cad.parameter[0]);
if (storeRef != null)
List<?> listArgument = getArgument(invocation, cad.parameter[0]);
if (listArgument != null)
{
if (log.isDebugEnabled())
NodeRef listNodeRef;
Integer accessAbstainOrDeny = null;
for (Object listElement : listArgument)
{
log.debug("\tPermission test against the store - using permissions on the root node");
}
if (nodeService.exists(storeRef))
{
testNodeRef = nodeService.getRootNode(storeRef);
}
}
}
else if (NodeRef.class.isAssignableFrom(params[cad.parameter[0]]))
{
testNodeRef = getArgument(invocation, cad.parameter[0]);
if (log.isDebugEnabled())
{
if (testNodeRef != null)
{
if (nodeService.exists(testNodeRef))
listNodeRef = getNodeRef(listElement, nodeService);
Integer currentValue = shouldAbstainOrDeny(cad.required, listNodeRef, abstainForClassQNames, nodeService, permissionService);
if (currentValue != null)
{
log.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
if (currentValue == AccessDecisionVoter.ACCESS_DENIED)
{
return AccessDecisionVoter.ACCESS_DENIED;
}
else
{
accessAbstainOrDeny = currentValue;
}
}
else
{
log.debug("\tPermission test on non-existing node " +testNodeRef);
}
}
}
}
else if (ChildAssociationRef.class.isAssignableFrom(params[cad.parameter[0]]))
{
ChildAssociationRef testChildRef = getArgument(invocation, cad.parameter[0]);
if (testChildRef != null)
{
testNodeRef = testChildRef.getChildRef();
if (log.isDebugEnabled())
if (accessAbstainOrDeny != null)
{
if (nodeService.exists(testNodeRef))
{
log.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
}
else
{
log.debug("\tPermission test on non-existing node " + testNodeRef);
}
return accessAbstainOrDeny;
}
if((hasMethodEntry == null) || (hasMethodEntry.booleanValue()))
{
return AccessDecisionVoter.ACCESS_GRANTED;
}
else
{
return AccessDecisionVoter.ACCESS_DENIED;
}
}
}
else
{
throw new ACLEntryVoterException("The specified parameter is not a NodeRef or ChildAssociationRef");
Object testObject = getArgument(invocation, cad.parameter[0]);
//If the execution reaches here, then testNodeRef is always null
testNodeRef = getNodeRef(testObject, nodeService);
}
}
else if (cad.typeString.equals(ACL_ITEM))
@@ -584,44 +578,10 @@ public class ACLEntryVoter implements AccessDecisionVoter, InitializingBean
}
}
if (testNodeRef != null)
Integer accessAbstainOrDeny = shouldAbstainOrDeny(cad.required, testNodeRef, abstainForClassQNames, nodeService, permissionService);
if (accessAbstainOrDeny != null)
{
// now we know the node - we can abstain for certain types and aspects (eg. RM)
if(abstainForClassQNames.size() > 0)
{
// check node exists
if (nodeService.exists(testNodeRef))
{
QName typeQName = nodeService.getType(testNodeRef);
if(abstainForClassQNames.contains(typeQName))
{
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
Set<QName> aspectQNames = nodeService.getAspects(testNodeRef);
for(QName abstain : abstainForClassQNames)
{
if(aspectQNames.contains(abstain))
{
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
}
}
}
if (log.isDebugEnabled())
{
log.debug("\t\tNode ref is not null");
}
if (permissionService.hasPermission(testNodeRef, cad.required.toString()) == AccessStatus.DENIED)
{
if (log.isDebugEnabled())
{
log.debug("\t\tPermission is denied");
Thread.dumpStack();
}
return AccessDecisionVoter.ACCESS_DENIED;
}
return accessAbstainOrDeny;
}
}

View File

@@ -0,0 +1,175 @@
/*
* #%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.security.permissions.impl.acegi;
import java.util.Set;
import net.sf.acegisecurity.vote.AccessDecisionVoter;
import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility methods extracted from AclEntryVoter
*
* @author Lev Belava
*/
final class ACLEntryVoterUtils
{
private static final Logger LOG = LoggerFactory.getLogger(ACLEntryVoterUtils.class);
private ACLEntryVoterUtils()
{
}
/**
* Gets NodeRef for testObject based on inferred type
*
* @param testObject Tested object to work on
* @param nodeService Node service to perform checks on refs
* @return NodeRef for testObject or null if (testObject is null or StoreRef from testObject does not exist in the provided NodeService)
* @throws ACLEntryVoterException if testObject is not null and not one of a NodeRef or ChildAssociationRef types
*/
static NodeRef getNodeRef(Object testObject, NodeService nodeService)
{
if (testObject == null)
{
return null;
}
if (StoreRef.class.isAssignableFrom(testObject.getClass()))
{
LOG.debug("Permission test against the store - using permissions on the root node");
StoreRef storeRef = (StoreRef) testObject;
if (nodeService.exists(storeRef))
{
return nodeService.getRootNode(storeRef);
}
else
{
LOG.debug("StoreRef does not exist");
return null;
}
}
if (NodeRef.class.isAssignableFrom(testObject.getClass()))
{
NodeRef result = (NodeRef) testObject;
if (LOG.isDebugEnabled())
{
if (nodeService.exists(result))
{
LOG.debug("Permission test on node {}", nodeService.getPath(result));
}
else
{
LOG.debug("Permission test on non-existing node {}", result);
}
}
return result;
}
if (ChildAssociationRef.class.isAssignableFrom(testObject.getClass()))
{
ChildAssociationRef testChildRef = (ChildAssociationRef) testObject;
NodeRef result = testChildRef.getChildRef();
if (LOG.isDebugEnabled())
{
if (nodeService.exists(result))
{
LOG.debug("Permission test on node {}", nodeService.getPath(result));
}
else
{
LOG.debug("Permission test on non-existing node {}", result);
}
}
return result;
}
throw new ACLEntryVoterException("The specified parameter is not a NodeRef or ChildAssociationRef");
}
/**
* Checks if tested NodeRef instance is abstained or denied based on set of QNames to abstain and
*
* @param requiredPermissionReference Required permissions
* @param testNodeRef NodeRef to be verified
* @param abstainForClassQNames Set of QNames to abstain
* @param nodeService Node service to perform checks on tested NodeRef
* @param permissionService Permission service to check for required permissions
* @return null if testNodeRef is not abstained or denied, otherwise returns appropriate status.
*/
static Integer shouldAbstainOrDeny(SimplePermissionReference requiredPermissionReference, NodeRef testNodeRef, Set<QName> abstainForClassQNames,
NodeService nodeService, PermissionService permissionService)
{
if (testNodeRef == null)
{
return null;
}
LOG.debug("Node ref is not null");
if (abstainForClassQNames.size() > 0 && nodeService.exists(testNodeRef))
{
if (abstainForClassQNames.contains(nodeService.getType(testNodeRef)))
{
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
Set<QName> testNodeRefAspects = nodeService.getAspects(testNodeRef);
for (QName abstain : abstainForClassQNames)
{
if (testNodeRefAspects.contains(abstain))
{
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
}
}
if (AccessStatus.DENIED == permissionService.hasPermission(testNodeRef, requiredPermissionReference.toString()))
{
if (LOG.isDebugEnabled())
{
LOG.debug("Permission is denied");
Thread.dumpStack();
}
return AccessDecisionVoter.ACCESS_DENIED;
}
return null;
}
}

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.security.person;
import java.util.ArrayList;
@@ -320,8 +320,8 @@ public class HomeFolderProviderSynchronizer extends AbstractLifecycleBean
threadCount, peoplePerTransaction,
null,
batchLogger, 100);
processor.process(worker, true);
if (processor.getTotalErrors() > 0)
processor.processLong(worker, true);
if (processor.getTotalErrorsLong() > 0)
{
logger.info(" -- Give up after error --");
break;
@@ -874,6 +874,12 @@ public class HomeFolderProviderSynchronizer extends AbstractLifecycleBean
return size;
}
@Override
public synchronized long getTotalEstimatedWorkSizeLong()
{
return size;
}
@Override
public synchronized Collection<NodeRef> getNextWork()
{

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.tools;
import java.io.BufferedReader;
@@ -59,13 +59,13 @@ import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.VmShutdownListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Rename user tool. This tool provides minimal support for renaming users.
* See {@link #displayHelp} message for restrictions.
* <pre>
* Usage: renameUser -user username [options] oldUsername newUsername");
* renameUser -user username [options] -file filename");
/**
* Rename user tool. This tool provides minimal support for renaming users.
* See {@link #displayHelp} message for restrictions.
* <pre>
* Usage: renameUser -user username [options] oldUsername newUsername");
* renameUser -user username [options] -file filename");
* </pre>
* The csv file has a simple comma separated list, with
* a pair of usernames on each line. Comments and blank
@@ -549,6 +549,12 @@ public class RenameUser extends Tool
return size;
}
@Override
public synchronized long getTotalEstimatedWorkSizeLong()
{
return size;
}
@Override
public synchronized Collection<User> getNextWork()
{

View File

@@ -27,7 +27,7 @@
<!-- that inherit from that type. Permissions defined against aspects apply to all -->
<!-- objects or only objects that have the aspect applied. For example, the permission -->
<!-- to lock an object could apply to any object but the permission to unlock an -->
<!-- object woujld only apply to objects that have the lockable aspect. -->
<!-- object would only apply to objects that have the lockable aspect. -->
<!-- -->
<!-- =============================================== -->
@@ -42,7 +42,7 @@
<!-- -->
<!-- Permission groups are convenient groups of permissions. They may be used in -->
<!-- thier own right or as the effective set of permissions. If an authority has -->
<!-- their own right or as the effective set of permissions. If an authority has -->
<!-- all the permissions that make up a permission group they also have that -->
<!-- permission group even though it has not been explicitly granted. -->
<!-- -->
@@ -153,7 +153,7 @@
<!-- The permission to delete a node -->
<!-- -->
<!-- A node can only be deleted if there is delete permission on the node, if the -->
<!-- node is accesible via its parent, and if the node can be deleted from its -->
<!-- node is accessible via its parent, and if the node can be deleted from its -->
<!-- parent. Currently, there is no check that all the children can be deleted. -->
<!-- This check can be added but requires more work so the UI is not checking this -->
<!-- permission just to show the delete icon. -->
@@ -229,7 +229,7 @@
-->
</permission>
<!-- The permission to delte associations between nodes (not children) -->
<!-- The permission to delete associations between nodes (not children) -->
<permission name="_DeleteAssociations" expose="false" >
<grantedToGroup permissionGroup="DeleteAssociations" />
@@ -456,7 +456,7 @@
<!-- They can not be denied by the permissions set on any node. -->
<!-- -->
<!-- Admin can do anything to any ndoe -->
<!-- Admin can do anything to any node -->
<globalPermission permission="FullControl" authority="ROLE_ADMINISTRATOR"/>
<!-- For now, owners can always see, find and manipulate their stuff -->
@@ -468,7 +468,7 @@
<!-- Check in is granted to the lock owner -->
<globalPermission permission="CheckIn" authority="ROLE_LOCK_OWNER"/>
<!-- Cancel check out is granted to the locak owner -->
<!-- Cancel check out is granted to the lock owner -->
<globalPermission permission="CancelCheckOut" authority="ROLE_LOCK_OWNER"/>
</permissions>

View File

@@ -58,5 +58,8 @@
<value>path</value>
</property>
</bean>
<bean id ="repoHealthChecker" class="org.alfresco.repo.admin.RepoHealthChecker">
<constructor-arg index="0" ref="dataSourceCheck"/>
</bean>
</beans>

View File

@@ -3,7 +3,7 @@
repository.name=Main Repository
# Schema number
version.schema=15002
version.schema=16000
# Directory configuration
@@ -1308,3 +1308,6 @@ system.tempFileCleaner.maxTimeToRun=
# Property to long running migration to remove alf_server in v7+ patch.db-V7.1.0-remove-alf_server-table
system.remove-alf_server-table-from-db.ignored=true
# When using JSONP, allows unsecure usage of "callback" functions. Disabled by default for security reasons
allow.unsecure.callback.jsonp=false

View File

@@ -209,6 +209,7 @@ import org.junit.runners.Suite;
org.alfresco.repo.security.authentication.AuthorizationTest.class,
org.alfresco.repo.security.permissions.PermissionCheckedCollectionTest.class,
org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSetTest.class,
org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtilsTest.class,
org.alfresco.repo.security.authentication.ChainingAuthenticationServiceTest.class,
org.alfresco.repo.security.authentication.NameBasedUserNameGeneratorTest.class,
org.alfresco.repo.version.common.VersionImplTest.class,

View File

@@ -83,6 +83,7 @@ public class ContentServiceImplUnitTest
openMocks(this);
when(mockNodeService.getProperty(NODE_REF, ContentModel.PROP_CONTENT)).thenReturn(mockContentData);
when(mockContentData.getContentUrl()).thenReturn("someContentUrl");
when(mockContentData.getMimetype()).thenReturn("someMimetype");
when(mockNodeService.getProperty(NODE_REF, ContentModel.PROP_NAME)).thenReturn("someFilename");
}
@@ -133,7 +134,7 @@ public class ContentServiceImplUnitTest
DirectAccessUrl directAccessUrl = contentService.requestContentDirectUrl(NODE_REF, true, 20L);
assertNull(directAccessUrl);
verify(mockContentStore, never()).requestContentDirectUrl(anyString(), eq(true), anyString(), anyLong());
verify(mockContentStore, never()).requestContentDirectUrl(anyString(), eq(true), anyString(), anyString(), anyLong());
}
@Test
@@ -144,7 +145,7 @@ public class ContentServiceImplUnitTest
DirectAccessUrl directAccessUrl = contentService.requestContentDirectUrl(NODE_REF, true, 20L);
assertNull(directAccessUrl);
verify(mockContentStore, times(1)).requestContentDirectUrl(anyString(), eq(true), anyString(), anyLong());
verify(mockContentStore, times(1)).requestContentDirectUrl(anyString(), eq(true), anyString(), anyString(), anyLong());
}
/* Helper method to set system-wide direct access url configuration settings */

View File

@@ -505,8 +505,8 @@ public class CachingContentStoreTest
{
try
{
when(backingStore.requestContentDirectUrl(anyString(), eq(true), anyString(), anyLong())).thenThrow(new UnsupportedOperationException());
cachingStore.requestContentDirectUrl("url", true,"someFile", 30L);
when(backingStore.requestContentDirectUrl(anyString(), eq(true), anyString(), anyString(), anyLong())).thenThrow(new UnsupportedOperationException());
cachingStore.requestContentDirectUrl("url", true,"someFile", "someMimetype", 30L);
fail();
}
catch (UnsupportedOperationException e)
@@ -518,7 +518,7 @@ public class CachingContentStoreTest
@Test
public void getRequestContentDirectUrl()
{
when(backingStore.requestContentDirectUrl(anyString(), eq(true), anyString(), anyLong())).thenReturn(new DirectAccessUrl());
cachingStore.requestContentDirectUrl("url", true,"someFile", 30L);
when(backingStore.requestContentDirectUrl(anyString(), eq(true), anyString(), anyString(), anyLong())).thenReturn(new DirectAccessUrl());
cachingStore.requestContentDirectUrl("url", true,"someFile", "someMimeType", 30L);
}
}

View File

@@ -227,14 +227,14 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
UnsupportedContentUrlException unsupportedContentUrlExc = new UnsupportedContentUrlException(aggStore, "");
// By default it is unsupported
DirectAccessUrl directAccessUrl = aggStore.requestContentDirectUrl("url", true, "anyfilename", 30L);
DirectAccessUrl directAccessUrl = aggStore.requestContentDirectUrl("url", true, "anyfilename", "anyMimetype", 30L);
assertNull(directAccessUrl);
// Direct access not supported
try
{
when(primaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedExc);
when(secondaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedExc);
when(primaryStoreMock.requestContentDirectUrl(any(), any(), any(), any(), any())).thenThrow(unsupportedExc);
when(secondaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any(), any())).thenThrow(unsupportedExc);
aggStore.requestContentDirectUrl(eq("urlDANotSupported"), true, "anyfilename", 30L);
fail();
}
@@ -245,9 +245,9 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
try
{
when(primaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
when(secondaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedExc);
aggStore.requestContentDirectUrl("urlDANotSupported", true, "anyfilename", 30L);
when(primaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
when(secondaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any(), any())).thenThrow(unsupportedExc);
aggStore.requestContentDirectUrl("urlDANotSupported", true, "anyfilename", "anyMimetype", 30L);
fail();
}
catch (UnsupportedOperationException e)
@@ -257,9 +257,9 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
try
{
when(primaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedExc);
when(secondaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
aggStore.requestContentDirectUrl("urlDANotSupported", true, "anyfilename", 30L);
when(primaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any(), any())).thenThrow(unsupportedExc);
when(secondaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
aggStore.requestContentDirectUrl("urlDANotSupported", true, "anyfilename", "anyMimetype", 30L);
fail();
}
catch (UnsupportedOperationException e)
@@ -270,9 +270,9 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
// Content url not supported
try
{
when(primaryStoreMock.requestContentDirectUrl(eq("urlNotSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
when(secondaryStoreMock.requestContentDirectUrl(eq("urlNotSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
aggStore.requestContentDirectUrl("urlNotSupported", true, "anyfilename", 30L);
when(primaryStoreMock.requestContentDirectUrl(eq("urlNotSupported"), any(), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
when(secondaryStoreMock.requestContentDirectUrl(eq("urlNotSupported"), any(), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
aggStore.requestContentDirectUrl("urlNotSupported", true, "anyfilename", "anyMimetype", 30L);
fail();
}
catch (UnsupportedContentUrlException e)
@@ -280,31 +280,31 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
// Expected
}
when(primaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
when(secondaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any())).thenThrow(unsupportedExc);
directAccessUrl = aggStore.requestContentDirectUrl("urlPriSupported", true, "anyfilename", 30L);
when(primaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any(), any())).thenReturn(new DirectAccessUrl());
when(secondaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any(), any())).thenThrow(unsupportedExc);
directAccessUrl = aggStore.requestContentDirectUrl("urlPriSupported", true, "anyfilename", "anyMimetype", 30L);
assertNotNull(directAccessUrl);
when(primaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
when(secondaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
directAccessUrl = aggStore.requestContentDirectUrl("urlPriSupported", true, "anyfilename", 30L);
when(primaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any(), any())).thenReturn(new DirectAccessUrl());
when(secondaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
directAccessUrl = aggStore.requestContentDirectUrl("urlPriSupported", true, "anyfilename", "anyMimetype", 30L);
assertNotNull(directAccessUrl);
when(primaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any())).thenThrow(unsupportedExc);
when(secondaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
directAccessUrl = aggStore.requestContentDirectUrl("urlSecSupported", true, "anyfilename", 30L);
when(primaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any(), any())).thenThrow(unsupportedExc);
when(secondaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any(), any())).thenReturn(new DirectAccessUrl());
directAccessUrl = aggStore.requestContentDirectUrl("urlSecSupported", true, "anyfilename", "anyMimetype", 30L);
assertNotNull(directAccessUrl);
when(primaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
when(secondaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
directAccessUrl = aggStore.requestContentDirectUrl("urlSecSupported", true, "anyfilename", 30L);
when(primaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
when(secondaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any(), any())).thenReturn(new DirectAccessUrl());
directAccessUrl = aggStore.requestContentDirectUrl("urlSecSupported", true, "anyfilename", "anyMimetype", 30L);
assertNotNull(directAccessUrl);
when(primaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
when(secondaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
directAccessUrl = aggStore.requestContentDirectUrl("urlPriSupported", true, "anyfilename", 30L);
when(primaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any(), any())).thenReturn(new DirectAccessUrl());
when(secondaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any(), any())).thenReturn(new DirectAccessUrl());
directAccessUrl = aggStore.requestContentDirectUrl("urlPriSupported", true, "anyfilename", "anyMimetype", 30L);
assertNotNull(directAccessUrl);
directAccessUrl = aggStore.requestContentDirectUrl("urlSecSupported", true, "anyfilename", 30L);
directAccessUrl = aggStore.requestContentDirectUrl("urlSecSupported", true, "anyfilename", "anyMimetype", 30L);
assertNotNull(directAccessUrl);
}
}

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
@@ -96,6 +96,8 @@ public abstract class AbstractPermissionTest extends TestCase
protected NodeRef systemNodeRef;
protected NodeRef abstainedNode;
protected AuthenticationComponent authenticationComponent;
protected ModelDAO permissionModelDAO;
@@ -186,6 +188,8 @@ public abstract class AbstractPermissionTest extends TestCase
props = createPersonProperties(USER2_LEMUR);
nodeService.createNode(typesNodeRef, children, ContentModel.TYPE_PERSON, container, props).getChildRef();
abstainedNode= nodeService.createNode(rootNodeRef, ContentModel.ASSOC_FAILED_THUMBNAIL, system, ContentModel.TYPE_FAILED_THUMBNAIL).getChildRef();
// create an authentication object e.g. the user
if(authenticationDAO.userExists(USER1_ANDY))
{

View File

@@ -0,0 +1,181 @@
/*
* #%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.security.permissions.impl.acegi;
import static org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtils.getNodeRef;
import static org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtils.shouldAbstainOrDeny;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.when;
import java.util.Collections;
import java.util.Set;
import net.sf.acegisecurity.vote.AccessDecisionVoter;
import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ACLEntryVoterUtilsTest
{
private final NodeRef testNodeRef = new NodeRef("workspace://testNodeRef/testNodeRef");
private final NodeRef rootNodeRef = new NodeRef("workspace://rootNodeRef/rootNodeRef");
private final NodeRef refNodeForTestObject = new NodeRef("workspace://refNodeForTestObject/refNodeForTestObject");
private final NodeRef childRefNode = new NodeRef("workspace://childRefNode/childRefNode");
private final StoreRef testStoreNodeRef = new StoreRef("system://testStoreRefMock/testStoreRefMock");
private final SimplePermissionReference simplePermissionReference = SimplePermissionReference.getPermissionReference(QName.createQName("uri", "local"), "Write");
private final QName qNameToAbstain1 = QName.createQName("{test}testnode1");
private final QName qNameToAbstain2 = QName.createQName("{test}testnode2");
private final QName qNameToAbstain3 = QName.createQName("{test}testnode3");
private final QName qNameNotFromTheAbstainSet = QName.createQName("{test}testnodeAbstain");
private final Set<QName> qNamesToAbstain = Set.of(qNameToAbstain1, qNameToAbstain2, qNameToAbstain3);
@Mock
private PermissionService permissionServiceMock;
@Mock
private NodeService nodeServiceMock;
@Mock
private ChildAssociationRef childAssocRefMock;
@Before
public void setUp()
{
when(nodeServiceMock.exists(testStoreNodeRef)).thenReturn(Boolean.TRUE);
when(nodeServiceMock.exists(testNodeRef)).thenReturn(Boolean.TRUE);
when(nodeServiceMock.getRootNode(testStoreNodeRef)).thenReturn(rootNodeRef);
when(nodeServiceMock.getType(testNodeRef)).thenReturn(qNameNotFromTheAbstainSet);
when(nodeServiceMock.getAspects(testNodeRef)).thenReturn(Set.of(qNameNotFromTheAbstainSet));
when(permissionServiceMock.hasPermission(eq(testNodeRef), nullable(String.class))).thenReturn(AccessStatus.DENIED);
}
@Test
public void returnsAccessDeniedFromPermissionService()
{
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
is(AccessDecisionVoter.ACCESS_DENIED));
}
@Test
public void returnsNullOnNullTestObject()
{
assertThat(getNodeRef(null, nodeServiceMock), is(nullValue()));
}
@Test(expected = ACLEntryVoterException.class)
public void throwsExceptionWhenParameterIsNotNodeRefOrChildAssociationRef()
{
getNodeRef("TEST", nodeServiceMock);
}
@Test
public void returnsGivenTestNodeRefWhenStoreRefDoesNotExist()
{
when(nodeServiceMock.exists(testStoreNodeRef)).thenReturn(Boolean.FALSE);
assertThat(getNodeRef(testStoreNodeRef, nodeServiceMock), is(nullValue()));
}
@Test
public void returnsRootNode()
{
assertThat(getNodeRef(testStoreNodeRef, nodeServiceMock), is(rootNodeRef));
}
@Test
public void returnsNodeRefFromTestObject()
{
assertThat(getNodeRef(refNodeForTestObject, nodeServiceMock), is(refNodeForTestObject));
}
@Test
public void returnsChildRefFromChildAssocRef()
{
when(childAssocRefMock.getChildRef()).thenReturn(childRefNode);
assertThat(getNodeRef(childAssocRefMock, nodeServiceMock), is(childRefNode));
}
@Test
public void returnsNullOnNullTestNodeRef()
{
assertThat(shouldAbstainOrDeny(simplePermissionReference, null, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
is(nullValue()));
}
@Test
public void returnsNullOnAbstainClassQnamesIsEmptyAndThereAreNoDeniedPermissions()
{
when(permissionServiceMock.hasPermission(eq(testNodeRef), nullable(String.class))).thenReturn(AccessStatus.ALLOWED);
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, Collections.emptySet(), nodeServiceMock, permissionServiceMock),
is(nullValue()));
}
@Test
public void returnsNullOnTestNodeRefDoesNotExistAndThereAreNoDeniedPermissions()
{
when(nodeServiceMock.exists(testNodeRef)).thenReturn(Boolean.FALSE);
when(permissionServiceMock.hasPermission(eq(testNodeRef), nullable(String.class))).thenReturn(AccessStatus.ALLOWED);
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
is(nullValue()));
}
@Test
public void returnsNullOnNodeTypeAndNodeAspectsAreNotInSetToAbstainAndThereAreNoDeniedPermissions()
{
when(permissionServiceMock.hasPermission(eq(testNodeRef), nullable(String.class))).thenReturn(AccessStatus.ALLOWED);
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
is(nullValue()));
}
@Test
public void returnsAbstainWhenNodeRefTypeIsInSetToAbstain()
{
when(nodeServiceMock.getType(testNodeRef)).thenReturn(qNameToAbstain2);
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
is(AccessDecisionVoter.ACCESS_ABSTAIN));
}
@Test
public void returnsAbstainWhenAtLeastOneAspectIsInSetToAbstain()
{
when(nodeServiceMock.getAspects(testNodeRef)).thenReturn(Set.of(qNameNotFromTheAbstainSet, qNameToAbstain3));
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
is(AccessDecisionVoter.ACCESS_ABSTAIN));
}
}