diff --git a/.travis.yml b/.travis.yml index 72168f82cf..52c3392fb6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,7 @@ branches: only: - master - /release\/.*/ - - feature/REPO-5266_dup_tas_code + - merge_to_7_0_0_A3 env: global: @@ -83,14 +83,14 @@ jobs: install: - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.7 postgres -c 'max_connections=300' - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8 - - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.2 + - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.4 script: travis_wait 20 mvn test -B -pl repository -Dtest=AppContext03TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco -Dalfresco-pdf-renderer.url=http://localhost:8090/ -Djodconverter.url=http://localhost:8090/ -Dimg.url=http://localhost:8090/ -Dtika.url=http://localhost:8090/ -Dtransform.misc.url=http://localhost:8090/ - name: "Repository - AppContext04TestSuite" install: - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.7 postgres -c 'max_connections=300' - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8 - - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.2 + - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.4 script: travis_wait 20 mvn test -B -pl repository -Dtest=AppContext04TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco - name: "Repository - AppContext05TestSuite" @@ -109,7 +109,7 @@ jobs: install: - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.7 postgres -c 'max_connections=300' - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8 - - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.2 + - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.4 script: travis_wait 20 mvn test -B -pl repository -Dtest=AppContext06TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco -Dalfresco-pdf-renderer.url=http://localhost:8090/ -Djodconverter.url=http://localhost:8090/ -Dimg.url=http://localhost:8090/ -Dtika.url=http://localhost:8090/ -Dtransform.misc.url=http://localhost:8090/ - name: "Repository - AppContextExtraTestSuite" @@ -122,32 +122,32 @@ jobs: install: - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.7 postgres -c 'max_connections=300' - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8 - - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.2 + - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.4 script: travis_wait 20 mvn test -B -pl repository -Dtest=MiscContextTestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco -Dalfresco-pdf-renderer.url=http://localhost:8090/ -Djodconverter.url=http://localhost:8090/ -Dimg.url=http://localhost:8090/ -Dtika.url=http://localhost:8090/ -Dtransform.misc.url=http://localhost:8090/ - name: "Repository - MySQL tests" - if: commit_message !~ /\[skip_db\]/ + if: commit_message !~ /\[skip db\]/ install: - docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=alfresco -e MYSQL_USER=alfresco -e MYSQL_DATABASE=alfresco -e MYSQL_PASSWORD=alfresco mysql:5.7.23 --transaction-isolation='READ-COMMITTED' - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8 script: travis_wait 20 mvn test -B -pl repository -Dtest=AllDBTestsTestSuite -Ddb.driver=com.mysql.jdbc.Driver -Ddb.name=alfresco -Ddb.url=jdbc:mysql://localhost:3307/alfresco -Ddb.username=alfresco -Ddb.password=alfresco - name: "Repository - PostgreSQL 10 tests" - if: commit_message !~ /\[skip_db\]/ + if: commit_message !~ /\[skip db\]/ install: - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:10.9 postgres -c 'max_connections=300' - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8 script: travis_wait 20 mvn test -B -pl repository -Dtest=AllDBTestsTestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco - name: "Repository - PostgreSQL 11 tests" - if: commit_message !~ /\[skip_db\]/ + if: commit_message !~ /\[skip db\]/ install: - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.7 postgres -c 'max_connections=300' - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8 script: travis_wait 20 mvn test -B -pl repository -Dtest=AllDBTestsTestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco - name: "Repository - MariaDB tests" - if: commit_message !~ /\[skip_db\]/ + if: commit_message !~ /\[skip db\]/ install: - docker run -d -p 3307:3306 --name mariadb -e MYSQL_ROOT_PASSWORD=alfresco -e MYSQL_USER=alfresco -e MYSQL_DATABASE=alfresco -e MYSQL_PASSWORD=alfresco mariadb:10.2.18 --transaction-isolation=READ-COMMITTED --max-connections=300 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8 @@ -185,7 +185,7 @@ jobs: - name: "REST API TAS tests part1" jdk: openjdk11 - if: commit_message ~ /\[tas\]/ + if: commit_message =~ /\[tas\]/ install: - ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml - ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco" @@ -194,7 +194,7 @@ jobs: - name: "REST API TAS tests part2" jdk: openjdk11 - if: commit_message ~ /\[tas\]/ + if: commit_message =~ /\[tas\]/ install: - ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml - ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco" @@ -203,7 +203,7 @@ jobs: - name: "REST API TAS tests part3" jdk: openjdk11 - if: commit_message ~ /\[tas\]/ + if: commit_message =~ /\[tas\]/ install: - ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml - ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco" @@ -212,7 +212,7 @@ jobs: - name: "CMIS TAS tests" jdk: openjdk11 - if: commit_message ~ /\[tas\]/ + if: commit_message =~ /\[tas\]/ install: - ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml - ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco" @@ -221,7 +221,7 @@ jobs: - name: "Email TAS tests" jdk: openjdk11 - if: commit_message ~ /\[tas\]/ + if: commit_message =~ /\[tas\]/ install: - ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal.yml - ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco" @@ -230,7 +230,7 @@ jobs: - name: "WebDAV TAS tests" jdk: openjdk11 - if: commit_message ~ /\[tas\]/ + if: commit_message =~ /\[tas\]/ install: - ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal.yml - ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco" @@ -239,7 +239,7 @@ jobs: - name: "Integration TAS tests" jdk: openjdk11 - if: commit_message ~ /\[tas\]/ + if: commit_message =~ /\[tas\]/ install: - ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal.yml - ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco" diff --git a/data-model/pom.xml b/data-model/pom.xml index abcab48ca1..3a7dbce8a2 100644 --- a/data-model/pom.xml +++ b/data-model/pom.xml @@ -159,8 +159,8 @@ com.fasterxml.jackson.core - jackson-annotations - 2.11.1 + jackson-annotations + ${dependency.jackson.version} org.antlr diff --git a/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/QueryConstants.java b/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/QueryConstants.java index 168dc9c7e2..ead924c330 100644 --- a/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/QueryConstants.java +++ b/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/QueryConstants.java @@ -187,7 +187,11 @@ public interface QueryConstants public static final String FIELD_SOLR_UNIT_OF_TIME_HOUR_SUFFIX = "_unit_of_time_hour"; - public static final String FIELD_SOLR_UNIT_OF_TIME_DAY_SUFFIX = "_unit_of_time_day"; + public static final String FIELD_SOLR_UNIT_OF_TIME_DAY_SUFFIX = "_unit_of_time_day_of_month"; + + public static final String FIELD_SOLR_UNIT_OF_TIME_DAY_OF_WEEK_SUFFIX = "_unit_of_time_day_of_week"; + + public static final String FIELD_SOLR_UNIT_OF_TIME_DAY_OF_YEAR_SUFFIX = "_unit_of_time_day_of_year"; public static final String FIELD_SOLR_UNIT_OF_TIME_MONTH_SUFFIX = "_unit_of_time_month"; diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/QueryParserUtils.java b/data-model/src/main/java/org/alfresco/repo/search/impl/QueryParserUtils.java index 31b225b774..098bd16cf1 100644 --- a/data-model/src/main/java/org/alfresco/repo/search/impl/QueryParserUtils.java +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/QueryParserUtils.java @@ -404,6 +404,16 @@ public class QueryParserUtils implements QueryConstants propertyFieldName = field.substring(field.startsWith("@") ? 1 : 0, field.length() - FIELD_SOLR_UNIT_OF_TIME_DAY_SUFFIX.length()); ending = FIELD_SOLR_UNIT_OF_TIME_DAY_SUFFIX; } + else if (field.endsWith(FIELD_SOLR_UNIT_OF_TIME_DAY_OF_WEEK_SUFFIX)) + { + propertyFieldName = field.substring(field.startsWith("@") ? 1 : 0, field.length() - FIELD_SOLR_UNIT_OF_TIME_DAY_OF_WEEK_SUFFIX.length()); + ending = FIELD_SOLR_UNIT_OF_TIME_DAY_OF_WEEK_SUFFIX; + } + else if (field.endsWith(FIELD_SOLR_UNIT_OF_TIME_DAY_OF_YEAR_SUFFIX)) + { + propertyFieldName = field.substring(field.startsWith("@") ? 1 : 0, field.length() - FIELD_SOLR_UNIT_OF_TIME_DAY_OF_YEAR_SUFFIX.length()); + ending = FIELD_SOLR_UNIT_OF_TIME_DAY_OF_YEAR_SUFFIX; + } else if (field.endsWith(FIELD_SOLR_UNIT_OF_TIME_MONTH_SUFFIX)) { propertyFieldName = field.substring(field.startsWith("@") ? 1 : 0, field.length() - FIELD_SOLR_UNIT_OF_TIME_MONTH_SUFFIX.length()); diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java index 376dd6210f..583bf2a110 100644 --- a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java @@ -552,6 +552,34 @@ public class AlfrescoFunctionEvaluationContext implements FunctionEvaluationCont return propertyField; } } + else if(field.endsWith(QueryConstants.FIELD_SOLR_UNIT_OF_TIME_DAY_OF_WEEK_SUFFIX)) + { + QName propertyField = QName.createQName(field.substring(0, field.length() - QueryConstants.FIELD_SOLR_UNIT_OF_TIME_DAY_OF_WEEK_SUFFIX.length())); + PropertyDefinition propertyDef = dictionaryService.getProperty(propertyField); + if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.DATE) && + !propertyDef.getDataType().getName().equals(DataTypeDefinition.DATETIME)) + { + throw new FTSQueryException(QueryConstants.FIELD_SOLR_UNIT_OF_TIME_DAY_OF_WEEK_SUFFIX+" only supported on date and datetime properties"); + } + else + { + return propertyField; + } + } + else if(field.endsWith(QueryConstants.FIELD_SOLR_UNIT_OF_TIME_DAY_OF_YEAR_SUFFIX)) + { + QName propertyField = QName.createQName(field.substring(0, field.length() - QueryConstants.FIELD_SOLR_UNIT_OF_TIME_DAY_OF_YEAR_SUFFIX.length())); + PropertyDefinition propertyDef = dictionaryService.getProperty(propertyField); + if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.DATE) && + !propertyDef.getDataType().getName().equals(DataTypeDefinition.DATETIME)) + { + throw new FTSQueryException(QueryConstants.FIELD_SOLR_UNIT_OF_TIME_DAY_OF_YEAR_SUFFIX+" only supported on date and datetime properties"); + } + else + { + return propertyField; + } + } else if(field.endsWith(QueryConstants.FIELD_SOLR_UNIT_OF_TIME_MONTH_SUFFIX)) { QName propertyField = QName.createQName(field.substring(0, field.length() - QueryConstants.FIELD_SOLR_UNIT_OF_TIME_MONTH_SUFFIX.length())); diff --git a/packaging/docker-alfresco/Dockerfile b/packaging/docker-alfresco/Dockerfile index 6d0e9fb433..31f34aec89 100644 --- a/packaging/docker-alfresco/Dockerfile +++ b/packaging/docker-alfresco/Dockerfile @@ -1,6 +1,6 @@ -# Fetch image based on Tomcat 8.5.43 and Java 11 +# Fetch image based on Tomcat 8.5 and Java 11 # More infos about this image: https://github.com/Alfresco/alfresco-docker-base-tomcat -FROM alfresco/alfresco-base-tomcat:8.5.43-java-11-openjdk-centos-7 +FROM alfresco/alfresco-base-tomcat:8.5.51-java-11-openjdk-centos-7 # Set default docker_context. Will / Can be overriden with maven. ARG resource_path=target diff --git a/packaging/l10n.properties b/packaging/l10n.properties deleted file mode 100644 index 96ee00fb2d..0000000000 --- a/packaging/l10n.properties +++ /dev/null @@ -1,8 +0,0 @@ -# Branch specific configuration file for localisation scripts -# here is no localization needed in the alfresco-community-repo-packaging project for now - -MESSAGE_SEARCH_PATH="" - - -EXCLUDED_FILES="" - diff --git a/packaging/tests/environment/.env b/packaging/tests/environment/.env index f13d730f80..389332f38b 100644 --- a/packaging/tests/environment/.env +++ b/packaging/tests/environment/.env @@ -1,4 +1,4 @@ -TRANSFORMERS_TAG=2.3.1 +TRANSFORMERS_TAG=2.3.4 SOLR6_TAG=1.4.2 POSTGRES_TAG=11.7 ACTIVEMQ_TAG=5.15.8 diff --git a/packaging/tests/environment/docker-compose-minimal+transforms.yml b/packaging/tests/environment/docker-compose-minimal+transforms.yml index b7a912e07b..30dfa8f706 100644 --- a/packaging/tests/environment/docker-compose-minimal+transforms.yml +++ b/packaging/tests/environment/docker-compose-minimal+transforms.yml @@ -29,20 +29,16 @@ services: -Dshare.host=localhost -Daos.baseUrlOverwrite=http://localhost:8082/alfresco/aos -Dmessaging.broker.url=\"failover:(tcp://activemq:61616)?timeout=3000&jms.useCompression=true\" - -DlocalTransform.core-aio.url=http://transform-core-aio:8090/ - -Dalfresco-pdf-renderer.url=http://transform-core-aio:8090/ -Djodconverter.url=http://transform-core-aio:8090/ -Dimg.url=http://transform-core-aio:8090/ -Dtika.url=http://transform-core-aio:8090/ -Dtransform.misc.url=http://transform-core-aio:8090/ - -Dimap.server.port=1143 -Dftp.port=1221 -Dcors.enabled=true -Dcors.allowed.origins=http://localhost:4200,http://localhost:8080 - -Dmetadata-keystore.password=mp6yc0UD9e -Dmetadata-keystore.aliases=metadata -Dmetadata-keystore.metadata.password=mp6yc0UD9e diff --git a/packaging/tests/environment/docker-compose-minimal.yml b/packaging/tests/environment/docker-compose-minimal.yml index 4d6c6e06ce..cb746e94b1 100644 --- a/packaging/tests/environment/docker-compose-minimal.yml +++ b/packaging/tests/environment/docker-compose-minimal.yml @@ -29,15 +29,12 @@ services: -Dshare.host=localhost -Daos.baseUrlOverwrite=http://localhost:8082/alfresco/aos -Dmessaging.broker.url=\"failover:(tcp://activemq:61616)?timeout=3000&jms.useCompression=true\" - -Dlocal.transform.service.enabled=false -Dlegacy.transform.service.enabled=false - -Dimap.server.port=1143 -Dftp.port=1221 -Dcors.enabled=true -Dcors.allowed.origins=http://localhost:4200,http://localhost:8080 - -Dmetadata-keystore.password=mp6yc0UD9e -Dmetadata-keystore.aliases=metadata -Dmetadata-keystore.metadata.password=mp6yc0UD9e diff --git a/packaging/tests/pom.xml b/packaging/tests/pom.xml index bcba4c1890..be71e9d7d1 100644 --- a/packaging/tests/pom.xml +++ b/packaging/tests/pom.xml @@ -20,15 +20,5 @@ 20170516 - - - - - - - - - - \ No newline at end of file diff --git a/packaging/tests/scripts/wait-for-alfresco-start.sh b/packaging/tests/scripts/wait-for-alfresco-start.sh index feb1edf501..8b6940c3c5 100755 --- a/packaging/tests/scripts/wait-for-alfresco-start.sh +++ b/packaging/tests/scripts/wait-for-alfresco-start.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash export ALFRESCO_URL=$1 +export EXTRA_WAIT_INTERVAL=$2 if [ -z "$ALFRESCO_URL" ] then @@ -24,6 +25,13 @@ if (("$COUNTER" < "$TIMEOUT")) ; then t1=$(date +%s) delta=$((($t1 - $t0)/60)) echo "Alfresco Started in $delta minutes" + + if [ -n "$EXTRA_WAIT_INTERVAL" ] + then + echo "Waiting an extra $EXTRA_WAIT_INTERVAL for all the containers to initialise..." + sleep $EXTRA_WAIT_INTERVAL + echo "Waited $EXTRA_WAIT_INTERVAL seconds" + fi else echo "Waited $COUNTER seconds" echo "Alfresco Could not start in time." diff --git a/pom.xml b/pom.xml index eeb4a09bb9..a3765779a1 100644 --- a/pom.xml +++ b/pom.xml @@ -44,40 +44,44 @@ 0.2 5.23.0 5.23.0 - 1.0.2.10 + 1.0.2.11 - 5.2.7.RELEASE + 5.2.8.RELEASE 3.5.2 4.4.0 - 2.11.1 + 2.11.2 2.10.1 3.3.7 1.0.0 2.0.20 - 8.5 + 8.8 1.66 - 3.4.4 + 3.4.6 20090211 1.4-DBCP330 28.2-jre 2.7 2.8.5 4.5.12 + 4.4.13 + 3.1-HTTPCLIENT-1265 2.12.0-alfresco-patched-20191004 3.2.0 1.7.30 + 0.11.6 + 2.3.3 3.2.0 1.3.1 42.2.14 8.0.21 - 2.6.1 + 2.6.2 3.0.21 3.3.0 1.1.4 - 1.46 + 1.47 1.13 1.8 1.6 @@ -264,12 +268,12 @@ org.apache.httpcomponents httpcore - 4.4.13 + ${dependency.httpcore.version} commons-httpclient commons-httpclient - 3.1-HTTPCLIENT-1265 + ${dependency.commons-httpclient.version} commons-logging @@ -315,7 +319,7 @@ com.sun.xml.bind jaxb-impl - 2.3.3 + ${dependency.jaxb.version} org.apache.httpcomponents diff --git a/remote-api/src/main/java/org/alfresco/rest/api/impl/GroupsImpl.java b/remote-api/src/main/java/org/alfresco/rest/api/impl/GroupsImpl.java index de7dcd7f15..784de7be2b 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/impl/GroupsImpl.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/GroupsImpl.java @@ -35,7 +35,6 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -74,6 +73,7 @@ import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.util.AlfrescoCollator; import org.alfresco.util.Pair; +import org.apache.commons.lang3.StringUtils; import org.springframework.extensions.surf.util.I18NUtil; /** @@ -84,7 +84,9 @@ import org.springframework.extensions.surf.util.I18NUtil; public class GroupsImpl implements Groups { private static final int MAX_ZONES = 1; + private static final int MAX_DISPLAY_NAMES = 1; private static final String DISPLAY_NAME = "displayName"; + private static final String ZONE = "zone"; private static final String AUTHORITY_NAME = "authorityName"; private static final String ERR_MSG_MODIFY_FIXED_AUTHORITY = "Trying to modify a fixed authority"; @@ -181,39 +183,20 @@ public class GroupsImpl implements Groups public CollectionWithPagingInfo getGroups(final Parameters parameters) { - final List includeParam = parameters.getInclude(); - Paging paging = parameters.getPaging(); // Retrieve sort column. This is limited for now to sort column due to // v0 api implementation. Should be improved in the future. Pair sortProp = getGroupsSortProp(parameters); - // Parse where clause properties. - Query q = parameters.getQuery(); - Boolean isRootParam = null; - String zoneFilter = null; - if (q != null) - { - GroupsQueryWalker propertyWalker = new GroupsQueryWalker(); - QueryHelper.walk(q, propertyWalker); - - isRootParam = propertyWalker.getIsRoot(); - List zonesParam = propertyWalker.getZones(); - if (zonesParam != null) - { - validateZonesParam(zonesParam); - zoneFilter = zonesParam.get(0); - } - } - + GroupsFilter groupsFilters = getGroupsFilterFromQueryParameters(parameters.getQuery()); final AuthorityType authorityType = AuthorityType.GROUP; final Set rootAuthorities = getAllRootAuthorities(authorityType); PagingResults pagingResult; try { - pagingResult = getAuthoritiesInfo(authorityType, isRootParam, zoneFilter, rootAuthorities, sortProp, paging); + pagingResult = getAuthoritiesInfo(authorityType, groupsFilters, rootAuthorities, sortProp, paging); } catch (UnknownAuthorityException e) { @@ -221,9 +204,15 @@ public class GroupsImpl implements Groups pagingResult = new EmptyPagingResults<>(); } - // Create response. - final List page = pagingResult.getPage(); + List groups = createGroupsResponse(pagingResult.getPage(), parameters.getInclude(), rootAuthorities); + int totalItems = pagingResult.getTotalResultCount().getFirst(); + + return CollectionWithPagingInfo.asPaged(paging, groups, pagingResult.hasMoreItems(), totalItems); + } + + private List createGroupsResponse(final List page, final List includeParam, final Set rootAuthorities) + { List groups = new AbstractList() { @Override @@ -239,27 +228,58 @@ public class GroupsImpl implements Groups return page.size(); } }; - - return CollectionWithPagingInfo.asPaged(paging, groups, pagingResult.hasMoreItems(), totalItems); + return groups; } - private void validateZonesParam(List zonesParam) + private GroupsFilter getGroupsFilterFromQueryParameters(Query queryParameters) { - if (zonesParam.size() > MAX_ZONES) + GroupsFilter.GroupsFilterBuilder groupsFilterBuilder = GroupsFilter.builder(); + + if (queryParameters != null) { - throw new IllegalArgumentException("A maximum of " + MAX_ZONES + " zones may be specified."); + GroupsQueryWalker propertyWalker = new GroupsQueryWalker(); + QueryHelper.walk(queryParameters, propertyWalker); + + groupsFilterBuilder + .withIsRoot( + propertyWalker.getIsRoot()) + .withZoneFilter( + getStringFilterFromList(propertyWalker.getZones(), ZONE, MAX_ZONES)) + .withDisplayNameFilter( + getStringFilterFromList(propertyWalker.getDisplayNames(), DISPLAY_NAME, MAX_DISPLAY_NAMES)); } - else if (zonesParam.isEmpty()) + return groupsFilterBuilder.build(); + } + + private String getStringFilterFromList(List listParam, String paramName, int maxItems) + { + String filter = null; + if (listParam != null) { - throw new IllegalArgumentException("Zones filter list cannot be empty."); + validateListParam(listParam, paramName, maxItems); + filter = listParam.get(0); } - // Validate each zone name - zonesParam.forEach(zone -> { - if (zone.isEmpty()) - { - throw new IllegalArgumentException("Zone name cannot be empty (i.e. '')"); - } - }); + return filter; + } + + private void validateListParam(List listParam, String paramName, int maxItems) + { + if (listParam.size() > maxItems) + { + throw new IllegalArgumentException("A maximum of " + maxItems + " " + paramName + "s may be specified."); + } + else if (listParam.isEmpty()) + { + throw new IllegalArgumentException(StringUtils.capitalize(paramName) + "s filter list cannot be empty."); + } + + listParam + .stream() + .filter(String::isEmpty) + .findAny() + .ifPresent(displayName -> { + throw new IllegalArgumentException(StringUtils.capitalize(paramName) + " cannot be empty (i.e. '')"); + }); } @Override @@ -290,7 +310,7 @@ public class GroupsImpl implements Groups List zonesParam = propertyWalker.getZones(); if (zonesParam != null) { - validateZonesParam(zonesParam); + validateListParam(zonesParam, ZONE, MAX_ZONES); zoneFilter = zonesParam.get(0); } } @@ -334,22 +354,26 @@ public class GroupsImpl implements Groups return CollectionWithPagingInfo.asPaged(paging, groups, pagingResult.hasMoreItems(), totalItems); } - private PagingResults getAuthoritiesInfo(AuthorityType authorityType, Boolean isRootParam, String zoneFilter, Set rootAuthorities, Pair sortProp, - Paging paging) + private PagingResults getAuthoritiesInfo(AuthorityType authorityType, GroupsFilter groupsFilter, Set rootAuthorities, + Pair sortProp, Paging paging) { + Boolean isRootParam = groupsFilter.getIsRoot(); + String zoneFilter = groupsFilter.getZoneFilter(); + String displayNameFilter = groupsFilter.getDisplayNameFilter(); PagingResults pagingResult; - if (isRootParam != null) + if (isRootParam != null || displayNameFilter != null) { List groupList; - if (isRootParam) + if (isRootParam != null && isRootParam) { // Limit the post processing work by using the already loaded // list of root authorities. List authorities = rootAuthorities.stream(). map(this::getAuthorityInfo). filter(auth -> zonePredicate(auth.getAuthorityName(), zoneFilter)). + filter(auth -> displayNamePredicate(auth.getAuthorityDisplayName(), displayNameFilter)). collect(Collectors.toList()); groupList = new ArrayList<>(rootAuthorities.size()); groupList.addAll(authorities); @@ -376,14 +400,11 @@ public class GroupsImpl implements Groups groupList = nonPagingResult.getPage(); if (groupList != null) { - for (Iterator i = groupList.iterator(); i.hasNext();) - { - AuthorityInfo authorityInfo = i.next(); - if (!isRootParam.equals(isRootAuthority(rootAuthorities, authorityInfo.getAuthorityName()))) - { - i.remove(); - } - } + groupList = groupList + .stream() + .filter(auth -> isRootPredicate(isRootParam, rootAuthorities, auth.getAuthorityName())) + .filter(auth -> displayNamePredicate(auth.getAuthorityDisplayName(), displayNameFilter)) + .collect(Collectors.toList()); } } @@ -463,6 +484,25 @@ public class GroupsImpl implements Groups return true; } + /** + * Checks to see if the named group authority should be included in results + * when filtered by displayName. + *

+ * If the requiredDisplayName parameter is null, then the filter will not be applied (returns true.) + *

+ * @param groupDisplayName + * @param requiredDisplayName + * @return true if result should be included. + */ + private boolean displayNamePredicate(String groupDisplayName, String requiredDisplayName) + { + if (requiredDisplayName != null) + { + return groupDisplayName != null && groupDisplayName.equalsIgnoreCase(requiredDisplayName); + } + return true; + } + private Set getAllRootAuthorities(AuthorityType authorityType) { Set authorities; @@ -1026,6 +1066,7 @@ public class GroupsImpl implements Groups private static class GroupsQueryWalker extends MapBasedQueryWalker { private List zones; + private List displayNames; public GroupsQueryWalker() { @@ -1045,6 +1086,10 @@ public class GroupsImpl implements Groups { zones = Arrays.asList(propertyValues); } + if (propertyName.equalsIgnoreCase(DISPLAY_NAME)) + { + displayNames = Arrays.asList(propertyValues); + } } /** @@ -1066,5 +1111,81 @@ public class GroupsImpl implements Groups { return getProperty(PARAM_IS_ROOT, WhereClauseParser.EQUALS, Boolean.class); } + + /** + * The list of displayName specified in the where clause. + * + * @return The displayNames list if specified, or null if not. + */ + public List getDisplayNames() + { + return displayNames; + } } } + +class GroupsFilter +{ + private Boolean isRoot; + private String zoneFilter; + private String displayNameFilter; + + private GroupsFilter() + { + } + + public static GroupsFilterBuilder builder() + { + return new GroupsFilterBuilder(); + } + + public Boolean getIsRoot() + { + return isRoot; + } + + public String getZoneFilter() + { + return zoneFilter; + } + + public String getDisplayNameFilter() + { + return displayNameFilter; + } + + public static class GroupsFilterBuilder + { + private Boolean isRoot; + private String zoneFilter; + private String displayNameFilter; + + public GroupsFilterBuilder withIsRoot(Boolean isRoot) + { + this.isRoot = isRoot; + return this; + } + + public GroupsFilterBuilder withZoneFilter(String zoneFilter) + { + this.zoneFilter = zoneFilter; + return this; + } + + public GroupsFilterBuilder withDisplayNameFilter(String displayNameFilter) + { + this.displayNameFilter = displayNameFilter; + return this; + } + + public GroupsFilter build() + { + GroupsFilter groupsFilter = new GroupsFilter(); + groupsFilter.isRoot = this.isRoot; + groupsFilter.zoneFilter = this.zoneFilter; + groupsFilter.displayNameFilter = this.displayNameFilter; + return groupsFilter; + } + + } +} \ No newline at end of file diff --git a/remote-api/src/test/java/org/alfresco/rest/api/tests/GroupsTest.java b/remote-api/src/test/java/org/alfresco/rest/api/tests/GroupsTest.java index e28de0e99d..e84ee463e1 100644 --- a/remote-api/src/test/java/org/alfresco/rest/api/tests/GroupsTest.java +++ b/remote-api/src/test/java/org/alfresco/rest/api/tests/GroupsTest.java @@ -115,6 +115,7 @@ public class GroupsTest extends AbstractSingleNetworkSiteTest testGetGroupsByIsRoot(true); testGetGroupsByIsRoot(false); testGetGroupsWithZoneFilter(); + testGetGroupsWithDisplayNameFilter(); } finally { @@ -1856,4 +1857,193 @@ public class GroupsTest extends AbstractSingleNetworkSiteTest return subGroup; } + + private void testGetGroupsWithDisplayNameFilter() throws Exception + { + shouldFilterGroupByDisplayName(); + shouldFilterGroupByDisplayNameWhenNameNotExist(); + shouldFilterGroupByDisplayNameAndZone(); + shouldFilterGroupByDisplayNameWhenGroupIsRoot(); + shouldFilterGroupByDisplayNameWhenIsRootIsFalse(); + shouldFilterGroupByDisplayNameAndZoneWhenGroupIsRoot(); + shouldReturnBadRequestErrorWhenTooManyDisplayNames(); + shouldReturnBadRequestErrorWhenDisplayNameIsEmpty(); + shouldNotAllowWildcards(); + } + + private void shouldFilterGroupByDisplayName() throws Exception + { + Paging paging = getPaging(0, Integer.MAX_VALUE); + Map otherParams = new HashMap<>(); + otherParams.put("where", "(displayName in ('A Group'))"); + + ListResponse response = getGroups(paging, otherParams); + List groups = response.getList(); + + assertEquals(1, groups.size()); + assertEquals("A Group", groups.get(0).getDisplayName()); + + otherParams.put("where", "(displayName in ('a group'))"); + response = getGroups(paging, otherParams); + response.getList(); + + assertEquals(1, groups.size()); + assertEquals("A Group", groups.get(0).getDisplayName()); + } + + private void shouldFilterGroupByDisplayNameWhenNameNotExist() throws Exception + { + Paging paging = getPaging(0, Integer.MAX_VALUE); + Map otherParams = new HashMap<>(); + otherParams.put("where", "(displayName in ('AGroupName'))"); + + ListResponse response = getGroups(paging, otherParams); + List groups = response.getList(); + + assertTrue(groups.isEmpty()); + } + + private void shouldFilterGroupByDisplayNameAndZone() throws Exception + { + Paging paging = getPaging(0, Integer.MAX_VALUE); + Map otherParams = new HashMap<>(); + addOrderBy(otherParams, org.alfresco.rest.api.Groups.PARAM_DISPLAY_NAME, true); + otherParams.put("include", org.alfresco.rest.api.Groups.PARAM_INCLUDE_ZONES); + otherParams.put("where", "(zones in ('APITEST.MYZONE') AND displayName in ('A Group'))"); + + ListResponse response = getGroups(paging, otherParams); + List groups = response.getList(); + + assertEquals(1, groups.size()); + assertTrue(groups.get(0).getZones().contains("APITEST.MYZONE")); + assertEquals("A Group", groups.get(0).getDisplayName()); + } + + private void shouldFilterGroupByDisplayNameWhenGroupIsRoot() throws Exception + { + Paging paging = getPaging(0, Integer.MAX_VALUE); + Map otherParams = new HashMap<>(); + otherParams.put("where", "(isRoot=true AND displayName in ('Root Group'))"); + + ListResponse response = getGroups(paging, otherParams); + List groups = response.getList(); + + assertEquals(1, groups.size()); + assertEquals("Root Group", groups.get(0).getDisplayName()); + } + + private void shouldFilterGroupByDisplayNameWhenIsRootIsFalse() throws Exception + { + Paging paging = getPaging(0, Integer.MAX_VALUE); + Map otherParams = new HashMap<>(); + otherParams.put("where", "(isRoot=False AND displayName in ('A Group'))"); + + ListResponse response = getGroups(paging, otherParams); + List groups = response.getList(); + + assertEquals(1, groups.size()); + assertEquals("A Group", groups.get(0).getDisplayName()); + } + + private void shouldFilterGroupByDisplayNameAndZoneWhenGroupIsRoot() throws Exception + { + Paging paging = getPaging(0, Integer.MAX_VALUE); + Map otherParams = new HashMap<>(); + otherParams.put("include", org.alfresco.rest.api.Groups.PARAM_INCLUDE_ZONES); + otherParams.put("where", "(isRoot=true AND zones in ('APITEST.MYZONE') AND displayName in ('Root Group'))"); + + ListResponse response = getGroups(paging, otherParams); + List groups = response.getList(); + + assertEquals(1, groups.size()); + assertTrue(groups.get(0).getZones().contains("APP.DEFAULT")); + assertEquals("Root Group", groups.get(0).getDisplayName()); + } + + private void shouldReturnBadRequestErrorWhenTooManyDisplayNames() throws Exception + { + Paging paging = getPaging(0, Integer.MAX_VALUE); + Map otherParams = new HashMap<>(); + otherParams.put("where", "(displayName in ('Group A', 'Group B'))"); + + getGroups(paging, otherParams, "Incorrect response", 400); + } + + private void shouldReturnBadRequestErrorWhenDisplayNameIsEmpty() throws Exception + { + Paging paging = getPaging(0, Integer.MAX_VALUE); + Map otherParams = new HashMap<>(); + otherParams.put("where","(displayName in ())"); + + getGroups(paging, otherParams, "Incorrect response",400); + + otherParams.put("where","(displayName in (''))"); + getGroups(paging, otherParams, "Incorrect response",400); + } + + private void shouldNotAllowWildcards() throws Exception + { + Paging paging = getPaging(0, Integer.MAX_VALUE); + Map otherParams = new HashMap<>(); + + otherParams.put("where", "(displayName in ('*'))"); + ListResponse response = getGroups(paging, otherParams); + List groups = response.getList(); + + assertEquals(0, groups.size()); + + otherParams.put("where", "(isRoot=true AND displayName in ('*'))"); + response = getGroups(paging, otherParams); + groups = response.getList(); + + assertEquals(0, groups.size()); + + otherParams.put("where", "(displayName in ('A*'))"); + response = getGroups(paging, otherParams); + groups = response.getList(); + + assertEquals(0, groups.size()); + + otherParams.put("where", "(isRoot=true AND displayName in ('A*'))"); + response = getGroups(paging, otherParams); + groups = response.getList(); + + assertEquals(0, groups.size()); + + otherParams.put("where", "(displayName in ('*roup'))"); + response = getGroups(paging, otherParams); + groups = response.getList(); + + assertEquals(0, groups.size()); + + otherParams.put("where", "(isRoot=true AND displayName in ('*roup'))"); + response = getGroups(paging, otherParams); + groups = response.getList(); + + assertEquals(0, groups.size()); + + otherParams.put("where", "(displayName in ('Root ?ROUP'))"); + response = getGroups(paging, otherParams); + groups = response.getList(); + + assertEquals(0, groups.size()); + + otherParams.put("where", "(isRoot=true AND displayName in ('Root ?ROUP'))"); + response = getGroups(paging, otherParams); + groups = response.getList(); + + assertEquals(0, groups.size()); + + otherParams.put("where", "(displayName in ('Group'))"); + response = getGroups(paging, otherParams); + groups = response.getList(); + + assertEquals(0, groups.size()); + + otherParams.put("where", "(isRoot=true AND displayName in ('Group'))"); + response = getGroups(paging, otherParams); + groups = response.getList(); + + assertEquals(0, groups.size()); + } } diff --git a/repository/pom.xml b/repository/pom.xml index 7d766198c6..e08404ad7b 100644 --- a/repository/pom.xml +++ b/repository/pom.xml @@ -705,7 +705,7 @@ org.gytheio gytheio-messaging-camel - 0.11.3 + ${dependency.gytheio.version} commons-logging @@ -1027,18 +1027,18 @@ org.aspectj aspectjrt - 1.9.5 + 1.9.6 commons-net commons-net - 3.6 + 3.7 test org.codehaus.groovy groovy-all - 2.4.19 + 2.4.20 indy test diff --git a/repository/src/main/java/org/alfresco/repo/rule/ruletrigger/OnPropertyUpdateRuleTrigger.java b/repository/src/main/java/org/alfresco/repo/rule/ruletrigger/OnPropertyUpdateRuleTrigger.java index 75407a717a..0122b60b2a 100644 --- a/repository/src/main/java/org/alfresco/repo/rule/ruletrigger/OnPropertyUpdateRuleTrigger.java +++ b/repository/src/main/java/org/alfresco/repo/rule/ruletrigger/OnPropertyUpdateRuleTrigger.java @@ -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 . - * #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 . + * #L% + */ package org.alfresco.repo.rule.ruletrigger; import java.io.Serializable; @@ -141,7 +141,7 @@ public class OnPropertyUpdateRuleTrigger extends RuleTriggerAbstractBase for (QName name : keys) { // Skip rule firing on this content property for performance reasons - if (name.equals(ContentModel.PROP_PREFERENCE_VALUES)) + if (name.equals(ContentModel.PROP_PREFERENCE_VALUES) || name.equals(ContentModel.PROP_CASCADE_CRC)) { continue; } diff --git a/repository/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/db/DBResultSet.java b/repository/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/db/DBResultSet.java index aef0e99ac1..bc55077c99 100644 --- a/repository/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/db/DBResultSet.java +++ b/repository/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/db/DBResultSet.java @@ -240,6 +240,11 @@ public class DBResultSet extends AbstractResultSet nodeRefs[n+1] = nodeRef == null ? null : tenantService.getBaseName(nodeRef); } } - } + } + + public NodeService getNodeService() + { + return nodeService; + } } diff --git a/repository/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/db/DBResultSetRow.java b/repository/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/db/DBResultSetRow.java index 9ee6f6c8c4..40de48db15 100644 --- a/repository/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/db/DBResultSetRow.java +++ b/repository/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/db/DBResultSetRow.java @@ -25,11 +25,13 @@ */ package org.alfresco.repo.search.impl.querymodel.impl.db; +import java.io.Serializable; import java.util.Map; import org.alfresco.repo.search.AbstractResultSetRow; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.namespace.QName; /** * @author Andy @@ -82,6 +84,13 @@ public class DBResultSetRow extends AbstractResultSetRow public float getScore(String selectorName) { throw new UnsupportedOperationException(); + } + + @Override + protected Map getDirectProperties() + { + DBResultSet rs = (DBResultSet) getResultSet(); + return rs.getNodeService().getProperties(rs.getNodeRef(getIndex())); } diff --git a/repository/src/main/java/org/alfresco/repo/security/sync/ldap/LDAPUserRegistry.java b/repository/src/main/java/org/alfresco/repo/security/sync/ldap/LDAPUserRegistry.java index c85f6af5cc..d72512d726 100644 --- a/repository/src/main/java/org/alfresco/repo/security/sync/ldap/LDAPUserRegistry.java +++ b/repository/src/main/java/org/alfresco/repo/security/sync/ldap/LDAPUserRegistry.java @@ -54,6 +54,7 @@ import javax.naming.InvalidNameException; import javax.naming.Name; import javax.naming.NamingEnumeration; import javax.naming.NamingException; +import javax.naming.ServiceUnavailableException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; @@ -882,6 +883,16 @@ public class LDAPUserRegistry implements UserRegistry, LDAPNameResolver, Initial continue; } } + catch (ServiceUnavailableException | CommunicationException e) + { + // MNT-21614: Check & fail if communication breaks due to ServiceUnavailableException or CommunicationException + if (e.getMessage() != null) + { + Object[] params = {e.getLocalizedMessage() }; + throw new AlfrescoRuntimeException("synchronization.err.ldap.search", params, e); + } + continue; + } catch (NamingException e) { // Check if it is a timeout and fail diff --git a/repository/src/main/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java b/repository/src/main/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java index 84701bef66..95a240a523 100644 --- a/repository/src/main/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java +++ b/repository/src/main/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java @@ -865,7 +865,22 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent } else { - throw new AlfrescoRuntimeException("Nodes with no type are ignored by SOLR"); + QName typeQName = null; + TypeDefinition typeDefinition = null; + + String errorMessage = "NodeId " + nodeId + " with nodeRef " + nodeRef; + + typeQName = nodeDAO.getNodeType(nodeId); + if (typeQName != null) + { + errorMessage += " has type " + typeQName + ", but this type is not registered in DictionaryService."; + } + else + { + errorMessage += " has no type."; + } + + throw new AlfrescoRuntimeException(errorMessage + " It will be ignored by SOLR."); } } diff --git a/repository/src/test/java/org/alfresco/repo/rule/ruletrigger/RuleTriggerTest.java b/repository/src/test/java/org/alfresco/repo/rule/ruletrigger/RuleTriggerTest.java index 5412b6adc6..055c30daf8 100644 --- a/repository/src/test/java/org/alfresco/repo/rule/ruletrigger/RuleTriggerTest.java +++ b/repository/src/test/java/org/alfresco/repo/rule/ruletrigger/RuleTriggerTest.java @@ -25,6 +25,7 @@ */ package org.alfresco.repo.rule.ruletrigger; +import java.util.Random; import org.alfresco.model.ContentModel; import org.alfresco.model.ForumModel; import org.alfresco.repo.content.MimetypeMap; @@ -426,7 +427,33 @@ public class RuleTriggerTest extends BaseSpringTest // Check to see if the rule type has been triggered assertTrue(ruleType.rulesTriggered); assertEquals(3, ruleType.triggerCount); - } + } + @Test + public void testOnPropertyUpdateRuleTrigger() + { + NodeRef nodeRef1 = this.nodeService.createNode(this.rootNodeRef, + ContentModel.ASSOC_CHILDREN, ContentModel.ASSOC_CHILDREN, + ContentModel.TYPE_CONTAINER).getChildRef(); + + ContentWriter contentWriter = this.contentService.getWriter(nodeRef1, ContentModel.PROP_CONTENT, true); + contentWriter.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + contentWriter.setEncoding("UTF-8"); + contentWriter.putContent("some content"); + + Random rand=new Random(); + this.nodeService.setProperty(nodeRef1, ContentModel.PROP_CASCADE_CRC, rand.nextLong()); + // Terminate the transaction + TestTransaction.flagForCommit(); + TestTransaction.end(); + TestTransaction.start(); + + TestRuleType contentUpdate = createTestRuleType(ON_PROPERTY_UPDATE_TRIGGER); + this.nodeService.setProperty(nodeRef1, ContentModel.PROP_CASCADE_CRC, rand.nextLong()); + + assertFalse(contentUpdate.rulesTriggered); + assertEquals("trigger count not matching",0,contentUpdate.triggerCount); + + } private TestRuleType createTestRuleType(String ruleTriggerName) { diff --git a/repository/src/test/java/org/alfresco/repo/search/impl/querymodel/impl/db/DBQueryTest.java b/repository/src/test/java/org/alfresco/repo/search/impl/querymodel/impl/db/DBQueryTest.java index f0165212c0..e9c6ae0117 100644 --- a/repository/src/test/java/org/alfresco/repo/search/impl/querymodel/impl/db/DBQueryTest.java +++ b/repository/src/test/java/org/alfresco/repo/search/impl/querymodel/impl/db/DBQueryTest.java @@ -994,6 +994,30 @@ public class DBQueryTest implements DictionaryListener results.getResultSetMetaData(); results.close(); } + + @Test + public void testGetValueForTransactionalQuery() + { + String query = "=TYPE:\"cm:folder\" "; + queryUsingGetValue(SearchService.LANGUAGE_FTS_ALFRESCO, query); + } + + public void queryUsingGetValue(String ql, String query) + { + SearchParameters sp = new SearchParameters(); + sp.setLanguage(ql); + sp.setQueryConsistency(QueryConsistency.TRANSACTIONAL); + sp.setQuery(query); + sp.addStore(rootNodeRef.getStoreRef()); + ResultSet results = serviceRegistry.getSearchService().query(sp); + + for (int i = 0; i < results.length(); i++) { + ResultSetRow row = results.getRow(i); + assertNotNull(row.getValue(ContentModel.PROP_NODE_UUID)); + } + results.getResultSetMetaData(); + results.close(); + } private static class UnknownDataType implements Serializable { diff --git a/repository/src/test/java/org/alfresco/repo/security/sync/LDAPUserRegistryTest.java b/repository/src/test/java/org/alfresco/repo/security/sync/LDAPUserRegistryTest.java index 96b192246c..1cade12eae 100644 --- a/repository/src/test/java/org/alfresco/repo/security/sync/LDAPUserRegistryTest.java +++ b/repository/src/test/java/org/alfresco/repo/security/sync/LDAPUserRegistryTest.java @@ -34,10 +34,10 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import javax.naming.CompositeName; -import javax.naming.Name; +import javax.naming.CommunicationException; import javax.naming.NamingEnumeration; import javax.naming.NamingException; +import javax.naming.ServiceUnavailableException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.InitialDirContext; @@ -144,4 +144,52 @@ public class LDAPUserRegistryTest are.getCause().getMessage().contains(LDAPUserRegistry.NAMING_TIMEOUT_EXCEPTION_MESSAGE)); } } + + /** + * Test for MNT-21614: Check & fail if communication breaks due to javax.naming.ServiceUnavailableException + */ + @Test + public void testTimeoutDuringSyncForServiceUnavailableException() throws Exception + { + LDAPUserRegistry userRegistry = createRegistry(); + + when(initialDirContext.getAttributes(eq(LDAPUserRegistry.jndiName(MEMBER_ATTRIBUTE_VALUE)), any())) + .thenThrow(new ServiceUnavailableException(" test.")); + try + { + userRegistry.getGroups(new Date()); + fail("The process should fail with an exception"); + } + catch (AlfrescoRuntimeException are) + { + assertEquals("The error message is not of the right format.", + "synchronization.err.ldap.search", are.getMsgId()); + assertTrue("The error message was not caused by timeout.", + are.getCause().getMessage().contains(" test.")); + } + } + + /** + * Test for MNT-21614: Check & fail if communication breaks due to javax.naming.CommunicationException + */ + @Test + public void testTimeoutDuringSyncForCommunicationException() throws Exception + { + LDAPUserRegistry userRegistry = createRegistry(); + + when(initialDirContext.getAttributes(eq(LDAPUserRegistry.jndiName(MEMBER_ATTRIBUTE_VALUE)), any())) + .thenThrow(new CommunicationException(" test.")); + try + { + userRegistry.getGroups(new Date()); + fail("The process should fail with an exception"); + } + catch (AlfrescoRuntimeException are) + { + assertEquals("The error message is not of the right format.", + "synchronization.err.ldap.search", are.getMsgId()); + assertTrue("The error message was not caused by timeout.", + are.getCause().getMessage().contains(" test.")); + } + } } diff --git a/repository/src/test/java/org/alfresco/repo/solr/SOLRTrackingComponentTest.java b/repository/src/test/java/org/alfresco/repo/solr/SOLRTrackingComponentTest.java index abab9c9eb7..1b5ac2058f 100644 --- a/repository/src/test/java/org/alfresco/repo/solr/SOLRTrackingComponentTest.java +++ b/repository/src/test/java/org/alfresco/repo/solr/SOLRTrackingComponentTest.java @@ -35,6 +35,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; import org.alfresco.repo.dictionary.DictionaryDAO; import org.alfresco.repo.dictionary.M2Model; @@ -68,6 +69,7 @@ import org.apache.commons.logging.LogFactory; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; +import org.springframework.extensions.surf.util.I18NUtil; /** * Tests tracking component @@ -1491,4 +1493,99 @@ public class SOLRTrackingComponentTest extends BaseSpringTest return txs; } } + + @Test + public void testGetNodeMetaDataWithNoType() + { + long startTime = System.currentTimeMillis(); + + SOLRTest st = new SOLRTestWithNoType(txnHelper, fileFolderService, nodeDAO, qnameDAO, nodeService, dictionaryService, rootNodeRef, "testNodeMetaDataNullPropertyValue", true, true); + List createdTransactions = st.buildTransactions(); + + List txns = getTransactions(null, startTime-1000, null, null, 100); + + int[] updates = new int[] {2}; + int[] deletes = new int[] {0}; + List checkedTransactions = checkTransactions(txns, createdTransactions, updates, deletes); + + NodeParameters nodeParameters = new NodeParameters(); + nodeParameters.setTransactionIds(getTransactionIds(checkedTransactions)); + getNodes(nodeParameters, st); + + + NodeMetaDataParameters nodeMetaDataParams = new NodeMetaDataParameters(); + nodeMetaDataParams.setNodeIds(st.getNodeIds()); + try + { + getNodeMetaData(nodeMetaDataParams, null, st); + } + catch (AlfrescoRuntimeException are) + { + if (!are.getMessage().contains("It will be ignored by SOLR")) + { + throw are; + } + } + + } + + private static class SOLRTestWithNoType extends SOLRTest + { + private NodeRef container; + private NodeRef content; + + SOLRTestWithNoType( + RetryingTransactionHelper txnHelper, FileFolderService fileFolderService, + NodeDAO nodeDAO, QNameDAO qnameDAO, NodeService nodeService, DictionaryService dictionaryService, + NodeRef rootNodeRef, String containerName, boolean doNodeChecks, boolean doMetaDataChecks) + { + super(txnHelper, fileFolderService, nodeDAO, qnameDAO, nodeService, dictionaryService,rootNodeRef, containerName, doNodeChecks, doMetaDataChecks); + } + + public int getExpectedNumNodes() + { + return 2; + } + + protected List buildTransactionsInternal() + { + ArrayList txs = new ArrayList(2); + + txs.add(txnHelper.doInTransaction(new RetryingTransactionCallback() + { + public Long execute() throws Throwable + { + PropertyMap props = new PropertyMap(); + props.put(ContentModel.PROP_NAME, "ContainerWithNoType"); + container = nodeService.createNode( + rootNodeRef, + ContentModel.ASSOC_CHILDREN, + ContentModel.ASSOC_CHILDREN, + ContentModel.TYPE_FOLDER, + props).getChildRef(); + + Long containerId = nodeDAO.getNodePair(container).getFirst(); + + content = nodeDAO.newNode( + containerId, + ContentModel.ASSOC_CHILDREN, + ContentModel.ASSOC_CHILDREN, + new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore"), + null, + QName.createQName("{nonExisting}nonExisting"), + I18NUtil.getLocale(), + null, + null).getChildNode().getNodeRef(); + + return nodeDAO.getNodeRefStatus(container).getDbTxnId(); + } + })); + + setExpectedNodeStatus(container, NodeStatus.UPDATED); + setExpectedNodeStatus(content, NodeStatus.UPDATED); + + return txs; + } + } + } \ No newline at end of file