diff --git a/.travis.yml b/.travis.yml index 359fcf58ca..c7804b1eaa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -80,14 +80,14 @@ jobs: before_script: - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.7 postgres -c 'max_connections=300' - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8 - - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.4 + - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.5 script: travis_wait 20 mvn -B test -pl repository -Dtest=AppContext03TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco -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" before_script: - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.7 postgres -c 'max_connections=300' - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8 - - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.4 + - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.5 script: travis_wait 20 mvn -B test -pl repository -Dtest=AppContext04TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco - name: "Repository - AppContext05TestSuite" @@ -104,7 +104,7 @@ jobs: before_script: - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.7 postgres -c 'max_connections=300' - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8 - - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.4 + - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.5 script: travis_wait 20 mvn -B test -pl repository -Dtest=AppContext06TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco -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" @@ -117,7 +117,7 @@ jobs: before_script: - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.7 postgres -c 'max_connections=300' - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8 - - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.4 + - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.5 script: travis_wait 20 mvn -B test -pl repository -Dtest=MiscContextTestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco -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" diff --git a/core/README.md b/core/README.md deleted file mode 100644 index 13462dd056..0000000000 --- a/core/README.md +++ /dev/null @@ -1,42 +0,0 @@ -### Alfresco Core -[![Build Status](https://travis-ci.com/Alfresco/alfresco-core.svg?branch=master)](https://travis-ci.com/Alfresco/alfresco-core) - -Alfresco Core is a library packaged as a jar file which is part of [Alfresco Content Services Repository](https://community.alfresco.com/docs/DOC-6385-project-overview-repository). -The library contains the following: -* Various helpers and utils -* Canned queries interface and supporting classes -* Generic encryption supporting classes - -Version 7 of the library uses Spring 5, Quartz 2.3 and does not have Hibernate dependency. - -### Building and testing -The project can be built and tested by running Maven command: -~~~ -mvn clean install -~~~ - -### Artifacts -The artifacts can be obtained by: -* downloading from [Alfresco repository](https://artifacts.alfresco.com/nexus/content/groups/public) -* getting as Maven dependency by adding the dependency to your pom file: -~~~ - - org.alfresco - alfresco-core - version - -~~~ -and Alfresco repository: -~~~ - - alfresco-maven-repo - https://artifacts.alfresco.com/nexus/content/groups/public - -~~~ -The SNAPSHOT version of the artifact is **never** published. - -### Old version history -The history for older versions can be found in [Alfresco SVN](https://svn.alfresco.com/repos/alfresco-open-mirror/services/alfresco-core/) - -### Contributing guide -Please use [this guide](CONTRIBUTING.md) to make a contribution to the project. diff --git a/core/pom.xml b/core/pom.xml index 1dd65445f6..6ce964ca99 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -112,7 +112,6 @@ javax.servlet javax.servlet-api - 3.0.1 provided @@ -130,13 +129,11 @@ org.mockito mockito-core - 3.2.4 test commons-dbcp commons-dbcp - 1.4-DBCP330 test diff --git a/data-model/README.md b/data-model/README.md deleted file mode 100644 index 3d9f56bc6c..0000000000 --- a/data-model/README.md +++ /dev/null @@ -1,47 +0,0 @@ -### Alfresco Data Model -[![Build Status](https://travis-ci.com/Alfresco/alfresco-data-model.svg?branch=master)](https://travis-ci.com/Alfresco/alfresco-data-model) - -Data model is a library packaged as a jar file which is part of [Alfresco Content Services Repository](https://community.alfresco.com/docs/DOC-6385-project-overview-repository). -The library contains the following: -* Dictionary, Repository and Search Services interfaces -* Models for data types and Dictionary implementation -* Parsers - -Please note that the data model uses version 2 of the Jackson libraries. -The upgrade from version 1 was not backward compatible, any projects -that are dependent on data model using Jackson 1.x should use the data-model 6.N branch. - -Version 8.0 of data-model depends on alfresco-core 7.0 which is based on Spring 5. - - -### Building and testing -The project can be built and tested by running Maven command: -~~~ -mvn clean install -~~~ - -### Artifacts -The artifacts can be obtained by: -* downloading from [Alfresco repository](https://artifacts.alfresco.com/nexus/content/groups/public) -* getting as Maven dependency by adding the dependency to your pom file: -~~~ - - org.alfresco - alfresco-data-model - version - -~~~ -and Alfresco repository: -~~~ - - alfresco-maven-repo - https://artifacts.alfresco.com/nexus/content/groups/public - -~~~ -The SNAPSHOT version of the artifact is **never** published. - -### Old version history -The history for older versions can be found in [Alfresco SVN](https://svn.alfresco.com/repos/alfresco-open-mirror/alfresco/HEAD/root/projects/data-model) - -### Contributing guide -Please use [this guide](CONTRIBUTING.md) to make a contribution to the project. diff --git a/data-model/pom.xml b/data-model/pom.xml index f34a937270..bd243f0a61 100644 --- a/data-model/pom.xml +++ b/data-model/pom.xml @@ -133,7 +133,6 @@ javax.servlet javax.servlet-api - 3.0.1 provided @@ -230,13 +228,11 @@ org.antlr gunit - 3.5.2 test org.mockito mockito-core - 3.2.4 test diff --git a/packaging/docker-alfresco/Dockerfile b/packaging/docker-alfresco/Dockerfile index 927490233d..71d44d63ac 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 # 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. ARG resource_path=target @@ -34,7 +34,7 @@ COPY ${resource_path}/war ${TOMCAT_DIR}/webapps COPY ${resource_path}/connector/* ${TOMCAT_DIR}/lib/ COPY ${resource_path}/alfresco-mmt/* ${TOMCAT_DIR}/alfresco-mmt/ COPY ${resource_path}/dependency/licenses/ /licenses/ -COPY ${resource_path}/dependency/keystore/metadata-keystore ${TOMCAT_DIR}/shared/classes/alfresco/extension/keystore/ +COPY ${resource_path}/dependency/keystore/metadata-keystore/keystore ${TOMCAT_DIR}/shared/classes/alfresco/extension/keystore # Change the value of the shared.loader= property to the following: # shared.loader=${catalina.base}/shared/classes diff --git a/packaging/tests/environment/.env b/packaging/tests/environment/.env index f13d730f80..b60ffc632e 100644 --- a/packaging/tests/environment/.env +++ b/packaging/tests/environment/.env @@ -1,4 +1,4 @@ -TRANSFORMERS_TAG=2.3.1 -SOLR6_TAG=1.4.2 +TRANSFORMERS_TAG=2.3.5 +SOLR6_TAG=2.0.0 POSTGRES_TAG=11.7 ACTIVEMQ_TAG=5.15.8 diff --git a/packaging/war/pom.xml b/packaging/war/pom.xml index 378645abbf..2ab2c486a8 100644 --- a/packaging/war/pom.xml +++ b/packaging/war/pom.xml @@ -103,13 +103,11 @@ org.springframework spring-test - ${dependency.spring.version} test org.mockito mockito-core - 3.3.3 test @@ -121,13 +119,11 @@ org.postgresql postgresql - ${dependency.postgresql.version} test mysql mysql-connector-java - ${dependency.mysql.version} test diff --git a/pom.xml b/pom.xml index 1bf362bc24..0f5a772cbc 100644 --- a/pom.xml +++ b/pom.xml @@ -75,14 +75,14 @@ 3.1-HTTPCLIENT-1265 2.12.0-alfresco-patched-20191004 1.7.30 - 0.11.3 + 0.11.6 2.3.2 2.5.9 1.6.2 - 1.21-20190624-alfresco-patched + 1.24.1 5.1.9.RELEASE 7.7.10 - 4.1.1 + 4.1.2 1.4 11.0.0-alfresco-001 3.4.1.Final @@ -91,7 +91,7 @@ 1.2.5 3.2.0 - 1.3.1 + 1.3.2-RC1 42.2.14 8.0.19 @@ -172,11 +172,6 @@ win64 tgz - - org.alfresco - alfresco-pdf-renderer - ${dependency.alfresco-pdf-renderer.version} - org.alfresco alfresco-server-root @@ -488,12 +483,6 @@ xercesImpl ${dependency.xercesImpl.version} - - - com.drewnoakes - metadata-extractor - 2.13.0 - com.github.junrar diff --git a/remote-api/README.md b/remote-api/README.md deleted file mode 100644 index 8065f12c9d..0000000000 --- a/remote-api/README.md +++ /dev/null @@ -1,41 +0,0 @@ -### Alfresco Remote API -[![Build Status](https://travis-ci.com/Alfresco/alfresco-remote-api.svg?branch=master)](https://travis-ci.com/Alfresco/alfresco-remote-api) - -Remote API is a library packaged as a jar file which is part of [Alfresco Content Services Repository](https://community.alfresco.com/docs/DOC-6385-project-overview-repository). -The library contains the following: -* REST API framework -* WebScript implementations including [V1 REST APIs](https://community.alfresco.com/community/ecm/blog/2017/05/02/v1-rest-api-10-things-you-should-know) -* [OpenCMIS](https://chemistry.apache.org/java/opencmis.html) implementations - -### Building and testing -The project can be built by running Maven command: -~~~ -mvn clean install -~~~ -The tests are combined in test classes split by test type or Spring application context used in the test, see classes in _src/test/java/org/alfresco_. All of these classes as well as individual tests can be run by specifying the test class name and a set of DB connection properties, for example: -~~~ -mvn clean test -Dtest=SomeTest -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql:alfresco -Ddb.username=alfresco -Ddb.password=alfresco -~~~ - -### Artifacts -The artifacts can be obtained by: -* downloading from [Alfresco repository](https://artifacts.alfresco.com/nexus/content/groups/public) -* getting as Maven dependency by adding the dependency to your pom file: -~~~ - - org.alfresco - alfresco-remote-api - version - -~~~ -and Alfresco Maven repository: -~~~ - - alfresco-maven-repo - https://artifacts.alfresco.com/nexus/content/groups/public - -~~~ -The SNAPSHOT version of the artifact is **never** published. - -### Contributing guide -Please use [this guide](CONTRIBUTING.md) to make a contribution to the project. diff --git a/remote-api/pom.xml b/remote-api/pom.xml index 9f34d5f37a..761b001553 100644 --- a/remote-api/pom.xml +++ b/remote-api/pom.xml @@ -24,28 +24,23 @@ com.fasterxml.jackson.core jackson-core - ${dependency.jackson.version} com.fasterxml.jackson.core jackson-databind - ${dependency.jackson-databind.version} com.fasterxml.jackson.core jackson-annotations - ${dependency.jackson.version} javax.servlet javax.servlet-api - 3.0.1 provided org.apache.commons commons-csv - 1.8 org.apache.santuario @@ -56,7 +51,6 @@ org.alfresco.surf spring-webscripts - ${dependency.webscripts.version} javax.xml @@ -83,13 +77,11 @@ org.mockito mockito-core - 3.3.0 test org.springframework spring-test - ${dependency.spring.version} test @@ -109,14 +101,12 @@ org.alfresco.surf spring-webscripts - ${dependency.webscripts.version} tests test org.postgresql postgresql - ${dependency.postgresql.version} test @@ -157,7 +147,6 @@ org.alfresco alfresco-pdf-renderer - ${dependency.alfresco-pdf-renderer.version} win64 tgz @@ -202,7 +191,6 @@ org.alfresco alfresco-pdf-renderer - ${dependency.alfresco-pdf-renderer.version} linux tgz @@ -239,54 +227,6 @@ ${project.build.directory}/test-binaries/alfresco-pdf-renderer/alfresco-pdf-renderer - - osx-alfresco-pdf-renderer-test - - - mac - - - - - org.alfresco - alfresco-pdf-renderer - ${dependency.alfresco-pdf-renderer.version} - osx - tgz - - - - - - false - maven-antrun-plugin - - - extract-alfresco-pdf-renderer-test - generate-test-resources - - run - - - ${skipTests} - - - - - - - - - - - - - - - - ${project.build.directory}/test-binaries/alfresco-pdf-renderer/alfresco-pdf-renderer - - diff --git a/remote-api/src/main/java/org/alfresco/repo/web/scripts/solr/SOLRSerializer.java b/remote-api/src/main/java/org/alfresco/repo/web/scripts/solr/SOLRSerializer.java index b483948b12..ecffd579a7 100644 --- a/remote-api/src/main/java/org/alfresco/repo/web/scripts/solr/SOLRSerializer.java +++ b/remote-api/src/main/java/org/alfresco/repo/web/scripts/solr/SOLRSerializer.java @@ -438,7 +438,7 @@ import org.springframework.extensions.webscripts.json.JSONUtils; { public String convert(ChildAssociationRef source) { - return source.toString(); + return org.json.simple.JSONObject.escape(source.toString()); } }); @@ -454,7 +454,7 @@ import org.springframework.extensions.webscripts.json.JSONUtils; { public String convert(AssociationRef source) { - return source.toString(); + return org.json.simple.JSONObject.escape(source.toString()); } }); diff --git a/remote-api/src/main/java/org/alfresco/repo/webdav/auth/BaseKerberosAuthenticationFilter.java b/remote-api/src/main/java/org/alfresco/repo/webdav/auth/BaseKerberosAuthenticationFilter.java index 2b0bfd7096..b08ea6d271 100644 --- a/remote-api/src/main/java/org/alfresco/repo/webdav/auth/BaseKerberosAuthenticationFilter.java +++ b/remote-api/src/main/java/org/alfresco/repo/webdav/auth/BaseKerberosAuthenticationFilter.java @@ -366,7 +366,22 @@ public abstract class BaseKerberosAuthenticationFilter extends BaseSSOAuthentica } // Send back a request for SPNEGO authentication - logonStartAgain(context, req, resp, true); + + // MNT-21702 fixing Kerberos SSO fallback machanism for WebDAV + if (req.getRequestURL().toString().contains("webdav")) + { + if ( getLogger().isDebugEnabled()) { + getLogger().debug("WebDAV request, fallback"); + } + logonStartAgain(context, req, resp, false); + } + else + { + if ( getLogger().isDebugEnabled()) { + getLogger().debug("Non-WebDAV request, don't fallback"); + } + logonStartAgain(context, req, resp, true); + } return false; } diff --git a/remote-api/src/main/java/org/alfresco/repo/webdav/auth/BaseSSOAuthenticationFilter.java b/remote-api/src/main/java/org/alfresco/repo/webdav/auth/BaseSSOAuthenticationFilter.java index 3c4bcdb90f..a99a30e68b 100644 --- a/remote-api/src/main/java/org/alfresco/repo/webdav/auth/BaseSSOAuthenticationFilter.java +++ b/remote-api/src/main/java/org/alfresco/repo/webdav/auth/BaseSSOAuthenticationFilter.java @@ -208,7 +208,7 @@ public abstract class BaseSSOAuthenticationFilter extends BaseAuthenticationFilt { match = container.getRegistry().findWebScript(req.getMethod(), getScriptUrl(req)); } - catch (NotFoundException notFoundEx) + catch (NotFoundException | IllegalArgumentException Ex) { getLogger().debug(req.getMethod() + " " + getScriptUrl(req) + "not found in Public API Container."); } diff --git a/remote-api/src/test/java/org/alfresco/repo/web/scripts/solr/SOLRSerializerTest.java b/remote-api/src/test/java/org/alfresco/repo/web/scripts/solr/SOLRSerializerTest.java index 5594dfa7e0..0cb5271feb 100644 --- a/remote-api/src/test/java/org/alfresco/repo/web/scripts/solr/SOLRSerializerTest.java +++ b/remote-api/src/test/java/org/alfresco/repo/web/scripts/solr/SOLRSerializerTest.java @@ -4,57 +4,121 @@ * %% * 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 + * 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 + * 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.web.scripts.solr; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.util.Date; +import org.alfresco.model.ContentModel; import org.alfresco.repo.web.scripts.solr.SOLRSerializer.SOLRTypeConverter; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; import org.alfresco.util.ISO8601DateFormat; +import org.json.JSONException; +import org.json.JSONObject; import org.junit.Test; +import org.mockito.Mockito; -public class SOLRSerializerTest +public class SOLRSerializerTest { - @Test + @Test public void testDateSerializer() { - SOLRTypeConverter typeConverter = new SOLRTypeConverter(null); - - trip(typeConverter, "1912-01-01T00:40:00-06:00", "1912-01-01T06:40:00.000Z"); - trip(typeConverter, "1812-01-01T00:40:00-06:00", "1812-01-01T06:40:00.000Z"); - trip(typeConverter, "1845-01-01T00:40:00-06:00", "1845-01-01T06:40:00.000Z"); - trip(typeConverter, "1846-01-01T00:40:00-06:00", "1846-01-01T06:40:00.000Z"); - trip(typeConverter, "1847-01-01T00:40:00-06:00", "1847-01-01T06:40:00.000Z"); - trip(typeConverter, "1848-01-01T00:40:00-06:00", "1848-01-01T06:40:00.000Z"); - - + SOLRTypeConverter typeConverter = new SOLRTypeConverter(null); + + trip(typeConverter, "1912-01-01T00:40:00-06:00", "1912-01-01T06:40:00.000Z"); + trip(typeConverter, "1812-01-01T00:40:00-06:00", "1812-01-01T06:40:00.000Z"); + trip(typeConverter, "1845-01-01T00:40:00-06:00", "1845-01-01T06:40:00.000Z"); + trip(typeConverter, "1846-01-01T00:40:00-06:00", "1846-01-01T06:40:00.000Z"); + trip(typeConverter, "1847-01-01T00:40:00-06:00", "1847-01-01T06:40:00.000Z"); + trip(typeConverter, "1848-01-01T00:40:00-06:00", "1848-01-01T06:40:00.000Z"); + } - - - private void trip( SOLRTypeConverter typeConverter, String iso, String zulu) - { - Date testDate = ISO8601DateFormat.parse(iso); - String strDate = typeConverter.INSTANCE.convert(String.class, testDate); - assertEquals(zulu, strDate); - } + + private void trip(SOLRTypeConverter typeConverter, String iso, String zulu) + { + Date testDate = ISO8601DateFormat.parse(iso); + String strDate = typeConverter.INSTANCE.convert(String.class, testDate); + assertEquals(zulu, strDate); + } + + /** + * Test SOLR Serialization including values with special characters for ChildAssociationRef + */ + @Test + public void testChildAssociationRefToJSONString() + { + SOLRSerializer solrSerializer = new SOLRSerializer(); + solrSerializer.setDictionaryService(Mockito.mock(DictionaryService.class)); + solrSerializer.setNamespaceService(Mockito.mock(NamespaceService.class)); + solrSerializer.init(); + + // Create a Child QName including special character \ + QName childQName = QName.createQName("hello", "wo\rld"); + + ChildAssociationRef childAssociationRef = new ChildAssociationRef(ContentModel.ASSOC_CONTAINS, + new NodeRef("workspace://SpacesStore/parent"), childQName, + new NodeRef("workspace://SpacesStore/child")); + String validJsonString = solrSerializer.serializeToJSONString(childAssociationRef); + String jsonObjectString = String.format("{ \"key\": \"%s\" }", validJsonString); + + try + { + new JSONObject(jsonObjectString); + } + catch (JSONException e) + { + assertTrue("JSON String " + jsonObjectString + " is not a valid JSON", false); + } + } + + /** + * Test SOLR Serialization including values with special characters for AssociationRef + */ + @Test + public void testAssociationRefToJSONString() + { + SOLRSerializer solrSerializer = new SOLRSerializer(); + solrSerializer.setDictionaryService(Mockito.mock(DictionaryService.class)); + solrSerializer.setNamespaceService(Mockito.mock(NamespaceService.class)); + solrSerializer.init(); + AssociationRef associationRef = new AssociationRef( + new NodeRef("workspace://SpacesStore/wo\rld"), + ContentModel.ASSOC_ATTACHMENTS, + new NodeRef("workspace://SpacesStore/hello")); + String validJsonString = solrSerializer.serializeToJSONString(associationRef); + String jsonObjectString = String.format("{ \"key\": \"%s\" }", validJsonString); + + try + { + new JSONObject(jsonObjectString); + } + catch (JSONException e) + { + assertTrue("JSON String " + jsonObjectString + " is not a valid JSON", false); + } + } + } diff --git a/repository/README.md b/repository/README.md deleted file mode 100644 index ae8a2cd64a..0000000000 --- a/repository/README.md +++ /dev/null @@ -1,41 +0,0 @@ -### Alfresco Repository -[![Build Status](https://travis-ci.com/Alfresco/alfresco-repository.svg?branch=master)](https://travis-ci.com/Alfresco/alfresco-repository) - -Repository is a library packaged as a jar file which is part of [Alfresco Content Services Repository](https://community.alfresco.com/docs/DOC-6385-project-overview-repository). -The library contains the following: -* DAOs and SQL scripts -* Various Service implementations -* Utility classes - -### Building and testing -The project can be built by running Maven command: -~~~ -mvn clean install -~~~ -The tests are combined in test classes split by test type or Spring application context used in the test, see classes in _src/test/java/org/alfresco_. All of these classes as well as individual tests can be run by specifying the test class name and a set of DB connection properties, for example: -~~~ -mvn clean test -Dtest=SomeRepoTest -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql:alfresco -Ddb.username=alfresco -Ddb.password=alfresco -~~~ - -### Artifacts -The artifacts can be obtained by: -* downloading from [Alfresco repository](https://artifacts.alfresco.com/nexus/content/groups/public) -* getting as Maven dependency by adding the dependency to your pom file: -~~~ - - org.alfresco - alfresco-repository - version - -~~~ -and Alfresco Maven repository: -~~~ - - alfresco-maven-repo - https://artifacts.alfresco.com/nexus/content/groups/public - -~~~ -The SNAPSHOT version of the artifact is **never** published. - -### Contributing guide -Please use [this guide](CONTRIBUTING.md) to make a contribution to the project. diff --git a/repository/pom.xml b/repository/pom.xml index d65694c0ac..07aae8ee3d 100644 --- a/repository/pom.xml +++ b/repository/pom.xml @@ -19,7 +19,6 @@ org.alfresco alfresco-jlan-embed - ${dependency.alfresco-jlan.version} * @@ -40,7 +39,6 @@ org.alfresco alfresco-heartbeat-data-sender - ${dependency.alfresco-hb-data-sender.version} com.sun.mail @@ -55,17 +53,14 @@ commons-dbcp commons-dbcp - 1.4-DBCP330 commons-fileupload commons-fileupload - 1.4 org.apache.commons commons-compress - 1.19 org.apache.commons @@ -75,17 +70,14 @@ commons-codec commons-codec - 1.14 commons-beanutils commons-beanutils - 1.9.4 commons-collections commons-collections - 3.2.2 commons-io @@ -129,7 +121,6 @@ org.springframework spring-core - ${dependency.spring.version} @@ -142,7 +133,6 @@ org.springframework spring-orm - ${dependency.spring.version} @@ -155,17 +145,14 @@ org.springframework spring-context - ${dependency.spring.version} org.springframework spring-context-support - ${dependency.spring.version} org.springframework spring-web - ${dependency.spring.version} org.subethamail @@ -226,12 +213,10 @@ xerces xercesImpl - 2.12.0-alfresco-patched-20191004 xalan xalan - 2.7.2-alfresco xml-apis @@ -272,7 +257,6 @@ org.apache.pdfbox pdfbox - ${dependency.pdfbox.version} org.apache.pdfbox @@ -379,7 +363,6 @@ javax.servlet javax.servlet-api - 3.0.1 provided @@ -392,19 +375,16 @@ com.fasterxml.jackson.core jackson-databind - ${dependency.jackson-databind.version} org.alfresco.surf spring-surf-core-configservice - ${dependency.webscripts.version} org.alfresco.surf spring-webscripts - ${dependency.webscripts.version} com.sun @@ -427,7 +407,6 @@ org.alfresco.surf spring-webscripts-api - ${dependency.webscripts.version} @@ -451,7 +430,6 @@ com.google.guava guava - 28.2-jre org.springframework.security @@ -800,13 +778,11 @@ org.mockito mockito-core - 3.3.0 test org.springframework spring-test - ${dependency.spring.version} test @@ -850,19 +826,16 @@ org.postgresql postgresql - ${dependency.postgresql.version} test mysql mysql-connector-java - ${dependency.mysql.version} test org.mariadb.jdbc mariadb-java-client - ${dependency.mariadb.version} test @@ -874,13 +847,11 @@ org.antlr gunit - ${dependency.antlr.version} test org.alfresco.surf spring-webscripts - ${dependency.webscripts.version} tests test @@ -938,7 +909,6 @@ org.alfresco alfresco-pdf-renderer - ${dependency.alfresco-pdf-renderer.version} win64 tgz @@ -983,7 +953,6 @@ org.alfresco alfresco-pdf-renderer - ${dependency.alfresco-pdf-renderer.version} linux tgz @@ -1020,54 +989,6 @@ ${project.build.directory}/test-binaries/alfresco-pdf-renderer/alfresco-pdf-renderer - - osx-alfresco-pdf-renderer-test - - - mac - - - - - org.alfresco - alfresco-pdf-renderer - ${dependency.alfresco-pdf-renderer.version} - osx - tgz - - - - - - false - maven-antrun-plugin - - - extract-alfresco-pdf-renderer-test - generate-test-resources - - run - - - ${skipTests} - - - - - - - - - - - - - - - - ${project.build.directory}/test-binaries/alfresco-pdf-renderer/alfresco-pdf-renderer - - diff --git a/repository/src/main/java/org/alfresco/opencmis/TransactionAwareHolder.java b/repository/src/main/java/org/alfresco/opencmis/TransactionAwareHolder.java index a5c5991583..e35d75d413 100644 --- a/repository/src/main/java/org/alfresco/opencmis/TransactionAwareHolder.java +++ b/repository/src/main/java/org/alfresco/opencmis/TransactionAwareHolder.java @@ -81,22 +81,19 @@ public class TransactionAwareHolder extends Holder { this.internalHolder = internalHolder; this.value = internalHolder.getValue(); - txListener = new TxAwareHolderListener(); } @Override public T getValue() { - if (TransactionSynchronizationManager.isSynchronizationActive()) - { - AlfrescoTransactionSupport.bindListener(txListener); - } + registerTxListenerIfNeeded(); return this.value; } @Override public void setValue(T value) { + registerTxListenerIfNeeded(); this.value = value; } @@ -109,6 +106,17 @@ public class TransactionAwareHolder extends Holder '}'; } + // MNT-21800 CMIS Web Service Check Out returns error + private void registerTxListenerIfNeeded() + { + if (this.txListener == null && TransactionSynchronizationManager.isSynchronizationActive()) + { + TxAwareHolderListener listener = new TxAwareHolderListener(); + AlfrescoTransactionSupport.bindListener(listener); + this.txListener = listener; + } + } + private class TxAwareHolderListener extends TransactionListenerAdapter { @Override diff --git a/repository/src/main/java/org/alfresco/repo/content/metadata/TikaAutoMetadataExtracter.java b/repository/src/main/java/org/alfresco/repo/content/metadata/TikaAutoMetadataExtracter.java index 74bec7fe45..63c1ad441a 100644 --- a/repository/src/main/java/org/alfresco/repo/content/metadata/TikaAutoMetadataExtracter.java +++ b/repository/src/main/java/org/alfresco/repo/content/metadata/TikaAutoMetadataExtracter.java @@ -68,11 +68,10 @@ public class TikaAutoMetadataExtracter extends TikaPoweredMetadataExtracter protected static Log logger = LogFactory.getLog(TikaAutoMetadataExtracter.class); private static AutoDetectParser parser; private static TikaConfig config; - private static String EXIF_IMAGE_HEIGHT_TAG = "Exif Image Height"; - private static String EXIF_IMAGE_WIDTH_TAG = "Exif Image Width"; + private static String EXIF_IMAGE_HEIGHT_TAG = "Exif SubIFD:Exif Image Height"; + private static String EXIF_IMAGE_WIDTH_TAG = "Exif SubIFD:Exif Image Width"; private static String JPEG_IMAGE_HEIGHT_TAG = "Image Height"; private static String JPEG_IMAGE_WIDTH_TAG = "Image Width"; - private static String COMPRESSION_TAG = "Compression"; public static ArrayList SUPPORTED_MIMETYPES; private static ArrayList buildMimeTypes(TikaConfig tikaConfig) @@ -122,24 +121,19 @@ public class TikaAutoMetadataExtracter extends TikaPoweredMetadataExtracter */ @Override protected Map extractSpecific(Metadata metadata, - Map properties, Map headers) + Map properties, Map headers) { - if(MimetypeMap.MIMETYPE_IMAGE_JPEG.equals(metadata.get(Metadata.CONTENT_TYPE))) + if (MimetypeMap.MIMETYPE_IMAGE_JPEG.equals(metadata.get(Metadata.CONTENT_TYPE))) { //check if the image has exif information - if(metadata.get(EXIF_IMAGE_WIDTH_TAG) != null - && metadata.get(EXIF_IMAGE_HEIGHT_TAG) != null - && metadata.get(COMPRESSION_TAG) != null) + if (metadata.get(EXIF_IMAGE_WIDTH_TAG) != null && metadata.get(EXIF_IMAGE_HEIGHT_TAG) != null) { //replace the exif size properties that will be embedded in the node with //the guessed dimensions from Tika - putRawValue(TIFF.IMAGE_LENGTH.getName(), extractSize(metadata.get(EXIF_IMAGE_HEIGHT_TAG)), properties); - putRawValue(TIFF.IMAGE_WIDTH.getName(), extractSize(metadata.get(EXIF_IMAGE_WIDTH_TAG)), properties); - putRawValue(JPEG_IMAGE_HEIGHT_TAG, metadata.get(EXIF_IMAGE_HEIGHT_TAG), properties); - putRawValue(JPEG_IMAGE_WIDTH_TAG, metadata.get(EXIF_IMAGE_WIDTH_TAG), properties); + putRawValue(TIFF.IMAGE_LENGTH.getName(), extractSize(metadata.get(JPEG_IMAGE_HEIGHT_TAG)), properties); + putRawValue(TIFF.IMAGE_WIDTH.getName(), extractSize(metadata.get(JPEG_IMAGE_WIDTH_TAG)), properties); } } return properties; } - } diff --git a/repository/src/main/java/org/alfresco/repo/domain/permissions/ADMAccessControlListDAO.java b/repository/src/main/java/org/alfresco/repo/domain/permissions/ADMAccessControlListDAO.java index 774cccc9bd..8d7b54d07d 100644 --- a/repository/src/main/java/org/alfresco/repo/domain/permissions/ADMAccessControlListDAO.java +++ b/repository/src/main/java/org/alfresco/repo/domain/permissions/ADMAccessControlListDAO.java @@ -430,8 +430,8 @@ public class ADMAccessControlListDAO implements AccessControlListDAO // { // setFixedAcls(child.getId(), inheritFrom, mergeFrom, sharedAclToReplace, changes, false); // } - // Already replaced - if(acl.equals(sharedAclToReplace)) + // Still has old shared ACL or already replaced + if(acl.equals(sharedAclToReplace) || acl.equals(mergeFrom)) { propagateOnChildren = setFixAclPending(child.getId(), inheritFrom, mergeFrom, sharedAclToReplace, changes, false, asyncCall, propagateOnChildren); } 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..4a45bc649b 100644 --- a/repository/src/main/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java +++ b/repository/src/main/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java @@ -691,20 +691,18 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent return new ArrayList(visited); } - + /** Get properties that we want to be indexed. */ protected Map getProperties(Long nodeId) { - Map props = null; - // ALF-10641 - // Residual properties are un-indexed -> break serlialisation + // Residual properties are un-indexed -> break serialisation nodeDAO.setCheckNodeConsistency(); Map sourceProps = nodeDAO.getNodeProperties(nodeId); - props = new HashMap((int)(sourceProps.size() * 1.3)); + Map props = new HashMap<>(sourceProps.size()); for(QName propertyQName : sourceProps.keySet()) { PropertyDefinition propDef = dictionaryService.getProperty(propertyQName); - if(propDef != null) + if(propDef != null && propDef.isIndexed()) { props.put(propertyQName, sourceProps.get(propertyQName)); } @@ -865,7 +863,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/main/resources/alfresco/subsystems/Search/solr4/solr-search-context.xml b/repository/src/main/resources/alfresco/subsystems/Search/solr4/solr-search-context.xml index c111fb94ac..52f5a18f82 100644 --- a/repository/src/main/resources/alfresco/subsystems/Search/solr4/solr-search-context.xml +++ b/repository/src/main/resources/alfresco/subsystems/Search/solr4/solr-search-context.xml @@ -153,18 +153,15 @@ - - - - - - - + + + + diff --git a/repository/src/test/java/org/alfresco/repo/domain/permissions/FixedAclUpdaterTest.java b/repository/src/test/java/org/alfresco/repo/domain/permissions/FixedAclUpdaterTest.java index 16b787afb2..70566e8d0f 100644 --- a/repository/src/test/java/org/alfresco/repo/domain/permissions/FixedAclUpdaterTest.java +++ b/repository/src/test/java/org/alfresco/repo/domain/permissions/FixedAclUpdaterTest.java @@ -25,7 +25,10 @@ */ package org.alfresco.repo.domain.permissions; +import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.alfresco.model.ContentModel; @@ -41,6 +44,7 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransacti import org.alfresco.repo.transaction.TransactionListenerAdapter; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.QName; @@ -69,6 +73,7 @@ public class FixedAclUpdaterTest extends TestCase private Repository repository; private FixedAclUpdater fixedAclUpdater; private NodeRef folderAsyncCallNodeRef; + private NodeRef folderAsyncCallWithCreateNodeRef; private NodeRef folderSyncCallNodeRef; private PermissionsDaoComponent permissionsDaoComponent; private PermissionService permissionService; @@ -100,6 +105,10 @@ public class FixedAclUpdaterTest extends TestCase filesPerLevel); folderSyncCallNodeRef = txnHelper.doInTransaction(cb2); + RetryingTransactionCallback cb3 = createFolderHierchyCallback(home, fileFolderService, + "rootFolderAsyncWithCreateCall", filesPerLevel); + folderAsyncCallWithCreateNodeRef = txnHelper.doInTransaction(cb3); + // change setFixedAclMaxTransactionTime to lower value so setInheritParentPermissions on created folder // hierarchy require async call setFixedAclMaxTransactionTime(permissionsDaoComponent, home, 50); @@ -147,8 +156,10 @@ public class FixedAclUpdaterTest extends TestCase aspect.add(ContentModel.ASPECT_TEMPORARY); nodeDAO.addNodeAspects(nodeDAO.getNodePair(folderAsyncCallNodeRef).getFirst(), aspect); nodeDAO.addNodeAspects(nodeDAO.getNodePair(folderSyncCallNodeRef).getFirst(), aspect); + nodeDAO.addNodeAspects(nodeDAO.getNodePair(folderAsyncCallWithCreateNodeRef).getFirst(), aspect); fileFolderService.delete(folderAsyncCallNodeRef); fileFolderService.delete(folderSyncCallNodeRef); + fileFolderService.delete(folderAsyncCallWithCreateNodeRef); return null; }, false, true); } @@ -189,7 +200,34 @@ public class FixedAclUpdaterTest extends TestCase testWork(folderAsyncCallNodeRef, true); } + @Test + public void testAsyncWithNodeCreation() + { + testWorkWithNodeCreation(folderAsyncCallWithCreateNodeRef, true); + } + private void testWork(NodeRef folderRef, boolean asyncCall) + { + setPermissionsOnTree(folderRef, asyncCall); + triggerFixedACLJob(folderRef); + } + + private void testWorkWithNodeCreation(NodeRef folderRef, boolean asyncCall) + { + setPermissionsOnTree(folderRef, asyncCall); + + // MNT-21847 - Create a new content in folder that has the aspect applied + txnHelper.doInTransaction((RetryingTransactionCallback) () -> { + NodeRef folderWithPendingAcl = getFirstFolderWithAclPending(folderRef); + assertNotNull("No children folders were found with pendingFixACl aspect", folderWithPendingAcl); + createFile(fileFolderService, folderWithPendingAcl, "NewFile", ContentModel.TYPE_CONTENT); + return null; + }, false, true); + + triggerFixedACLJob(folderRef); + } + + private void setPermissionsOnTree(NodeRef folderRef, boolean asyncCall) { // kick it off by setting inherit parent permissions == false txnHelper.doInTransaction((RetryingTransactionCallback) () -> { @@ -203,21 +241,61 @@ public class FixedAclUpdaterTest extends TestCase assertTrue("There are no nodes to process", getNodesCountWithPendingFixedAclAspect() > 0); return null; }, false, true); + } - // run the fixedAclUpdater until there is nothing more to fix (running the updater - // may create more to fix up) + private void triggerFixedACLJob(NodeRef folder) + { + // run the fixedAclUpdater until there is nothing more to fix (running the updater may create more to fix up) or + // the count doesn't change, meaning we have a problem. txnHelper.doInTransaction((RetryingTransactionCallback) () -> { int count = 0; + int previousCount = 0; do { + previousCount = count; count = fixedAclUpdater.execute(); - } while (count > 0); + } while (count > 0 && previousCount != count); return null; }, false, true); // check if nodes with ASPECT_PENDING_FIX_ACL are processed txnHelper.doInTransaction((RetryingTransactionCallback) () -> { assertEquals("Not all nodes were processed", 0, getNodesCountWithPendingFixedAclAspect()); + //Remove the tree that failed so it does not influence the other test results + removeNodesWithPendingAcl(folder); + return null; + }, false, true); + } + + private NodeRef getFirstFolderWithAclPending(NodeRef parentNodeRef) + { + NodeRef folderWithPendingFixedAcl = null; + List primaryChildFolders = fileFolderService.listFolders(parentNodeRef); + for (int i = 0; i < primaryChildFolders.size(); i++) + { + NodeRef thisChildFolder = primaryChildFolders.get(i).getNodeRef(); + Long thisChildNodeId = nodeDAO.getNodePair(thisChildFolder).getFirst(); + if (nodeDAO.hasNodeAspect(thisChildNodeId, ContentModel.ASPECT_PENDING_FIX_ACL)) + { + folderWithPendingFixedAcl = thisChildFolder; + break; + } + + if (folderWithPendingFixedAcl == null) + { + folderWithPendingFixedAcl = getFirstFolderWithAclPending(thisChildFolder); + } + } + return folderWithPendingFixedAcl; + } + + private void removeNodesWithPendingAcl(NodeRef folder) + { + txnHelper.doInTransaction((RetryingTransactionCallback) () -> { + Set aspect = new HashSet<>(); + aspect.add(ContentModel.ASPECT_TEMPORARY); + nodeDAO.addNodeAspects(nodeDAO.getNodePair(folder).getFirst(), aspect); + fileFolderService.delete(folder); return null; }, false, true); } 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 diff --git a/repository/src/test/java/org/alfresco/repo/solr/SOLRTrackingComponentUnitTest.java b/repository/src/test/java/org/alfresco/repo/solr/SOLRTrackingComponentUnitTest.java new file mode 100644 index 0000000000..316f5398f0 --- /dev/null +++ b/repository/src/test/java/org/alfresco/repo/solr/SOLRTrackingComponentUnitTest.java @@ -0,0 +1,115 @@ +/* + * #%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.solr; + +import static java.util.Collections.emptyMap; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import java.io.Serializable; +import java.util.Map; + +import org.alfresco.repo.domain.node.NodeDAO; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.namespace.QName; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +/** Unit tests for {@link org.alfresco.repo.solr.SOLRTrackingComponent}. */ +public class SOLRTrackingComponentUnitTest +{ + /** A pair of QNames for use in the tests. */ + private static final QName FIRST_PROPERTY = QName.createQName("the://first/property"); + private static final QName SECOND_PROPERTY = QName.createQName("the://second/property"); + /** A node id for use in the tests. */ + private static final long NODE_ID = 123L; + + /** The class under test. */ + @InjectMocks + private SOLRTrackingComponentImpl solrTrackingComponent; + @Mock + private NodeDAO nodeDAO; + @Mock + private DictionaryService dictionaryService; + + @Before + public void setUp() + { + initMocks(this); + } + + /** Check that properties of different types can be returned. */ + @Test + public void testGetProperties_indexedPropertiesPassedThrough() + { + Map propertiesFromDB = Map.of(FIRST_PROPERTY, "value1", SECOND_PROPERTY, 2); + when(nodeDAO.getNodeProperties(NODE_ID)).thenReturn(propertiesFromDB); + PropertyDefinition firstDefinition = mock(PropertyDefinition.class); + when(firstDefinition.isIndexed()).thenReturn(true); + when(dictionaryService.getProperty(FIRST_PROPERTY)).thenReturn(firstDefinition); + PropertyDefinition secondDefinition = mock(PropertyDefinition.class); + when(secondDefinition.isIndexed()).thenReturn(true); + when(dictionaryService.getProperty(SECOND_PROPERTY)).thenReturn(secondDefinition); + + Map properties = solrTrackingComponent.getProperties(NODE_ID); + + assertEquals("Expected both properties to be returned.", propertiesFromDB, properties); + } + + /** Check that a property is not indexed if it is not registered in the dictionary service. */ + @Test + public void testGetProperties_propertyWithoutModelIsNotIndexed() + { + Map propertiesFromDB = Map.of(FIRST_PROPERTY, "value1"); + when(nodeDAO.getNodeProperties(NODE_ID)).thenReturn(propertiesFromDB); + when(dictionaryService.getProperty(FIRST_PROPERTY)).thenReturn(null); + + Map properties = solrTrackingComponent.getProperties(NODE_ID); + + assertEquals("Expected residual property to be skipped.", emptyMap(), properties); + } + + /** Check that a property is not indexed if the model contains */ + @Test + public void testGetProperties_propertySkippedIfIndexFalseSet() + { + Map propertiesFromDB = Map.of(FIRST_PROPERTY, "value1"); + when(nodeDAO.getNodeProperties(NODE_ID)).thenReturn(propertiesFromDB); + PropertyDefinition firstDefinition = mock(PropertyDefinition.class); + when(firstDefinition.isIndexed()).thenReturn(false); + when(dictionaryService.getProperty(FIRST_PROPERTY)).thenReturn(firstDefinition); + + Map properties = solrTrackingComponent.getProperties(NODE_ID); + + assertEquals("Unexpected property when index enabled set to false.", emptyMap(), properties); + } +}