<%
if (descriptorService.getLicenseDescriptor() == null && transactionService.isReadOnly())
{
diff --git a/pom.xml b/pom.xml
index e5d7153fcb..afb283668d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
4.0.0alfresco-community-repo
- 23.3.0.63-SNAPSHOT
+ 23.3.0.86-SNAPSHOTpomAlfresco Community Repo Parent
@@ -51,54 +51,54 @@
7.0.15.23.05.23.0
- 5.1.3-A3
- 4.1.3-A2
+ 5.1.3
+ 4.1.37.00.0.27
- 1.9.20.1
+ 1.9.22.16.0.19
- 6.3.0
+ 6.3.13.5.32.15.2
- 4.0.2
+ 4.0.51.0.0-jakarta-19.01.78.1
- 5.4.0
- 3.24.2
+ 5.12.0
+ 3.26.320231013
- 2.9.0
- 2.14.0
- 2.10.1
- 32.1.2-jre
+ 2.12.0
+ 2.16.1
+ 2.11.0
+ 33.2.1-jre4.5.144.4.165.2.1
- 5.2.3
+ 5.2.53.1-HTTPCLIENT-12652.12.2
- 2.0.9
- 2.20.0
- 3.0.19
+ 2.0.13
+ 2.23.1
+ 3.0.222.9.27.7.105.2.53.5.0.Final
- 4.0.5
+ 4.6.04.1.110.Final5.18.3
- 1.26.0
- 4.2.0
+ 1.26.2
+ 4.2.14.1.3
- 1.0.67
+ 1.0.713.1.13.8.62.0.6.13.1.6
- 4.0.0
- 4.0.3
+ 4.0.2
+ 4.0.53.0.12.0.12.1.1
@@ -106,12 +106,12 @@
3.0.02.0.12.0.1
- 3.0.0
+ 3.1.01.2.0
- 2.1.2
- 1.1.4
+ 2.1.3
+ 1.1.62.9.0
- 2.5.0
+ 2.5.14.1.03.1.0-A123.2.0
@@ -124,7 +124,7 @@
82.7.45.0.1
- 5.3.2
+ 5.5.02.0.01.211.19
@@ -401,7 +401,7 @@
commons-loggingcommons-logging
- 1.2
+ 1.3.3commons-beanutils
@@ -442,7 +442,7 @@
commons-netcommons-net
- 3.9.0
+ 3.11.1org.apache.httpcomponents
@@ -462,7 +462,7 @@
org.apache.xmlbeansxmlbeans
- 5.2.0
+ 5.2.1org.json
@@ -621,7 +621,7 @@
org.apache.commonscommons-email
- 1.5
+ 1.6.0org.alfresco.aos-module
@@ -700,13 +700,13 @@
com.networkntjson-schema-validator
- 1.0.86
+ 1.5.0org.jsoupjsoup
- 1.16.1
+ 1.18.1
@@ -851,6 +851,17 @@
org.apache.commonscommons-dbcp2${dependency.commons-dbcp.version}
+
+
+
+ jakarta.transaction
+ jakarta.transaction-api
+
+ com.google.code.gson
@@ -936,7 +947,7 @@
org.projectlomboklombok
- 1.18.30
+ 1.18.34provided
@@ -975,7 +986,7 @@
org.apache.maven.pluginsmaven-compiler-plugin
- 3.11.0
+ 3.13.0-parameters
@@ -1005,7 +1016,7 @@
maven-jar-plugin
- 3.3.0
+ 3.4.2maven-war-plugin
@@ -1014,7 +1025,7 @@
org.apache.maven.pluginsmaven-javadoc-plugin
- 3.5.0
+ 3.7.0org.apache.maven.plugins
@@ -1024,11 +1035,11 @@
org.apache.maven.pluginsmaven-dependency-plugin
- 3.6.0
+ 3.7.1maven-assembly-plugin
- 3.6.0
+ 3.7.1org.alfresco.maven.plugin
@@ -1074,7 +1085,7 @@
org.codehaus.cargocargo-maven3-plugin
- 1.10.9
+ 1.10.14org.apache.maven.plugins
diff --git a/remote-api/pom.xml b/remote-api/pom.xml
index a551b5bd31..4d8a321ae5 100644
--- a/remote-api/pom.xml
+++ b/remote-api/pom.xml
@@ -7,7 +7,7 @@
org.alfrescoalfresco-community-repo
- 23.3.0.63-SNAPSHOT
+ 23.3.0.86-SNAPSHOT
@@ -143,7 +143,7 @@
org.eclipse.jettyjetty-webapp
- 11.0.16
+ 11.0.22test
diff --git a/remote-api/src/main/java/org/alfresco/rest/api/impl/AuditImpl.java b/remote-api/src/main/java/org/alfresco/rest/api/impl/AuditImpl.java
index cf44a92f9c..d2259e3c6c 100644
--- a/remote-api/src/main/java/org/alfresco/rest/api/impl/AuditImpl.java
+++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/AuditImpl.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Remote API
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -909,16 +909,14 @@ public class AuditImpl implements Audit
public int getAuditEntriesCountByAppAndProperties(AuditService.AuditApplication auditApplication, AuditEntryQueryWalker propertyWalker)
{
- final String applicationName = auditApplication.getKey().substring(1);
-
AuditQueryParameters parameters = new AuditQueryParameters();
- parameters.setApplicationName(applicationName);
+ parameters.setApplicationName(auditApplication.getName());
parameters.setFromTime(propertyWalker.getFromTime());
parameters.setToTime(propertyWalker.getToTime());
parameters.setFromId(propertyWalker.getFromId());
parameters.setToId(propertyWalker.getToId());
parameters.setUser(propertyWalker.getCreatedByUser());
- return auditService.getAuditEntriesCountByAppAndProperties(applicationName, parameters);
+ return auditService.getAuditEntriesCountByAppAndProperties(parameters);
}
}
diff --git a/remote-api/src/main/java/org/alfresco/rest/api/impl/PeopleImpl.java b/remote-api/src/main/java/org/alfresco/rest/api/impl/PeopleImpl.java
index 706e5238dd..d789a58d4e 100644
--- a/remote-api/src/main/java/org/alfresco/rest/api/impl/PeopleImpl.java
+++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/PeopleImpl.java
@@ -125,7 +125,7 @@ public class PeopleImpl implements People
protected ResetPasswordService resetPasswordService;
protected UserRegistrySynchronizer userRegistrySynchronizer;
protected Renditions renditions;
-
+ private Boolean allowImmutableEnabledUpdate;
private final static Map sort_params_to_qnames;
static
@@ -202,6 +202,11 @@ public class PeopleImpl implements People
this.userRegistrySynchronizer = userRegistrySynchronizer;
}
+ public void setAllowImmutableEnabledUpdate(Boolean allowImmutableEnabledUpdate)
+ {
+ this.allowImmutableEnabledUpdate = allowImmutableEnabledUpdate;
+ }
+
/**
* Validate, perform -me- substitution and canonicalize the person ID.
*
@@ -708,16 +713,26 @@ public class PeopleImpl implements People
// if requested, update password
updatePassword(isAdmin, personIdToUpdate, person);
- if (person.isEnabled() != null)
+ Set immutableProperties = userRegistrySynchronizer.getPersonMappedProperties(personIdToUpdate);
+
+ Boolean isEnabled = person.isEnabled();
+ if (isEnabled != null)
{
if (isAdminAuthority(personIdToUpdate))
{
throw new PermissionDeniedException("Admin authority cannot be disabled.");
}
- // note: if current user is not an admin then permission denied exception is thrown
- MutableAuthenticationService mutableAuthenticationService = (MutableAuthenticationService) authenticationService;
- mutableAuthenticationService.setAuthenticationEnabled(personIdToUpdate, person.isEnabled());
+ if (allowImmutableEnabledStatusUpdate(personIdToUpdate, isAdmin, immutableProperties))
+ {
+ LOGGER.info("User " + personIdToUpdate + " is immutable but enabled status will be set to: " + isEnabled);
+ }
+ else
+ {
+ // note: if current user is not an admin then permission denied exception is thrown
+ MutableAuthenticationService mutableAuthenticationService = (MutableAuthenticationService) authenticationService;
+ mutableAuthenticationService.setAuthenticationEnabled(personIdToUpdate, person.isEnabled());
+ }
}
NodeRef personNodeRef = personService.getPerson(personIdToUpdate, false);
@@ -742,9 +757,7 @@ public class PeopleImpl implements People
properties.putAll(nodes.mapToNodeProperties(customProps));
}
- // MNT-21150 LDAP synced attributes can be changed using REST API
- Set immutableProperties = userRegistrySynchronizer.getPersonMappedProperties(personIdToUpdate);
-
+ // MNT-21150 LDAP synced attributes can't be changed using REST API
immutableProperties.forEach(immutableProperty -> {
if (properties.containsKey(immutableProperty))
{
@@ -768,6 +781,28 @@ public class PeopleImpl implements People
return getPerson(personId);
}
+ private boolean allowImmutableEnabledStatusUpdate(String userId, boolean isAdmin, Set immutableProperties)
+ {
+ if (allowImmutableEnabledUpdate)
+ {
+ boolean containLdapUserAccountStatus = false;
+ QName propertyNameToCheck = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "userAccountStatusProperty");
+
+ for (QName immutableProperty : immutableProperties)
+ {
+ if (immutableProperty.equals(propertyNameToCheck))
+ {
+ containLdapUserAccountStatus = true;
+ break;
+ }
+ }
+
+ return isAdmin && !containLdapUserAccountStatus && !isMutableAuthority(userId);
+ }
+
+ return false;
+ }
+
private boolean checkCurrentUserOrAdmin(String personId)
{
boolean isAdmin = isAdminAuthority();
diff --git a/remote-api/src/main/resources/alfresco/public-rest-context.xml b/remote-api/src/main/resources/alfresco/public-rest-context.xml
index 8a094f000a..dddc92113d 100644
--- a/remote-api/src/main/resources/alfresco/public-rest-context.xml
+++ b/remote-api/src/main/resources/alfresco/public-rest-context.xml
@@ -764,6 +764,7 @@
+
diff --git a/repository/pom.xml b/repository/pom.xml
index 1290166374..0de9b0aac4 100644
--- a/repository/pom.xml
+++ b/repository/pom.xml
@@ -7,7 +7,7 @@
org.alfrescoalfresco-community-repo
- 23.3.0.63-SNAPSHOT
+ 23.3.0.86-SNAPSHOT
@@ -94,7 +94,7 @@
org.apache.commonscommons-lang3
- 3.13.0
+ 3.14.0commons-codec
@@ -120,7 +120,7 @@
commons-validatorcommons-validator
- 1.7
+ 1.9.0org.json
@@ -133,7 +133,7 @@
com.ibm.icuicu4j
- 73.2
+ 75.1com.googlecode.json-simple
@@ -273,7 +273,7 @@
com.sun.xml.fastinfosetFastInfoset
- 2.1.0
+ 2.1.1org.htmlparser
@@ -402,7 +402,7 @@
org.mybatismybatis-spring
- 3.0.2
+ 3.0.3
@@ -839,7 +839,7 @@
org.codehaus.mojoaspectj-maven-plugin
- 1.14.0
+ 1.15.0
diff --git a/repository/src/main/java/org/alfresco/ibatis/IdsEntity.java b/repository/src/main/java/org/alfresco/ibatis/IdsEntity.java
index 8178745189..96a49a4f07 100644
--- a/repository/src/main/java/org/alfresco/ibatis/IdsEntity.java
+++ b/repository/src/main/java/org/alfresco/ibatis/IdsEntity.java
@@ -41,6 +41,8 @@ public class IdsEntity
private Long idFour;
private List ids;
private boolean ordered;
+ private Integer maxResults;
+
public Long getIdOne()
{
return idOne;
@@ -89,4 +91,12 @@ public class IdsEntity
{
this.ordered = ordered;
}
+ public int getMaxResults()
+ {
+ return maxResults;
+ }
+ public void setMaxResults(Integer maxResults)
+ {
+ this.maxResults = maxResults;
+ }
}
diff --git a/repository/src/main/java/org/alfresco/repo/audit/AuditComponent.java b/repository/src/main/java/org/alfresco/repo/audit/AuditComponent.java
index 821c0c4759..29955432a7 100644
--- a/repository/src/main/java/org/alfresco/repo/audit/AuditComponent.java
+++ b/repository/src/main/java/org/alfresco/repo/audit/AuditComponent.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -276,11 +276,10 @@ public interface AuditComponent
/**
* Issue an audit query to retrieve count of records for a given application and properties
*
- * @param applicationName the name of the application
* @param parameters audit parameters provided by the where clause on the ReST API
* @return a map containing min/max and the associated value
*/
- default int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
+ default int getAuditEntriesCountByAppAndProperties(AuditQueryParameters parameters)
{
return -1;
}
diff --git a/repository/src/main/java/org/alfresco/repo/audit/AuditComponentImpl.java b/repository/src/main/java/org/alfresco/repo/audit/AuditComponentImpl.java
index 38fbd5ff69..98479db3af 100644
--- a/repository/src/main/java/org/alfresco/repo/audit/AuditComponentImpl.java
+++ b/repository/src/main/java/org/alfresco/repo/audit/AuditComponentImpl.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -956,10 +956,8 @@ public class AuditComponentImpl implements AuditComponent
return auditDAO.getAuditEntriesCountByApp(applicationId);
}
- @Override public int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
+ @Override public int getAuditEntriesCountByAppAndProperties(AuditQueryParameters parameters)
{
- org.alfresco.repo.domain.audit.AuditQueryParameters dbParameters = new org.alfresco.repo.domain.audit.AuditQueryParameters();
-
- return auditDAO.getAuditEntriesCountByAppAndProperties(applicationName, parameters);
+ return auditDAO.getAuditEntriesCountByAppAndProperties(parameters);
}
-}
+}
\ No newline at end of file
diff --git a/repository/src/main/java/org/alfresco/repo/audit/AuditServiceImpl.java b/repository/src/main/java/org/alfresco/repo/audit/AuditServiceImpl.java
index 7c92ec8e3f..4824914e51 100644
--- a/repository/src/main/java/org/alfresco/repo/audit/AuditServiceImpl.java
+++ b/repository/src/main/java/org/alfresco/repo/audit/AuditServiceImpl.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -190,8 +190,8 @@ public class AuditServiceImpl implements AuditService
/**
* {@inheritDoc}
*/
- @Override public int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
+ @Override public int getAuditEntriesCountByAppAndProperties(AuditQueryParameters parameters)
{
- return auditComponent.getAuditEntriesCountByAppAndProperties(applicationName, parameters);
+ return auditComponent.getAuditEntriesCountByAppAndProperties(parameters);
}
}
\ No newline at end of file
diff --git a/repository/src/main/java/org/alfresco/repo/domain/CrcHelper.java b/repository/src/main/java/org/alfresco/repo/domain/CrcHelper.java
index 8c71789809..d3cdb157b6 100644
--- a/repository/src/main/java/org/alfresco/repo/domain/CrcHelper.java
+++ b/repository/src/main/java/org/alfresco/repo/domain/CrcHelper.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 - 2024 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
package org.alfresco.repo.domain;
@@ -102,21 +102,22 @@ public class CrcHelper
{
throw new RuntimeException("UTF-8 encoding is not supported");
}
- // Get the short value (case-sensitive or not)
+ // Crc Value will change based on the case-sensitive, So we need to get the short value based on case-sensitive
String valueShort = null;
- int valueLen = valueLowerCase.length();
+ String currentValue = caseSensitive ? value : valueLowerCase;
+ int valueLen = currentValue.length();
if (valueLen < dataLength)
{
- valueShort = valueLowerCase;
+ valueShort = currentValue;
}
else if (useCharsFromStart)
{
- valueShort = valueLowerCase.substring(0, dataLength - 1);
+ valueShort = currentValue.substring(0, dataLength - 1);
}
else
{
- valueShort = valueLowerCase.substring(valueLen - dataLength);
+ valueShort = currentValue.substring(valueLen - dataLength);
}
return new Pair(valueShort, valueCrc);
}
-}
+}
\ No newline at end of file
diff --git a/repository/src/main/java/org/alfresco/repo/domain/audit/AuditDAO.java b/repository/src/main/java/org/alfresco/repo/domain/audit/AuditDAO.java
index f8c61d0a8c..cac517706e 100644
--- a/repository/src/main/java/org/alfresco/repo/domain/audit/AuditDAO.java
+++ b/repository/src/main/java/org/alfresco/repo/domain/audit/AuditDAO.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -248,11 +248,10 @@ public interface AuditDAO
/**
* Issue an audit query to retrieve count of records for a given application and properties
*
- * @param applicationName name of the application to be queried
* @param parameters audit parameters provided by the where clause on the ReST API
* @return a map containing min/max and the associated value
*/
- default int getAuditEntriesCountByAppAndProperties(String applicationName, org.alfresco.service.cmr.audit.AuditQueryParameters parameters)
+ default int getAuditEntriesCountByAppAndProperties(org.alfresco.service.cmr.audit.AuditQueryParameters parameters)
{
return -1;
}
diff --git a/repository/src/main/java/org/alfresco/repo/domain/audit/ibatis/AuditDAOImpl.java b/repository/src/main/java/org/alfresco/repo/domain/audit/ibatis/AuditDAOImpl.java
index 89f602dba5..12468dbf8e 100644
--- a/repository/src/main/java/org/alfresco/repo/domain/audit/ibatis/AuditDAOImpl.java
+++ b/repository/src/main/java/org/alfresco/repo/domain/audit/ibatis/AuditDAOImpl.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -237,7 +237,7 @@ public class AuditDAOImpl extends AbstractAuditDAOImpl
}
@Override
- public int getAuditEntriesCountByAppAndProperties(String applicationName, org.alfresco.service.cmr.audit.AuditQueryParameters parameters)
+ public int getAuditEntriesCountByAppAndProperties(org.alfresco.service.cmr.audit.AuditQueryParameters parameters)
{
AuditQueryParameters dbParameters = convertFromRestAuditQueryParameters(parameters);
diff --git a/repository/src/main/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java b/repository/src/main/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java
index 1095e7448d..9b223788c5 100644
--- a/repository/src/main/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java
+++ b/repository/src/main/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java
@@ -2785,6 +2785,23 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
selectNodesWithAspects(qnameIds, minNodeId, maxNodeId, ordered, resultsCallback);
}
+ @Override
+ public void getNodesWithAspects(
+ Set aspectQNames,
+ Long minNodeId, Long maxNodeId, boolean ordered,
+ int maxResults,
+ NodeRefQueryCallback resultsCallback)
+ {
+ Set qnameIdsSet = qnameDAO.convertQNamesToIds(aspectQNames, false);
+ if (qnameIdsSet.isEmpty())
+ {
+ // No point running a query
+ return;
+ }
+ List qnameIds = new ArrayList<>(qnameIdsSet);
+ selectNodesWithAspects(qnameIds, minNodeId, maxNodeId, ordered, maxResults, resultsCallback);
+ }
+
/**
* @return Returns a writable copy of the cached aspects set
*/
@@ -4960,6 +4977,10 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
List qnameIds,
Long minNodeId, Long maxNodeId, boolean ordered,
NodeRefQueryCallback resultsCallback);
+ protected abstract void selectNodesWithAspects(
+ List qnameIds,
+ Long minNodeId, Long maxNodeId, boolean ordered, int maxResults,
+ NodeRefQueryCallback resultsCallback);
protected abstract Long insertNodeAssoc(Long sourceNodeId, Long targetNodeId, Long assocTypeQNameId, int assocIndex);
protected abstract int updateNodeAssoc(Long id, int assocIndex);
protected abstract int deleteNodeAssoc(Long sourceNodeId, Long targetNodeId, Long assocTypeQNameId);
@@ -5088,4 +5109,5 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
protected abstract Long selectMinTxInNodeIdRange(Long fromNodeId, Long toNodeId);
protected abstract Long selectMaxTxInNodeIdRange(Long fromNodeId, Long toNodeId);
protected abstract Long selectNextTxCommitTime(Long fromCommitTime);
+
}
diff --git a/repository/src/main/java/org/alfresco/repo/domain/node/NodeDAO.java b/repository/src/main/java/org/alfresco/repo/domain/node/NodeDAO.java
index 3c1bb2675d..6ef10852ab 100644
--- a/repository/src/main/java/org/alfresco/repo/domain/node/NodeDAO.java
+++ b/repository/src/main/java/org/alfresco/repo/domain/node/NodeDAO.java
@@ -427,6 +427,22 @@ public interface NodeDAO extends NodeBulkLoader
Long minNodeId, Long maxNodeId, boolean ordered,
NodeRefQueryCallback resultsCallback);
+ /**
+ * Get nodes with aspects between the given ranges, ordering the results optionally
+ * and limit the result set
+ *
+ * @param aspectQNames the aspects that must be on the nodes
+ * @param minNodeId the minimum node ID (inclusive)
+ * @param maxNodeId the maximum node ID (exclusive)
+ * @param ordered if the results are to be ordered by nodeID
+ * @param maxResults limit query to maxResults
+ * @param resultsCallback callback to process results
+ */
+ public void getNodesWithAspects(
+ Set aspectQNames,
+ Long minNodeId, Long maxNodeId, boolean ordered, int maxResults,
+ NodeRefQueryCallback resultsCallback);
+
/*
* Node Assocs
*/
diff --git a/repository/src/main/java/org/alfresco/repo/domain/node/ibatis/NodeDAOImpl.java b/repository/src/main/java/org/alfresco/repo/domain/node/ibatis/NodeDAOImpl.java
index a387385de0..1357975404 100644
--- a/repository/src/main/java/org/alfresco/repo/domain/node/ibatis/NodeDAOImpl.java
+++ b/repository/src/main/java/org/alfresco/repo/domain/node/ibatis/NodeDAOImpl.java
@@ -116,6 +116,7 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
private static final String SELECT_NODE_MAX_ID = "alfresco.node.select_NodeMaxId";
private static final String SELECT_NODE_INTERVAL_BY_TYPE = "alfresco.node.select_MinMaxNodeIdForNodeType";
private static final String SELECT_NODES_WITH_ASPECT_IDS = "alfresco.node.select_NodesWithAspectIds";
+ private static final String SELECT_NODES_WITH_ASPECT_IDS_LIMITED = "alfresco.node.select_NodesWithAspectIds_Limited";
private static final String INSERT_NODE_ASSOC = "alfresco.node.insert.insert_NodeAssoc";
private static final String UPDATE_NODE_ASSOC = "alfresco.node.update_NodeAssoc";
private static final String DELETE_NODE_ASSOC = "alfresco.node.delete_NodeAssoc";
@@ -799,6 +800,33 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
template.select(SELECT_NODES_WITH_ASPECT_IDS, parameters, resultHandler);
}
+ @Override
+ protected void selectNodesWithAspects(
+ List qnameIds,
+ Long minNodeId, Long maxNodeId, boolean ordered,
+ final int maxResults,
+ final NodeRefQueryCallback resultsCallback)
+ {
+ @SuppressWarnings("rawtypes")
+ ResultHandler resultHandler = new ResultHandler()
+ {
+ public void handleResult(ResultContext context)
+ {
+ NodeEntity entity = (NodeEntity) context.getResultObject();
+ Pair nodePair = new Pair<>(entity.getId(), entity.getNodeRef());
+ resultsCallback.handle(nodePair);
+ }
+ };
+
+ IdsEntity parameters = new IdsEntity();
+ parameters.setIdOne(minNodeId);
+ parameters.setIdTwo(maxNodeId);
+ parameters.setIds(qnameIds);
+ parameters.setOrdered(ordered);
+ parameters.setMaxResults(maxResults);
+ template.select(SELECT_NODES_WITH_ASPECT_IDS_LIMITED, parameters, resultHandler);
+ }
+
@Override
protected Long insertNodeAssoc(Long sourceNodeId, Long targetNodeId, Long assocTypeQNameId, int assocIndex)
{
diff --git a/repository/src/main/java/org/alfresco/repo/domain/permissions/FixedAclUpdater.java b/repository/src/main/java/org/alfresco/repo/domain/permissions/FixedAclUpdater.java
index f313c25dd8..b9da62f6e3 100644
--- a/repository/src/main/java/org/alfresco/repo/domain/permissions/FixedAclUpdater.java
+++ b/repository/src/main/java/org/alfresco/repo/domain/permissions/FixedAclUpdater.java
@@ -85,8 +85,11 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
public static final String FIXED_ACL_ASYNC_REQUIRED_KEY = "FIXED_ACL_ASYNC_REQUIRED";
public static final String FIXED_ACL_ASYNC_CALL_KEY = "FIXED_ACL_ASYNC_CALL";
+
protected static final QName LOCK_Q_NAME = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "FixedAclUpdater");
+ private static final int DEFAULT_MAX_ITEMS = Integer.MAX_VALUE;
+
/** A set of listeners to receive callback events whenever permissions are updated by this class. */
private static Set listeners = Sets.newConcurrentHashSet();
@@ -101,6 +104,8 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
private int maxItemBatchSize = 100;
private int numThreads = 4;
private boolean forceSharedACL = false;
+ private int maxItems = DEFAULT_MAX_ITEMS;
+ private boolean orderNodes = true;
private ClassPolicyDelegate onInheritPermissionsDisabledDelegate;
private PolicyComponent policyComponent;
@@ -147,12 +152,22 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
this.forceSharedACL = forceSharedACL;
}
+ public void setOrderNodes(boolean orderNodes)
+ {
+ this.orderNodes = orderNodes;
+ }
+
public void setLockTimeToLive(long lockTimeToLive)
{
this.lockTimeToLive = lockTimeToLive;
this.lockRefreshTime = lockTimeToLive / 2;
}
+ public void setMaxItems(int maxItems)
+ {
+ this.maxItems = maxItems > 0 ? maxItems : DEFAULT_MAX_ITEMS;
+ }
+
public void setPolicyComponent(PolicyComponent policyComponent)
{
this.policyComponent = policyComponent;
@@ -209,7 +224,7 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
public List execute() throws Throwable
{
getNodesCallback.init();
- nodeDAO.getNodesWithAspects(aspects, getNodesCallback.getMinNodeId(), null, true, getNodesCallback);
+ nodeDAO.getNodesWithAspects(aspects, getNodesCallback.getMinNodeId(), null, orderNodes, maxItemBatchSize, getNodesCallback);
getNodesCallback.done();
return getNodesCallback.getNodes();
@@ -220,6 +235,11 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
int countNodesWithAspects()
{
+ if (maxItems < DEFAULT_MAX_ITEMS) {
+ log.info("Job limited to process a maximum of " + maxItems + " Pending Acls");
+ return maxItems;
+ }
+
final CountNodesWithAspectCallback countNodesCallback = new CountNodesWithAspectCallback();
int count = transactionService.getRetryingTransactionHelper()
.doInTransaction(new RetryingTransactionCallback()
@@ -238,6 +258,9 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
private class AclWorkProvider implements BatchProcessWorkProvider
{
private GetNodesWithAspects getNodesWithAspects;
+ private long estimatedUpdatedItems;
+ private long execTime;
+ private long execBatches;
AclWorkProvider()
{
@@ -259,8 +282,37 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
@Override
public Collection getNextWork()
{
- return getNodesWithAspects.getNodesWithAspects();
+ if(estimatedUpdatedItems >= maxItems)
+ {
+ log.info("Reached max items to process. Nodes Processed: " + estimatedUpdatedItems + "/" + maxItems);
+ return Collections.emptyList();
+ }
+
+ long initTime = System.currentTimeMillis();
+ Collection batchNodes = getNodesWithAspects.getNodesWithAspects();
+ long endTime = System.currentTimeMillis();
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("Query for batch executed in " + (endTime-initTime) + " ms");
+ }
+
+ if (!batchNodes.isEmpty())
+ {
+ // Increment estimatedUpdatedItems with the expected number of nodes to process
+ estimatedUpdatedItems += batchNodes.size();
+ execTime+=endTime-initTime;
+ execBatches++;
+ }
+
+ return batchNodes;
}
+
+ public double getAverageQueryExecutionTime()
+ {
+ return execBatches > 0 ? execTime/execBatches : 0;
+ }
+
}
protected class AclWorker implements BatchProcessor.BatchProcessWorker
@@ -451,6 +503,7 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
try
{
+ log.info("Running FixedAclUpdater. Max Items: " + maxItems + ", Impose order: " + orderNodes);
lockToken = jobLockService.getLock(LOCK_Q_NAME, lockTimeToLive, 0, 1);
jobLockService.refreshLock(lockToken, LOCK_Q_NAME, lockRefreshTime, jobLockRefreshCallback);
@@ -460,6 +513,7 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
transactionService.getRetryingTransactionHelper(), provider, numThreads, maxItemBatchSize, applicationContext,
log, 100);
int count = bp.process(worker, true);
+ log.info("FixedAclUpdater updated " + count + ". Average query time " + provider.getAverageQueryExecutionTime() + " ms");
return count;
}
catch (LockAcquisitionException e)
diff --git a/repository/src/main/java/org/alfresco/repo/domain/propval/PropertyStringValueEntity.java b/repository/src/main/java/org/alfresco/repo/domain/propval/PropertyStringValueEntity.java
index dbc3090298..56e188fbf6 100644
--- a/repository/src/main/java/org/alfresco/repo/domain/propval/PropertyStringValueEntity.java
+++ b/repository/src/main/java/org/alfresco/repo/domain/propval/PropertyStringValueEntity.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 - 2024 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
package org.alfresco.repo.domain.propval;
import org.alfresco.repo.domain.CrcHelper;
@@ -44,6 +44,7 @@ public class PropertyStringValueEntity
private String stringValue;
private String stringEndLower;
private Long stringCrc;
+ private String stringLower;
public PropertyStringValueEntity()
{
@@ -115,6 +116,9 @@ public class PropertyStringValueEntity
Pair crcPair = CrcHelper.getStringCrcPair(value, 16, false, true);
stringEndLower = crcPair.getFirst();
stringCrc = crcPair.getSecond();
+ // Calculate the crc value with case-insensitive
+ Pair crcPairWithCaseInSensitive = CrcHelper.getStringCrcPair(value, 16, false, false);
+ stringLower = crcPairWithCaseInSensitive.getFirst();
}
public Long getId()
@@ -156,4 +160,14 @@ public class PropertyStringValueEntity
{
this.stringCrc = stringCrc;
}
+
+ public String getStringLower()
+ {
+ return stringLower;
+ }
+
+ public void setStringLower(String stringLower)
+ {
+ this.stringLower = stringLower;
+ }
}
diff --git a/repository/src/main/java/org/alfresco/repo/event2/DirectEventSender.java b/repository/src/main/java/org/alfresco/repo/event2/DirectEventSender.java
index f2af8666ea..3f3805be09 100644
--- a/repository/src/main/java/org/alfresco/repo/event2/DirectEventSender.java
+++ b/repository/src/main/java/org/alfresco/repo/event2/DirectEventSender.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2023 Alfresco Software Limited
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -36,18 +36,13 @@ import org.springframework.beans.factory.InitializingBean;
/**
* Sends a message to a destination in the current thread.
*/
-public class DirectEventSender implements EventSender, InitializingBean
+public class DirectEventSender implements EventSender
{
- protected Event2MessageProducer event2MessageProducer;
+ protected final Event2MessageProducer event2MessageProducer;
- @Override
- public void afterPropertiesSet()
+ public DirectEventSender(Event2MessageProducer event2MessageProducer)
{
PropertyCheck.mandatory(this, "event2MessageProducer", event2MessageProducer);
- }
-
- public void setEvent2MessageProducer(Event2MessageProducer event2MessageProducer)
- {
this.event2MessageProducer = event2MessageProducer;
}
diff --git a/repository/src/main/java/org/alfresco/repo/event2/EnqueuingEventSender.java b/repository/src/main/java/org/alfresco/repo/event2/EnqueuingEventSender.java
index 08a425f218..7615cba81f 100644
--- a/repository/src/main/java/org/alfresco/repo/event2/EnqueuingEventSender.java
+++ b/repository/src/main/java/org/alfresco/repo/event2/EnqueuingEventSender.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2023 Alfresco Software Limited
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -46,28 +46,18 @@ public class EnqueuingEventSender extends DirectEventSender
{
protected static final Log LOGGER = LogFactory.getLog(EnqueuingEventSender.class);
- protected Executor enqueueThreadPoolExecutor;
- protected Executor dequeueThreadPoolExecutor;
+ protected final Executor enqueueThreadPoolExecutor;
+ protected final Executor dequeueThreadPoolExecutor;
protected BlockingQueue queue = new LinkedBlockingQueue<>();
protected Runnable listener = createListener();
- @Override
- public void afterPropertiesSet()
+ public EnqueuingEventSender(Event2MessageProducer event2MessageProducer, Executor enqueueThreadPoolExecutor, Executor dequeueThreadPoolExecutor)
{
- super.afterPropertiesSet();
+ super(event2MessageProducer);
PropertyCheck.mandatory(this, "enqueueThreadPoolExecutor", enqueueThreadPoolExecutor);
PropertyCheck.mandatory(this, "dequeueThreadPoolExecutor", dequeueThreadPoolExecutor);
- }
-
- public void setEnqueueThreadPoolExecutor(Executor enqueueThreadPoolExecutor)
- {
this.enqueueThreadPoolExecutor = enqueueThreadPoolExecutor;
- }
-
- public void setDequeueThreadPoolExecutor(Executor dequeueThreadPoolExecutor)
- {
this.dequeueThreadPoolExecutor = dequeueThreadPoolExecutor;
- dequeueThreadPoolExecutor.execute(listener);
}
/**
@@ -91,6 +81,12 @@ public class EnqueuingEventSender extends DirectEventSender
});
}
+ @Override
+ public void initialize()
+ {
+ dequeueThreadPoolExecutor.execute(listener);
+ }
+
/**
* Create listener task in charge of dequeuing and sending events ready to be sent.
* @return The task in charge of dequeuing and sending events ready to be sent.
diff --git a/repository/src/main/java/org/alfresco/repo/event2/EventSender.java b/repository/src/main/java/org/alfresco/repo/event2/EventSender.java
index 798c66f111..e23aa1692d 100644
--- a/repository/src/main/java/org/alfresco/repo/event2/EventSender.java
+++ b/repository/src/main/java/org/alfresco/repo/event2/EventSender.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2023 Alfresco Software Limited
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -40,4 +40,13 @@ public interface EventSender
* @param eventProducer - callback function that creates an event
*/
void accept(Callable>> eventProducer);
+
+ /**
+ * It's called right after event sender instantiation (see {@link org.alfresco.repo.event2.EventSenderFactoryBean}).
+ * It might be used to initialize the sender implementation.
+ */
+ default void initialize()
+ {
+ //no initialization by default
+ }
}
diff --git a/repository/src/main/java/org/alfresco/repo/event2/EventSenderFactoryBean.java b/repository/src/main/java/org/alfresco/repo/event2/EventSenderFactoryBean.java
new file mode 100644
index 0000000000..2f0f216e9a
--- /dev/null
+++ b/repository/src/main/java/org/alfresco/repo/event2/EventSenderFactoryBean.java
@@ -0,0 +1,158 @@
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.repo.event2;
+
+import jakarta.annotation.Nonnull;
+import org.alfresco.util.PropertyCheck;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.beans.factory.config.AbstractFactoryBean;
+import org.springframework.core.env.PropertyResolver;
+
+import java.util.Optional;
+import java.util.concurrent.Executor;
+
+public class EventSenderFactoryBean extends AbstractFactoryBean
+{
+ static final String LEGACY_SKIP_QUEUE_PROPERTY = "repo.event2.queue.skip";
+ static final String EVENT_SEND_STRATEGY_PROPERTY = "repo.event2.send.strategy";
+ private static final String DIRECT_EVENT_SENDER_NAME = "direct";
+ private static final String ASYNC_EVENT_SENDER_NAME = "async";
+
+ private final PropertyResolver propertyResolver;
+ private final Event2MessageProducer event2MessageProducer;
+ private final Executor enqueueThreadPoolExecutor;
+ private final Executor dequeueThreadPoolExecutor;
+
+ private String configuredSenderName;
+ private boolean legacySkipQueueConfig;
+
+ public EventSenderFactoryBean(@Autowired PropertyResolver propertyResolver, Event2MessageProducer event2MessageProducer,
+ Executor enqueueThreadPoolExecutor, Executor dequeueThreadPoolExecutor)
+ {
+ super();
+ PropertyCheck.mandatory(this, "propertyResolver", propertyResolver);
+ PropertyCheck.mandatory(this, "event2MessageProducer", event2MessageProducer);
+ PropertyCheck.mandatory(this, "enqueueThreadPoolExecutor", enqueueThreadPoolExecutor);
+ PropertyCheck.mandatory(this, "dequeueThreadPoolExecutor", dequeueThreadPoolExecutor);
+ this.propertyResolver = propertyResolver;
+ this.event2MessageProducer = event2MessageProducer;
+ this.enqueueThreadPoolExecutor = enqueueThreadPoolExecutor;
+ this.dequeueThreadPoolExecutor = dequeueThreadPoolExecutor;
+ }
+
+ @Value("${" + LEGACY_SKIP_QUEUE_PROPERTY + "}")
+ public void setLegacySkipQueueConfig(boolean legacySkipQueueConfig)
+ {
+ this.legacySkipQueueConfig = legacySkipQueueConfig;
+ }
+
+ @Value("${" + EVENT_SEND_STRATEGY_PROPERTY + "}")
+ public void setConfiguredSenderName(String configuredSenderName)
+ {
+ this.configuredSenderName = configuredSenderName;
+ }
+
+ @Override
+ public Class> getObjectType()
+ {
+ return EventSender.class;
+ }
+
+ @Override
+ @Nonnull
+ protected EventSender createInstance() throws Exception
+ {
+ EventSender sender = instantiateConfiguredSender();
+
+ sender.initialize();
+
+ return sender;
+ }
+
+ private EventSender instantiateConfiguredSender()
+ {
+ if (isSenderNameConfigured())
+ {
+ return instantiateSender(getConfiguredSenderName());
+ }
+ return isLegacySkipQueueConfigured() ? instantiateDirectSender() : instantiateAsyncSender();
+ }
+
+ protected EventSender instantiateSender(String senderName)
+ {
+ if (DIRECT_EVENT_SENDER_NAME.equalsIgnoreCase(senderName))
+ {
+ return instantiateDirectSender();
+ }
+
+ if (ASYNC_EVENT_SENDER_NAME.equalsIgnoreCase(senderName))
+ {
+ return instantiateAsyncSender();
+ }
+
+ throw new IllegalStateException("Failed to instantiate sender: " + senderName);
+ }
+
+ private DirectEventSender instantiateDirectSender()
+ {
+ return new DirectEventSender(getEvent2MessageProducer());
+ }
+
+ private EnqueuingEventSender instantiateAsyncSender()
+ {
+ return new EnqueuingEventSender(getEvent2MessageProducer(), enqueueThreadPoolExecutor, dequeueThreadPoolExecutor);
+ }
+
+ private boolean isSenderNameConfigured()
+ {
+ return !Optional.ofNullable(getConfiguredSenderName())
+ .map(String::isBlank)
+ .orElse(true);
+ }
+
+ private boolean isLegacySkipQueueConfigured()
+ {
+ return Optional.ofNullable(resolveProperty(LEGACY_SKIP_QUEUE_PROPERTY, Boolean.class))
+ .orElse(legacySkipQueueConfig);
+ }
+
+ private String getConfiguredSenderName()
+ {
+ return Optional.ofNullable(resolveProperty(EVENT_SEND_STRATEGY_PROPERTY, String.class))
+ .orElse(configuredSenderName);
+ }
+
+ protected T resolveProperty(String key, Class targetType)
+ {
+ return propertyResolver.getProperty(key, targetType);
+ }
+
+ protected Event2MessageProducer getEvent2MessageProducer()
+ {
+ return event2MessageProducer;
+ }
+}
diff --git a/repository/src/main/java/org/alfresco/repo/quickshare/QuickShareServiceImpl.java b/repository/src/main/java/org/alfresco/repo/quickshare/QuickShareServiceImpl.java
index 2102a2bf93..9757bc622a 100644
--- a/repository/src/main/java/org/alfresco/repo/quickshare/QuickShareServiceImpl.java
+++ b/repository/src/main/java/org/alfresco/repo/quickshare/QuickShareServiceImpl.java
@@ -36,7 +36,10 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import java.util.UUID;
+import com.fasterxml.uuid.Generators;
+import com.fasterxml.uuid.impl.UUIDUtil;
import org.alfresco.sync.events.types.ActivityEvent;
import org.alfresco.sync.events.types.Event;
import org.alfresco.model.ContentModel;
@@ -108,8 +111,6 @@ import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.joda.time.PeriodType;
-import org.safehaus.uuid.UUID;
-import org.safehaus.uuid.UUIDGenerator;
/**
* QuickShare Service implementation.
@@ -435,8 +436,8 @@ public class QuickShareServiceImpl implements QuickShareService,
// If it is retura dto built from the existing properties.
if (! nodeService.getAspects(nodeRef).contains(QuickShareModel.ASPECT_QSHARE))
{
- UUID uuid = UUIDGenerator.getInstance().generateRandomBasedUUID();
- sharedId = Base64.encodeBase64URLSafeString(uuid.toByteArray()); // => 22 chars (eg. q3bEKPeDQvmJYgt4hJxOjw)
+ UUID uuid = Generators.randomBasedGenerator().generate();
+ sharedId = Base64.encodeBase64URLSafeString(UUIDUtil.asByteArray(uuid)); // => 22 chars (eg. q3bEKPeDQvmJYgt4hJxOjw)
final Map props = new HashMap(2);
props.put(QuickShareModel.PROP_QSHARE_SHAREDID, sharedId);
@@ -1246,7 +1247,7 @@ public class QuickShareServiceImpl implements QuickShareService,
}
// Create the expiry action
- final QuickShareLinkExpiryAction expiryAction = new QuickShareLinkExpiryActionImpl(java.util.UUID.randomUUID().toString(), sharedId,
+ final QuickShareLinkExpiryAction expiryAction = new QuickShareLinkExpiryActionImpl(UUID.randomUUID().toString(), sharedId,
"QuickShare link expiry action");
// Create the persisted schedule
final ScheduledPersistedAction schedule = scheduledPersistedActionService.createSchedule(expiryAction);
diff --git a/repository/src/main/java/org/alfresco/repo/security/authentication/AuthenticationContextImpl.java b/repository/src/main/java/org/alfresco/repo/security/authentication/AuthenticationContextImpl.java
index c9c4a84bb5..39b57d155f 100644
--- a/repository/src/main/java/org/alfresco/repo/security/authentication/AuthenticationContextImpl.java
+++ b/repository/src/main/java/org/alfresco/repo/security/authentication/AuthenticationContextImpl.java
@@ -36,7 +36,11 @@ import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import net.sf.acegisecurity.providers.dao.User;
+import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.tenant.TenantService;
+import org.alfresco.service.cmr.security.AuthenticationService;
+import org.alfresco.service.cmr.security.MutableAuthenticationService;
+import org.alfresco.service.cmr.security.PersonService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -49,12 +53,30 @@ public class AuthenticationContextImpl implements AuthenticationContext
private final Log logger = LogFactory.getLog(getClass());
private TenantService tenantService;
+ private PersonService personService;
+ private AuthenticationService authenticationService;
+ private Boolean allowImmutableEnabledUpdate;
public void setTenantService(TenantService tenantService)
{
this.tenantService = tenantService;
}
+ public void setPersonService(PersonService personService)
+ {
+ this.personService = personService;
+ }
+
+ public void setAuthenticationService(AuthenticationService authenticationService)
+ {
+ this.authenticationService = authenticationService;
+ }
+
+ public void setAllowImmutableEnabledUpdate(Boolean allowImmutableEnabledUpdate)
+ {
+ this.allowImmutableEnabledUpdate = allowImmutableEnabledUpdate;
+ }
+
/**
* Explicitly set the given validated user details to be authenticated.
*
@@ -70,7 +92,7 @@ public class AuthenticationContextImpl implements AuthenticationContext
{
// Apply the same validation that ACEGI would have to the user details - we may be going through a 'back
// door'.
- if (!ud.isEnabled())
+ if (isDisabled(userId, ud))
{
throw new DisabledException("User is disabled");
}
@@ -114,6 +136,43 @@ public class AuthenticationContextImpl implements AuthenticationContext
}
}
+ private boolean isDisabled(String userId, UserDetails ud)
+ {
+ boolean isDisabled = !ud.isEnabled();
+ boolean isSystemUser = isSystemUserName(userId);
+
+ if (allowImmutableEnabledUpdate && !isSystemUser)
+ {
+ try
+ {
+ boolean isImmutable = isImmutableAuthority(userId);
+ boolean isPersonEnabled = personService.isEnabled(userId);
+ isDisabled = isDisabled || (isImmutable && !isPersonEnabled);
+ }
+ catch (Exception e)
+ {
+ if (logger.isWarnEnabled())
+ {
+ logger.warn("Failed to determine if person is enabled: " + userId + ", using user details status: " + isDisabled);
+ }
+ }
+ }
+
+ return isDisabled;
+ }
+
+ private boolean isImmutableAuthority(String authorityName)
+ {
+ return AuthenticationUtil.runAsSystem(new RunAsWork()
+ {
+ @Override public Boolean doWork() throws Exception
+ {
+ MutableAuthenticationService mutableAuthenticationService = (MutableAuthenticationService) authenticationService;
+ return !mutableAuthenticationService.isAuthenticationMutable(authorityName);
+ }
+ });
+ }
+
public Authentication setSystemUserAsCurrentUser()
{
return setSystemUserAsCurrentUser(TenantService.DEFAULT_DOMAIN);
diff --git a/repository/src/main/java/org/alfresco/repo/security/person/SplitPersonCleanupBootstrapBean.java b/repository/src/main/java/org/alfresco/repo/security/person/SplitPersonCleanupBootstrapBean.java
index 777ef52afb..c87679cc2e 100644
--- a/repository/src/main/java/org/alfresco/repo/security/person/SplitPersonCleanupBootstrapBean.java
+++ b/repository/src/main/java/org/alfresco/repo/security/person/SplitPersonCleanupBootstrapBean.java
@@ -1,32 +1,33 @@
-/*
- * #%L
- * Alfresco Repository
- * %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
- * %%
- * This file is part of the Alfresco software.
- * If the software was purchased under a paid Alfresco license, the terms of
- * the paid license agreement will prevail. Otherwise, the software is
- * provided under the following open source license terms:
- *
- * Alfresco is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Alfresco is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Alfresco. If not, see .
- * #L%
- */
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
package org.alfresco.repo.security.person;
import java.util.Set;
import java.util.TreeSet;
+import java.util.UUID;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.batch.BatchProcessor;
@@ -41,7 +42,6 @@ import org.springframework.extensions.surf.util.AbstractLifecycleBean;
import org.alfresco.util.GUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.safehaus.uuid.UUID;
import org.springframework.context.ApplicationEvent;
/**
@@ -168,7 +168,7 @@ public class SplitPersonCleanupBootstrapBean extends AbstractLifecycleBean
try
{
@SuppressWarnings("unused")
- UUID id = new UUID(guidString);
+ UUID id = UUID.fromString(guidString);
// We have a valid guid.
return true;
}
@@ -188,7 +188,7 @@ public class SplitPersonCleanupBootstrapBean extends AbstractLifecycleBean
try
{
@SuppressWarnings("unused")
- UUID id = new UUID(guidString);
+ UUID id = UUID.fromString(guidString);
// We have a valid guid.
return true;
}
diff --git a/repository/src/main/java/org/alfresco/service/cmr/audit/AuditService.java b/repository/src/main/java/org/alfresco/service/cmr/audit/AuditService.java
index 4a7bcd0091..bbb2f886ac 100644
--- a/repository/src/main/java/org/alfresco/service/cmr/audit/AuditService.java
+++ b/repository/src/main/java/org/alfresco/service/cmr/audit/AuditService.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -256,11 +256,10 @@ public interface AuditService
/**
* Issue an audit query to retrieve min / max audit record id for a given application and properties
*
- * @param applicationName the name of the application
* @param parameters audit parameters provided by the where clause on the ReST API
* @return a map containing min/max and the associated value
*/
- default int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
+ default int getAuditEntriesCountByAppAndProperties(AuditQueryParameters parameters)
{
return -1;
}
diff --git a/repository/src/main/resources/alfresco/authentication-services-context.xml b/repository/src/main/resources/alfresco/authentication-services-context.xml
index 1925c02d35..7d4f6d9666 100644
--- a/repository/src/main/resources/alfresco/authentication-services-context.xml
+++ b/repository/src/main/resources/alfresco/authentication-services-context.xml
@@ -274,6 +274,15 @@
+
+
+
+
+
+
+
+ ${allow.immutable.user.enabled.status.update}
+
diff --git a/repository/src/main/resources/alfresco/events2-context.xml b/repository/src/main/resources/alfresco/events2-context.xml
index 0fb6f3ef43..aa5d78d1ba 100644
--- a/repository/src/main/resources/alfresco/events2-context.xml
+++ b/repository/src/main/resources/alfresco/events2-context.xml
@@ -41,7 +41,7 @@
-
+
@@ -55,18 +55,17 @@
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
diff --git a/repository/src/main/resources/alfresco/ibatis/org.alfresco.repo.domain.dialect.Dialect/node-common-SqlMap.xml b/repository/src/main/resources/alfresco/ibatis/org.alfresco.repo.domain.dialect.Dialect/node-common-SqlMap.xml
index 1bd8e4844d..9c1a6a0bd8 100644
--- a/repository/src/main/resources/alfresco/ibatis/org.alfresco.repo.domain.dialect.Dialect/node-common-SqlMap.xml
+++ b/repository/src/main/resources/alfresco/ibatis/org.alfresco.repo.domain.dialect.Dialect/node-common-SqlMap.xml
@@ -782,6 +782,25 @@
order by node.id ASC
+
+
select
diff --git a/repository/src/main/resources/alfresco/public-services-security-context.xml b/repository/src/main/resources/alfresco/public-services-security-context.xml
index 8f8769493e..6b7806df0a 100644
--- a/repository/src/main/resources/alfresco/public-services-security-context.xml
+++ b/repository/src/main/resources/alfresco/public-services-security-context.xml
@@ -121,6 +121,8 @@
+
+
diff --git a/repository/src/main/resources/alfresco/repository.properties b/repository/src/main/resources/alfresco/repository.properties
index 91f678dee9..a429143f61 100644
--- a/repository/src/main/resources/alfresco/repository.properties
+++ b/repository/src/main/resources/alfresco/repository.properties
@@ -435,6 +435,9 @@ repo.remote.endpoint=/service
# persisted.
create.missing.people=${server.transaction.allow-writes}
+# Allow an immutable user to have its enabled status changed
+allow.immutable.user.enabled.status.update=false
+
# Create home folders (unless disabled, see next property) as people are created (true) or create them lazily (false)
home.folder.creation.eager=true
# Disable home folder creation - if true then home folders are not created (neither eagerly nor lazily)
@@ -1104,7 +1107,11 @@ system.fixedACLsUpdater.numThreads=4
# fixedACLsUpdater - Force shared ACL to propagate through children even if there is an unexpected ACL
system.fixedACLsUpdater.forceSharedACL=false
# fixedACLsUpdater cron expression - fire at midnight every day
-system.fixedACLsUpdater.cronExpression=0 0 0 * * ?
+system.fixedACLsUpdater.cronExpression=0 0 0 * * ?
+# fixedACLsUpdater - maximum number of pending ACLs to process overall
+system.fixedACLsUpdater.maxItems=-1
+# fixedACLsUpdater - Impose the order by in the query. If false, it may not process all the results but should do the queries faster
+system.fixedACLsUpdater.orderNodes=true
cmis.disable.hidden.leading.period.files=false
@@ -1229,7 +1236,10 @@ repo.event2.filter.childAssocTypes=rn:rendition
repo.event2.filter.users=
# Topic name
repo.event2.topic.endpoint=amqp:topic:alfresco.repo.event2
+# Specifies the strategy for sending the events
+repo.event2.send.strategy=
# Specifies if messages should be enqueued in in-memory queue or sent directly to the topic
+# Deprecated. Please use repo.event2.send.strategy
repo.event2.queue.skip=false
#repo.event2.topic.endpoint=amqp:topic:VirtualTopic.alfresco.repo.event2
# Thread pool for async enqueue of repo events
diff --git a/repository/src/test/java/org/alfresco/AppContext06TestSuite.java b/repository/src/test/java/org/alfresco/AppContext06TestSuite.java
index 49bede2566..1c30218387 100644
--- a/repository/src/test/java/org/alfresco/AppContext06TestSuite.java
+++ b/repository/src/test/java/org/alfresco/AppContext06TestSuite.java
@@ -44,11 +44,6 @@ import org.junit.runners.Suite;
@RunWith(Categories.class)
@Categories.ExcludeCategory({DBTests.class, NonBuildTests.class})
@Suite.SuiteClasses({
- // Requires a running ActiveMQ
- org.alfresco.repo.rawevents.EventBehaviourTest.class,
- org.alfresco.repo.rawevents.TransactionAwareEventProducerTest.class,
- org.alfresco.repo.event2.RepoEvent2ITSuite.class,
-
// Requires running transformers
org.alfresco.transform.registry.LocalTransformServiceRegistryConfigTest.class,
org.alfresco.repo.rendition2.RenditionService2IntegrationTest.class,
@@ -71,7 +66,12 @@ import org.junit.runners.Suite;
org.alfresco.repo.blog.BlogServiceImplTest.class,
org.alfresco.repo.action.scheduled.ScheduledPersistedActionServiceTest.class,
- org.alfresco.repo.rendition2.RenditionDefinitionTest.class
+ org.alfresco.repo.rendition2.RenditionDefinitionTest.class,
+
+ // Requires a running ActiveMQ
+ org.alfresco.repo.rawevents.EventBehaviourTest.class,
+ org.alfresco.repo.rawevents.TransactionAwareEventProducerTest.class,
+ org.alfresco.repo.event2.RepoEvent2ITSuite.class,
})
public class AppContext06TestSuite
{
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 ad0dabfaf3..f66c3003a5 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
@@ -104,9 +104,9 @@ public class FixedAclUpdaterTest
private ContentService contentService;
private AuthorityService authorityService;
private static final long MAX_TRANSACTION_TIME_DEFAULT = 10;
+ private static final int LARGE_TRANSACTION_TIME = 86_400_000;
private static final int[] filesPerLevelMoreFolders = { 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
private static final int[] filesPerLevelMoreFiles = { 5, 100 };
- private long maxTransactionTime;
private static HashMap> errors;
private static String TEST_GROUP_NAME = "FixedACLUpdaterTest";
private static String TEST_GROUP_NAME_FULL = PermissionService.GROUP_PREFIX + TEST_GROUP_NAME;
@@ -134,8 +134,11 @@ public class FixedAclUpdaterTest
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
homeFolderNodeRef = repository.getCompanyHome();
- maxTransactionTime = MAX_TRANSACTION_TIME_DEFAULT;
- setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, maxTransactionTime);
+ setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, MAX_TRANSACTION_TIME_DEFAULT);
+
+ fixedAclUpdater.setForceSharedACL(false);
+ fixedAclUpdater.setMaxItems(-1);
+ fixedAclUpdater.setOrderNodes(true);
}
@After
@@ -155,8 +158,7 @@ public class FixedAclUpdaterTest
try
{
- maxTransactionTime = 86400000;
- setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, maxTransactionTime);
+ setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, LARGE_TRANSACTION_TIME);
setPermissionsOnTree(folderRef, false, false);
aclComparator.compareACLs();
@@ -164,6 +166,7 @@ public class FixedAclUpdaterTest
}
finally
{
+ setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, MAX_TRANSACTION_TIME_DEFAULT);
deleteNodes(folderRef);
}
}
@@ -344,8 +347,7 @@ public class FixedAclUpdaterTest
try
{
- maxTransactionTime = 86400000;
- setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, maxTransactionTime);
+ setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, LARGE_TRANSACTION_TIME);
// Set permissions on target folder
txnHelper.doInTransaction((RetryingTransactionCallback) () -> {
@@ -386,6 +388,7 @@ public class FixedAclUpdaterTest
}
finally
{
+ setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, MAX_TRANSACTION_TIME_DEFAULT);
deleteNodes(originalRef);
deleteNodes(targetRefBase);
}
@@ -1438,6 +1441,79 @@ public class FixedAclUpdaterTest
}
}
+ /*
+ * Test with maxItems limit
+ */
+ @Test
+ @RetryAtMost(3)
+ public void testWithLimits()
+ {
+ NodeRef folderRef = createFolderHierarchyInRootForFileTests("testWithLimitsFolder");
+
+ try
+ {
+ int maxItems = 200;
+ setPermissionsOnTree(folderRef, true, true);
+
+ // Get the current amount of pending ACls
+ int initialPendingAcls = getNodesCountWithPendingFixedAclAspect();
+
+ // We need at least maxItems+1 pending ACLs
+ while (initialPendingAcls <= maxItems && initialPendingAcls > 0)
+ {
+ // Trigger the job a single round each time to create new pendings until we have enough
+ triggerFixedACLJob(false,true,maxItems,1);
+ initialPendingAcls = getNodesCountWithPendingFixedAclAspect();
+ }
+
+ assertTrue("We don't have enough pending acls to test", initialPendingAcls > 0);
+
+ // Increase transaction time to not create new pending ACLs
+ setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, LARGE_TRANSACTION_TIME);
+
+ // Trigger job in single round without timeout
+ triggerFixedACLJob(false,true,maxItems,1);
+
+ int finalPendingAcls = getNodesCountWithPendingFixedAclAspect();
+
+ assertTrue("Processed ACLs should not have exceeded 200", (initialPendingAcls - finalPendingAcls) <= maxItems);
+ }
+ finally
+ {
+ setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, MAX_TRANSACTION_TIME_DEFAULT);
+ deleteNodes(folderRef);
+ }
+ }
+
+ /*
+ * Test without imposing the order by
+ */
+ @Test
+ @RetryAtMost(3)
+ public void testUnordered()
+ {
+ NodeRef folderRef = createFolderHierarchyInRootForFileTests("testWithLimitsFolder");
+
+ try
+ {
+ setPermissionsOnTree(folderRef, true, true);
+
+ int initialPendingAcls = getNodesCountWithPendingFixedAclAspect();
+ assertTrue("We don't have enough pending acls to test", initialPendingAcls > 0);
+
+ triggerFixedACLJob(false,true,-1,30);
+
+ int finalPendingAcls = getNodesCountWithPendingFixedAclAspect();
+
+ assertEquals("Not all ACls were processed",0, finalPendingAcls);
+ }
+ finally
+ {
+ setFixedAclMaxTransactionTime(permissionsDaoComponent, homeFolderNodeRef, MAX_TRANSACTION_TIME_DEFAULT);
+ deleteNodes(folderRef);
+ }
+ }
+
private Long getChild(Long parentId)
{
List children = fileFolderService.list(nodeDAO.getNodePair(parentId).getSecond());
@@ -1601,13 +1677,18 @@ public class FixedAclUpdaterTest
private void triggerFixedACLJob()
{
- triggerFixedACLJob(false);
+ // Trigger job 30 times max to process all nodes
+ triggerFixedACLJob(false, true, -1, 30);
}
private void triggerFixedACLJob(boolean forceSharedACL)
+ {
+ triggerFixedACLJob(forceSharedACL, true, -1, 30);
+ }
+
+ private void triggerFixedACLJob(boolean forceSharedACL, boolean orderNodes, int maxItems, int rounds)
{
LOG.debug("Fixing ACL");
- final int rounds = 30;
final int enoughZeros = 3;
int numberOfConsecutiveZeros = 0;
@@ -1615,6 +1696,8 @@ public class FixedAclUpdaterTest
{
int count = txnHelper.doInTransaction(() -> {
fixedAclUpdater.setForceSharedACL(forceSharedACL);
+ fixedAclUpdater.setMaxItems(maxItems);
+ fixedAclUpdater.setOrderNodes(orderNodes);
return fixedAclUpdater.execute();
}, false, true);
numberOfConsecutiveZeros = count == 0 ? numberOfConsecutiveZeros + 1 : 0;
diff --git a/repository/src/test/java/org/alfresco/repo/event2/AbstractContextAwareRepoEvent.java b/repository/src/test/java/org/alfresco/repo/event2/AbstractContextAwareRepoEvent.java
index d7af0a25e7..6edf471720 100644
--- a/repository/src/test/java/org/alfresco/repo/event2/AbstractContextAwareRepoEvent.java
+++ b/repository/src/test/java/org/alfresco/repo/event2/AbstractContextAwareRepoEvent.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2023 Alfresco Software Limited
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -71,14 +71,14 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.beans.factory.annotation.Value;
import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.test.context.TestPropertySource;
/**
* @author Iulian Aftene
*/
-
+@TestPropertySource(properties = {"repo.event2.queue.skip=false"})
public abstract class AbstractContextAwareRepoEvent extends BaseSpringTest
{
protected static final boolean DEBUG = false;
@@ -123,9 +123,6 @@ public abstract class AbstractContextAwareRepoEvent extends BaseSpringTest
@Autowired
private NamespaceDAO namespaceDAO;
- @Value("${repo.event2.queue.skip}")
- protected boolean skipEventQueue;
-
protected NodeRef rootNodeRef;
@BeforeClass
diff --git a/repository/src/test/java/org/alfresco/repo/event2/DirectEventGeneratorTest.java b/repository/src/test/java/org/alfresco/repo/event2/DirectEventGeneratorTest.java
index 1298ded98d..94349cfbbc 100644
--- a/repository/src/test/java/org/alfresco/repo/event2/DirectEventGeneratorTest.java
+++ b/repository/src/test/java/org/alfresco/repo/event2/DirectEventGeneratorTest.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2023 Alfresco Software Limited
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -25,78 +25,32 @@
*/
package org.alfresco.repo.event2;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.junit.BeforeClass;
import org.junit.Test;
-import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.config.BeanPostProcessor;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.test.annotation.DirtiesContext;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.ContextHierarchy;
+import org.springframework.test.context.TestPropertySource;
-@ContextHierarchy({
- // Context hierarchy inherits context config from parent classes and extends it with TestConfig from this class
- @ContextConfiguration(classes = DirectEventGeneratorTest.TestConfig.class)
-})
-@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
+import java.util.Collection;
+
+@TestPropertySource(properties = {"repo.event2.queue.skip=true"})
public class DirectEventGeneratorTest extends EventGeneratorTest
{
@Autowired
- private InstantiatedBeansRegistry instantiatedBeansRegistry;
-
+ private EventSender eventSender;
@Autowired
- private EventSender directEventSender;
-
- @BeforeClass
- public static void beforeClass()
- {
- System.setProperty("repo.event2.queue.skip", "true");
- }
+ private Collection allEventSenderBeans;
@Test
- public void testIfEnqueuingEventSenderIsNotInstantiated()
+ public void testIfOnlyRequiredEventSenderIsInstantiated()
{
- final Set instantiatedBeans = this.instantiatedBeansRegistry.getBeans();
-
- assertTrue(skipEventQueue);
- assertFalse(instantiatedBeans.contains("enqueuingEventSender"));
+ assertEquals(1, allEventSenderBeans.size());
+ assertTrue(allEventSenderBeans.contains(eventSender));
}
+
@Test
public void testIfDirectSenderIsSetInEventGenerator()
{
- assertTrue(skipEventQueue);
- assertEquals(directEventSender, eventGenerator.getEventSender());
- }
-
- @Configuration
- public static class TestConfig
- {
- @Bean
- public BeanPostProcessor instantiatedBeansRegistry()
- {
- return new InstantiatedBeansRegistry();
- }
- }
-
- protected static class InstantiatedBeansRegistry implements BeanPostProcessor
- {
- private final Set registeredBeans = new HashSet<>();
-
- @Override
- public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException
- {
- registeredBeans.add(beanName);
- return bean;
- }
-
- public Set getBeans() {
- return registeredBeans;
- }
+ assertEquals(DirectEventSender.class, eventSender.getClass());
+ assertEquals(eventSender, eventGenerator.getEventSender());
}
}
diff --git a/repository/src/test/java/org/alfresco/repo/event2/EnqueuingEventGeneratorTest.java b/repository/src/test/java/org/alfresco/repo/event2/EnqueuingEventGeneratorTest.java
index 06e0643ec6..244f89ed23 100644
--- a/repository/src/test/java/org/alfresco/repo/event2/EnqueuingEventGeneratorTest.java
+++ b/repository/src/test/java/org/alfresco/repo/event2/EnqueuingEventGeneratorTest.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2023 Alfresco Software Limited
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -27,9 +27,9 @@ package org.alfresco.repo.event2;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.TestPropertySource;
-@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
+@TestPropertySource(properties = {"repo.event2.queue.skip=false"})
public class EnqueuingEventGeneratorTest extends EventGeneratorTest
{
@Autowired
@@ -38,7 +38,7 @@ public class EnqueuingEventGeneratorTest extends EventGeneratorTest
@Test
public void testIfEnqueuingSenderIsSetInEventGenerator()
{
- assertFalse(skipEventQueue);
+ assertEquals(EnqueuingEventSender.class, enqueuingEventSender.getClass());
assertEquals(enqueuingEventSender, eventGenerator.getEventSender());
}
}
diff --git a/repository/src/test/java/org/alfresco/repo/event2/EnqueuingEventSenderUnitTest.java b/repository/src/test/java/org/alfresco/repo/event2/EnqueuingEventSenderUnitTest.java
index ce8604f326..162c99b7dd 100644
--- a/repository/src/test/java/org/alfresco/repo/event2/EnqueuingEventSenderUnitTest.java
+++ b/repository/src/test/java/org/alfresco/repo/event2/EnqueuingEventSenderUnitTest.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2023 Alfresco Software Limited
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -65,15 +65,11 @@ public class EnqueuingEventSenderUnitTest
@Before
public void setup()
{
- eventSender = new EnqueuingEventSender();
-
- enqueuePool = newThreadPool();
- eventSender.setEnqueueThreadPoolExecutor(enqueuePool);
- dequeuePool = newThreadPool();
- eventSender.setDequeueThreadPoolExecutor(dequeuePool);
-
bus = mock(Event2MessageProducer.class);
- eventSender.setEvent2MessageProducer(bus);
+ enqueuePool = newThreadPool();
+ dequeuePool = newThreadPool();
+ eventSender = new EnqueuingEventSender(bus, enqueuePool, dequeuePool);
+ eventSender.initialize();
events = new HashMap<>();
diff --git a/repository/src/test/java/org/alfresco/repo/event2/EventGeneratorTest.java b/repository/src/test/java/org/alfresco/repo/event2/EventGeneratorTest.java
index 561cb77ae1..25c6f96cc2 100644
--- a/repository/src/test/java/org/alfresco/repo/event2/EventGeneratorTest.java
+++ b/repository/src/test/java/org/alfresco/repo/event2/EventGeneratorTest.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2023 Alfresco Software Limited
+ * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -49,7 +49,6 @@ import org.apache.activemq.command.ActiveMQTopic;
import org.awaitility.Awaitility;
import org.junit.After;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Test;
public abstract class EventGeneratorTest extends AbstractContextAwareRepoEvent
@@ -60,12 +59,6 @@ public abstract class EventGeneratorTest extends AbstractContextAwareRepoEvent
private ActiveMQConnection connection;
protected List> receivedEvents;
- @BeforeClass
- public static void beforeClass()
- {
- System.setProperty("repo.event2.queue.skip", "false");
- }
-
@Before
public void startupTopicListener() throws Exception
{
diff --git a/repository/src/test/java/org/alfresco/repo/quickshare/QuickShareServiceIntegrationTest.java b/repository/src/test/java/org/alfresco/repo/quickshare/QuickShareServiceIntegrationTest.java
index 1c50d23fd6..fbba0bdba2 100644
--- a/repository/src/test/java/org/alfresco/repo/quickshare/QuickShareServiceIntegrationTest.java
+++ b/repository/src/test/java/org/alfresco/repo/quickshare/QuickShareServiceIntegrationTest.java
@@ -37,7 +37,10 @@ import java.io.Serializable;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
+import java.util.UUID;
+import com.fasterxml.uuid.Generators;
+import com.fasterxml.uuid.impl.UUIDUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.model.QuickShareModel;
import org.alfresco.repo.model.Repository;
@@ -83,8 +86,6 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.RuleChain;
-import org.safehaus.uuid.UUID;
-import org.safehaus.uuid.UUIDGenerator;
import org.springframework.context.ApplicationContext;
/**
@@ -420,8 +421,8 @@ public class QuickShareServiceIntegrationTest
@Test(expected=InvalidSharedIdException.class) public void getMetadataFromShareIdWithInvalidId()
{
- UUID uuid = UUIDGenerator.getInstance().generateRandomBasedUUID();
- String sharedId = Base64.encodeBase64URLSafeString(uuid.toByteArray()); // => 22 chars (eg. q3bEKPeDQvmJYgt4hJxOjw)
+ UUID uuid = Generators.randomBasedGenerator().generate();
+ String sharedId = Base64.encodeBase64URLSafeString(UUIDUtil.asByteArray(uuid)); // => 22 chars (eg. q3bEKPeDQvmJYgt4hJxOjw)
Map metadata = quickShareService.getMetaData(sharedId);
}
@@ -884,7 +885,7 @@ public class QuickShareServiceIntegrationTest
{
// Create a private site
AuthenticationUtil.setFullyAuthenticatedUser(user1.getUsername());
- String randomUUID = UUIDGenerator.getInstance().generateRandomBasedUUID().toString();
+ String randomUUID = Generators.randomBasedGenerator().generate().toString();
String siteName = "testSite" + randomUUID;
siteService.createSite("site-dashboard", siteName, "Title for " + siteName,
"Description for " + siteName, SiteVisibility.PRIVATE);