diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml index e90acf725e..564b2f280a 100644 --- a/config/alfresco/bootstrap-context.xml +++ b/config/alfresco/bootstrap-context.xml @@ -462,6 +462,44 @@ + + + + + + + + + + + ${spaces.store} + + + + + + + + + + + + + + + + + + 50 + + + 50 + + + ${system.usages.enabled} + + + diff --git a/config/alfresco/scheduled-jobs-context.xml b/config/alfresco/scheduled-jobs-context.xml index 382c4054c3..b43a3e3615 100644 --- a/config/alfresco/scheduled-jobs-context.xml +++ b/config/alfresco/scheduled-jobs-context.xml @@ -277,44 +277,7 @@ 0 30 3 * * ? - - - - - - - - - - - ${spaces.store} - - - - - - - - - - - - - - - - - - 50 - - - 50 - - - ${system.usages.enabled} - - - + @@ -348,39 +311,6 @@ - - - - - - org.alfresco.repo.usage.UserUsageBootstrapJob - - - - - - - - - - - - - - - - - - - - 0 - - - 0 - - - - diff --git a/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml b/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml index da717f78c7..b73246e627 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml +++ b/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml @@ -437,32 +437,38 @@ assoc.id - + + + + + + + + + + + + + select - assoc.id, - assoc.typeQNameId, - assoc.qnameNamespaceId, - assoc.qnameLocalName, - assoc.childNodeName, - assoc.childNodeNameCrc, - assoc.isPrimary, - assoc.index, - child.id, - store.protocol, - store.identifier, - child.uuid + a.id, + a.type_qname_id, + a.qname_ns_id, + a.qname_localname, + a.child_node_name, + a.child_node_name_crc, + a.is_primary, + a.assoc_index, + n.id, + s.protocol, + s.identifier, + n.uuid from - org.alfresco.repo.domain.hibernate.ChildAssocImpl as assoc - join assoc.parent as parent - join assoc.child as child - join child.store as store - where - parent.id = :parentId and - assoc.typeQNameId in (:childAssocTypeQNameIds) - order by - assoc.index, - assoc.id - + (select * from alf_child_assoc a where parent_node_id = :parentId and type_qname_id in (:childAssocTypeQNameIds)) a + inner join alf_node n on a.child_node_id=n.id + inner join alf_store s on n.store_id=s.id + order by a.assoc_index, a.id + select @@ -720,11 +726,11 @@ alf_node n JOIN alf_store s ON (s.id = n.store_id AND n.type_qname_id = :personTypeQNameID) JOIN alf_node_properties p1 ON (p1.node_id = n.id AND p1.qname_id = :usernamePropQNameID) - LEFT JOIN alf_node_properties p2 ON (p2.node_id = n.id AND p2.qname_id = :sizeCurrentPropQNameID) + JOIN alf_node_properties p2 ON (p2.node_id = n.id AND p2.qname_id = :sizeCurrentPropQNameID) WHERE s.protocol = :storeProtocol AND s.identifier = :storeIdentifier AND - (p2.persisted_type_n IS NULL OR p2.persisted_type_n = 0) AND + p2.persisted_type_n = 0 AND p1.string_value != 'System' @@ -738,11 +744,11 @@ alf_node n JOIN alf_store s ON (s.id = n.store_id AND n.type_qname_id = :personTypeQNameID) JOIN alf_node_properties p1 ON (p1.node_id = n.id AND p1.qname_id = :usernamePropQNameID) - LEFT JOIN alf_node_properties p2 ON (p2.node_id = n.id AND p2.qname_id = :sizeCurrentPropQNameID) + JOIN alf_node_properties p2 ON (p2.node_id = n.id AND p2.qname_id = :sizeCurrentPropQNameID) WHERE s.protocol = :storeProtocol AND s.identifier = :storeIdentifier AND - (p2.persisted_type_n != 0 AND p2.persisted_type_n IS NOT NULL) AND + p2.persisted_type_n != 0 AND p1.string_value != 'System' diff --git a/source/java/org/alfresco/repo/domain/hibernate/Permission.hbm.xml b/source/java/org/alfresco/repo/domain/hibernate/Permission.hbm.xml index c168d7a2fa..a4d16c6d94 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/Permission.hbm.xml +++ b/source/java/org/alfresco/repo/domain/hibernate/Permission.hbm.xml @@ -412,6 +412,7 @@ JOIN alf_store s on s.id = n.store_id WHERE c.qname_localname = :userNameLowerCase AND + c.type_qname_id = :assocTypeQNameID AND p.qname_id = :qnamePropId AND n.type_qname_id = :qnameTypeId AND n.node_deleted = :False AND diff --git a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java index 807cb04e1b..4eec436bde 100644 --- a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java +++ b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java @@ -1456,65 +1456,136 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl Long nodeId = nodePair.getFirst(); final List results = new ArrayList(100); - - // if the type is the wildcard type, and the qname is not a search, then use a shortcut query - if (typeQNamePattern.equals(RegexQNamePattern.MATCH_ALL) && qnamePattern instanceof QName) + + if (qnamePattern instanceof QName) { - NodeDaoService.ChildAssocRefQueryCallback callback = new NodeDaoService.ChildAssocRefQueryCallback() + // Both explicit QNames + if (typeQNamePattern instanceof QName) { - public boolean handle( - Pair childAssocPair, - Pair parentNodePair, - Pair childNodePair) + NodeDaoService.ChildAssocRefQueryCallback callback = new NodeDaoService.ChildAssocRefQueryCallback() { - results.add(childAssocPair.getSecond()); - return false; - } - }; - // Get all child associations with the specific qualified name - nodeDaoService.getChildAssocs(nodeId, (QName)qnamePattern, callback); - } - else if (typeQNamePattern instanceof QName && qnamePattern instanceof QName) - { - NodeDaoService.ChildAssocRefQueryCallback callback = new NodeDaoService.ChildAssocRefQueryCallback() + public boolean handle(Pair childAssocPair, + Pair parentNodePair, Pair childNodePair) + { + results.add(childAssocPair.getSecond()); + return false; + } + }; + // Get all child associations with the specific qualified name + nodeDaoService.getChildAssocsByTypeQNameAndQName(nodeId, (QName) typeQNamePattern, + (QName) qnamePattern, callback); + } + // Type is explicit, local qname is pattern + else { - public boolean handle( - Pair childAssocPair, - Pair parentNodePair, - Pair childNodePair) + NodeDaoService.ChildAssocRefQueryCallback callback; + if (typeQNamePattern.equals(RegexQNamePattern.MATCH_ALL)) { - results.add(childAssocPair.getSecond()); - return false; + callback = new NodeDaoService.ChildAssocRefQueryCallback() + { + public boolean handle(Pair childAssocPair, + Pair parentNodePair, Pair childNodePair) + { + results.add(childAssocPair.getSecond()); + return false; + } + }; } - }; - // Get all child associations with the specific qualified name - nodeDaoService.getChildAssocsByTypeQNameAndQName( - nodeId, - (QName)typeQNamePattern, - (QName)qnamePattern, - callback); + else + { + callback = new NodeDaoService.ChildAssocRefQueryCallback() + { + public boolean handle(Pair childAssocPair, + Pair parentNodePair, Pair childNodePair) + { + ChildAssociationRef assocRef = childAssocPair.getSecond(); + QName assocTypeQName = assocRef.getTypeQName(); + if (!typeQNamePattern.isMatch(assocTypeQName)) + { + // No match + return false; + } + results.add(assocRef); + return false; + } + }; + + } + + // Get all child associations with the specific qualified name + nodeDaoService.getChildAssocs(nodeId, (QName) qnamePattern, callback); + } } else { - NodeDaoService.ChildAssocRefQueryCallback callback = new NodeDaoService.ChildAssocRefQueryCallback() + // Local qname is pattern, type name is explicit + if (typeQNamePattern instanceof QName) { - public boolean handle(Pair childAssocPair, Pair parentNodePair, Pair childNodePair) + NodeDaoService.ChildAssocRefQueryCallback callback; + // if the type is the wildcard type, and the qname is not a search, then use a shortcut query + if (qnamePattern.equals(RegexQNamePattern.MATCH_ALL)) { - ChildAssociationRef assocRef = childAssocPair.getSecond(); - QName assocTypeQName = assocRef.getTypeQName(); - QName assocQName = assocRef.getQName(); - if (!qnamePattern.isMatch(assocQName) || !typeQNamePattern.isMatch(assocTypeQName)) + callback = new NodeDaoService.ChildAssocRefQueryCallback() { - // No match + public boolean handle(Pair childAssocPair, + Pair parentNodePair, Pair childNodePair) + { + results.add(childAssocPair.getSecond()); + return false; + } + }; + } + else + { + + callback = new NodeDaoService.ChildAssocRefQueryCallback() + { + public boolean handle(Pair childAssocPair, + Pair parentNodePair, Pair childNodePair) + { + ChildAssociationRef assocRef = childAssocPair.getSecond(); + QName assocQName = assocRef.getQName(); + if (!qnamePattern.isMatch(assocQName)) + { + // No match + return false; + } + results.add(assocRef); + return false; + } + }; + } + + // Get all child associations with the specific type qualified name + nodeDaoService.getChildAssocsByTypeQNames(nodeId, Collections.singletonList((QName) typeQNamePattern), + callback); + + } + // Local qname is pattern, type name is pattern + else + { + NodeDaoService.ChildAssocRefQueryCallback callback = new NodeDaoService.ChildAssocRefQueryCallback() + { + public boolean handle(Pair childAssocPair, + Pair parentNodePair, Pair childNodePair) + { + ChildAssociationRef assocRef = childAssocPair.getSecond(); + QName assocTypeQName = assocRef.getTypeQName(); + QName assocQName = assocRef.getQName(); + if (!qnamePattern.isMatch(assocQName) || !typeQNamePattern.isMatch(assocTypeQName)) + { + // No match + return false; + } + results.add(assocRef); return false; } - results.add(assocRef); - return false; - } - }; - // Get all child associations - nodeDaoService.getChildAssocs(nodeId, callback, false); + }; + // Get all child associations + nodeDaoService.getChildAssocs(nodeId, callback, false); + } } + // sort the results List orderedList = reorderChildAssocs(results); // done diff --git a/source/java/org/alfresco/repo/security/authority/AuthorityDAOImpl.java b/source/java/org/alfresco/repo/security/authority/AuthorityDAOImpl.java index d31ee01cf4..295910fc00 100644 --- a/source/java/org/alfresco/repo/security/authority/AuthorityDAOImpl.java +++ b/source/java/org/alfresco/repo/security/authority/AuthorityDAOImpl.java @@ -47,6 +47,7 @@ import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.security.AuthorityType; +import org.alfresco.service.cmr.security.NoSuchPersonException; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.namespace.NamespacePrefixResolver; import org.alfresco.service.namespace.QName; @@ -219,7 +220,8 @@ public class AuthorityDAOImpl implements AuthorityDAO NodeRef container = getAuthorityContainer(); if (container != null) { - for (ChildAssociationRef childRef : nodeService.getChildAssocs(container)) + for (ChildAssociationRef childRef : nodeService.getChildAssocs(container, + ContentModel.ASSOC_CHILDREN, RegexQNamePattern.MATCH_ALL)) { addAuthorityNameIfMatches(authorities, childRef.getQName().getLocalName(), type, pattern); } @@ -234,9 +236,11 @@ public class AuthorityDAOImpl implements AuthorityDAO { if (container != null) { - for (ChildAssociationRef childRef : nodeService.getChildAssocs(container)) + for (ChildAssociationRef childRef : nodeService.getChildAssocs(container, + ContentModel.ASSOC_IN_ZONE, RegexQNamePattern.MATCH_ALL)) { - addAuthorityNameIfMatches(authorities, childRef.getQName().getLocalName(), type, pattern); + addAuthorityNameIfMatches(authorities, childRef.getQName().getLocalName(), type, + pattern); } } } @@ -375,35 +379,30 @@ public class AuthorityDAOImpl implements AuthorityDAO private NodeRef getAuthorityOrNull(String name) { - if (AuthorityType.getAuthorityType(name).equals(AuthorityType.USER)) + try { - if (!personService.personExists(name)) + if (AuthorityType.getAuthorityType(name).equals(AuthorityType.USER)) { - return null; + return personService.getPerson(name, false); } - return personService.getPerson(name); - } - else if (AuthorityType.getAuthorityType(name).equals(AuthorityType.GUEST)) - { - if (!personService.personExists(name)) + else if (AuthorityType.getAuthorityType(name).equals(AuthorityType.GUEST)) { - return null; + return personService.getPerson(name, false); } - return personService.getPerson(name); - } - else if (AuthorityType.getAuthorityType(name).equals(AuthorityType.ADMIN)) - { - if (!personService.personExists(name)) + else if (AuthorityType.getAuthorityType(name).equals(AuthorityType.ADMIN)) { - return null; + return personService.getPerson(name, false); + } + else + { + List results = nodeService.getChildAssocs(getAuthorityContainer(), + ContentModel.ASSOC_CHILDREN, QName.createQName("cm", name, namespacePrefixResolver)); + return results.isEmpty() ? null : results.get(0).getChildRef(); } - return personService.getPerson(name); } - else + catch (NoSuchPersonException e) { - List results = nodeService.getChildAssocs(getAuthorityContainer(), ContentModel.ASSOC_CHILDREN, QName.createQName("cm", name, - namespacePrefixResolver)); - return results.isEmpty() ? null : results.get(0).getChildRef(); + return null; } } @@ -575,7 +574,7 @@ public class AuthorityDAOImpl implements AuthorityDAO NodeRef zoneRef = getZone(zoneName); if (zoneRef != null) { - for (ChildAssociationRef childRef : nodeService.getChildAssocs(zoneRef)) + for (ChildAssociationRef childRef : nodeService.getChildAssocs(zoneRef, ContentModel.ASSOC_IN_ZONE, RegexQNamePattern.MATCH_ALL)) { addAuthorityNameIfMatches(authorities, childRef.getQName().getLocalName(), type, null); } diff --git a/source/java/org/alfresco/repo/security/authority/AuthorityServiceImpl.java b/source/java/org/alfresco/repo/security/authority/AuthorityServiceImpl.java index 301800d3a4..c50be96ffb 100644 --- a/source/java/org/alfresco/repo/security/authority/AuthorityServiceImpl.java +++ b/source/java/org/alfresco/repo/security/authority/AuthorityServiceImpl.java @@ -338,13 +338,6 @@ public class AuthorityServiceImpl implements AuthorityService, InitializingBean public void addAuthority(String parentName, String childName) { - if (AuthorityType.getAuthorityType(childName).equals(AuthorityType.USER)) - { - if(!personService.personExists(childName)) - { - throw new AuthorityException("The person "+childName+" does not exist and can not be added to a group"); - } - } authorityDAO.addAuthority(parentName, childName); } diff --git a/source/java/org/alfresco/repo/security/person/PersonDaoImpl.java b/source/java/org/alfresco/repo/security/person/PersonDaoImpl.java index 91a29da9ed..4d50f13cfc 100644 --- a/source/java/org/alfresco/repo/security/person/PersonDaoImpl.java +++ b/source/java/org/alfresco/repo/security/person/PersonDaoImpl.java @@ -57,6 +57,7 @@ public class PersonDaoImpl extends HibernateDaoSupport implements PersonDao private static final String QUERY_PERSON_GET_ALL_PEOPLE = "person.getAllPeople"; private QNameDAO qnameDAO; + private Long assocTypeQNameID; private Long qNamePropId; private Long qNameTypeId; private LocaleDAO localeDAO; @@ -79,6 +80,7 @@ public class PersonDaoImpl extends HibernateDaoSupport implements PersonDao public void init() { + assocTypeQNameID = qnameDAO.getOrCreateQName(ContentModel.ASSOC_CHILDREN).getFirst(); qNamePropId = qnameDAO.getOrCreateQName(ContentModel.PROP_USERNAME).getFirst(); qNameTypeId = qnameDAO.getOrCreateQName(ContentModel.TYPE_PERSON).getFirst(); } @@ -112,6 +114,7 @@ public class PersonDaoImpl extends HibernateDaoSupport implements PersonDao public Object doInHibernate(Session session) { SQLQuery query = (SQLQuery) session.getNamedQuery(QUERY_PERSON_GET_PERSON_IGNORE_CASE); + query.setParameter("assocTypeQNameID", assocTypeQNameID); query.setParameter("qnamePropId", qNamePropId); query.setParameter("qnameTypeId", qNameTypeId); query.setParameter("userNameLowerCase", searchUserName.toLowerCase()); // Lowercase: ETHREEOH-1431 diff --git a/source/java/org/alfresco/repo/security/person/PersonServiceImpl.java b/source/java/org/alfresco/repo/security/person/PersonServiceImpl.java index 3e63a1389a..d935c327ab 100644 --- a/source/java/org/alfresco/repo/security/person/PersonServiceImpl.java +++ b/source/java/org/alfresco/repo/security/person/PersonServiceImpl.java @@ -18,7 +18,7 @@ * As a special exception to the terms and conditions of version 2.0 of * the GPL, you may redistribute this Program in connection with Free/Libre * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing + * FLOSS exception. You should have received a copy of the text describing * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ @@ -255,7 +255,25 @@ public class PersonServiceImpl extends TransactionListenerAdapter implements Per * @return NodeRef of the person as specified by the username * @throws NoSuchPersonException */ - public NodeRef getPerson(final String userName) + public NodeRef getPerson(String userName) + { + return getPerson(userName, true); + } + + /** + * Retrieve the person NodeRef for a username key. Depending on the autoCreate parameter and + * configuration missing people will be created if not found, else a NoSuchPersonException exception will be thrown. + * + * @param userName + * of the person NodeRef to retrieve + * @param autoCreate + * should we auto-create the person node and home folder if they don't exist? (and configuration allows + * us to) + * @return NodeRef of the person as specified by the username + * @throws NoSuchPersonException + * if the person doesn't exist and can't be created + */ + public NodeRef getPerson(final String userName, final boolean autoCreate) { // MT share - for activity service system callback if (tenantService.isEnabled() && (AuthenticationUtil.SYSTEM_USER_NAME.equals(AuthenticationUtil.getRunAsUser())) && tenantService.isTenantUser(userName)) @@ -266,17 +284,17 @@ public class PersonServiceImpl extends TransactionListenerAdapter implements Per { public NodeRef doWork() throws Exception { - return getPersonImpl(userName); + return getPersonImpl(userName, autoCreate); } }, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantDomain)); } else { - return getPersonImpl(userName); + return getPersonImpl(userName, autoCreate); } } - private NodeRef getPersonImpl(String userName) + private NodeRef getPersonImpl(String userName, boolean autoCreate) { if(userName == null) { @@ -290,7 +308,7 @@ public class PersonServiceImpl extends TransactionListenerAdapter implements Per if (personNode == null) { TxnReadState txnReadState = AlfrescoTransactionSupport.getTransactionReadState(); - if (createMissingPeople() && txnReadState == TxnReadState.TXN_READ_WRITE) + if (autoCreate && createMissingPeople() && txnReadState == TxnReadState.TXN_READ_WRITE) { // We create missing people AND are in a read-write txn return createMissingPerson(userName); @@ -300,11 +318,11 @@ public class PersonServiceImpl extends TransactionListenerAdapter implements Per throw new NoSuchPersonException(userName); } } - else + else if (autoCreate) { makeHomeFolderIfRequired(personNode); - return personNode; } + return personNode; } public boolean personExists(String caseSensitiveUserName) diff --git a/source/java/org/alfresco/repo/security/sync/BatchProcessor.java b/source/java/org/alfresco/repo/security/sync/BatchProcessor.java index 0b0ce21b1d..3a73b3b9d8 100644 --- a/source/java/org/alfresco/repo/security/sync/BatchProcessor.java +++ b/source/java/org/alfresco/repo/security/sync/BatchProcessor.java @@ -452,9 +452,12 @@ public class BatchProcessor implements BatchMonitor /** The number of successfully processed entries. */ private int txnSuccesses; + /** The current entry being processed in the transaction */ + private String txnEntryId; + /** The last error. */ private Throwable txnLastError; - + /** The last error entry id. */ private String txnLastErrorEntryId; @@ -467,7 +470,7 @@ public class BatchProcessor implements BatchMonitor reset(); for (T entry : this.batch) { - String txnEntryId = this.worker.getIdentifier(entry); + this.txnEntryId = this.worker.getIdentifier(entry); synchronized (BatchProcessor.this) { BatchProcessor.this.currentEntryId = txnEntryId; @@ -479,9 +482,6 @@ public class BatchProcessor implements BatchMonitor } catch (Throwable t) { - this.txnLastError = t; - this.txnLastErrorEntryId = txnEntryId; - this.txnErrors++; if (RetryingTransactionHelper.extractRetryCause(t) == null) { if (BatchProcessor.logger.isWarnEnabled()) @@ -489,6 +489,9 @@ public class BatchProcessor implements BatchMonitor BatchProcessor.logger.warn(getProcessName() + ": Failed to process entry \"" + txnEntryId + "\".", t); } + this.txnLastError = t; + this.txnLastErrorEntryId = txnEntryId; + this.txnErrors++; } else { @@ -514,6 +517,9 @@ public class BatchProcessor implements BatchMonitor // If the callback was in its own transaction, it must have run out of retries if (this.splitTxns) { + this.txnLastError = t; + this.txnLastErrorEntryId = this.txnEntryId; + this.txnErrors++; if (BatchProcessor.logger.isWarnEnabled()) { BatchProcessor.logger.warn(getProcessName() + ": Failed to process entry \"" diff --git a/source/java/org/alfresco/repo/security/sync/ChainingUserRegistrySynchronizerTest.java b/source/java/org/alfresco/repo/security/sync/ChainingUserRegistrySynchronizerTest.java index 4e677b31c6..4657d483d8 100644 --- a/source/java/org/alfresco/repo/security/sync/ChainingUserRegistrySynchronizerTest.java +++ b/source/java/org/alfresco/repo/security/sync/ChainingUserRegistrySynchronizerTest.java @@ -405,6 +405,31 @@ public class ChainingUserRegistrySynchronizerTest extends TestCase tearDownTestUsersAndGroups(); } + /** + * Tests synchronization of group associations in a zone with a larger volume of authorities. + * + * @throws Exception + * the exception + */ + public void dontTestAssocs() throws Exception + { + this.retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback() + { + public Object execute() throws Throwable + { + List groups = new ArrayList(new RandomGroupCollection(1000, + ChainingUserRegistrySynchronizerTest.this.authorityService.getAllAuthoritiesInZone( + AuthorityService.ZONE_AUTH_EXT_PREFIX + "Z0", null))); + ChainingUserRegistrySynchronizerTest.this.applicationContextManager + .setUserRegistries(new MockUserRegistry("Z0", Collections. emptyList(), groups)); + ; + ChainingUserRegistrySynchronizerTest.this.synchronizer.synchronize(true, true); + return null; + } + }); + tearDownTestUsersAndGroups(); + } + /** * Constructs a description of a test group. * @@ -719,12 +744,12 @@ public class ChainingUserRegistrySynchronizerTest extends TestCase public boolean hasNext() { - return pos < size; + return this.pos < RandomPersonCollection.this.size; } public NodeDescription next() { - pos++; + this.pos++; return newPerson("U" + GUID.generate()); } @@ -743,7 +768,7 @@ public class ChainingUserRegistrySynchronizerTest extends TestCase @Override public int size() { - return size; + return this.size; } } @@ -758,21 +783,39 @@ public class ChainingUserRegistrySynchronizerTest extends TestCase /** The collection size. */ private final int size; - /** The persons. */ - private final List persons; + /** The authorities. */ + private final List authorities; /** * The Constructor. * * @param size * the collection size - * @param persons - * the persons + * @param authorities + * the authorities */ - public RandomGroupCollection(int size, List persons) + public RandomGroupCollection(int size, Set authorities) { this.size = size; - this.persons = persons; + this.authorities = new ArrayList(authorities); + } + + /** + * The Constructor. + * + * @param size + * the collection size + * @param authorities + * the authorities + */ + public RandomGroupCollection(int size, Collection persons) + { + this.size = size; + this.authorities = new ArrayList(persons.size()); + for (NodeDescription nodeDescription : persons) + { + this.authorities.add((String) nodeDescription.getProperties().get(ContentModel.PROP_USERNAME)); + } } /* @@ -789,19 +832,21 @@ public class ChainingUserRegistrySynchronizerTest extends TestCase public boolean hasNext() { - return pos < size; + return this.pos < RandomGroupCollection.this.size; } public NodeDescription next() { - pos++; - String[] personNames = new String[10]; - for (int i = 0; i < personNames.length; i++) + this.pos++; + String[] authorityNames = new String[17]; + for (int i = 0; i < authorityNames.length; i++) { - personNames[i] = (String) persons.get((int) (Math.random() * (double) (persons.size() - 1))) - .getProperties().get(ContentModel.PROP_USERNAME); + authorityNames[i] = ChainingUserRegistrySynchronizerTest.this.authorityService + .getShortName((String) RandomGroupCollection.this.authorities + .get((int) (Math.random() * (double) (RandomGroupCollection.this.authorities + .size() - 1)))); } - return newGroup("G" + GUID.generate(), personNames); + return newGroup("G" + GUID.generate(), authorityNames); } public void remove() @@ -819,7 +864,7 @@ public class ChainingUserRegistrySynchronizerTest extends TestCase @Override public int size() { - return size; + return this.size; } } diff --git a/source/java/org/alfresco/repo/tenant/MultiTAdminServiceImpl.java b/source/java/org/alfresco/repo/tenant/MultiTAdminServiceImpl.java index 68de2e8a51..536010b227 100755 --- a/source/java/org/alfresco/repo/tenant/MultiTAdminServiceImpl.java +++ b/source/java/org/alfresco/repo/tenant/MultiTAdminServiceImpl.java @@ -52,7 +52,6 @@ import org.alfresco.repo.security.authentication.AuthenticationContext; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.site.SiteAVMBootstrap; -import org.alfresco.repo.usage.UserUsageBootstrapJob; import org.alfresco.repo.usage.UserUsageTrackingComponent; import org.alfresco.repo.workflow.WorkflowDeployer; import org.alfresco.service.cmr.admin.RepoAdminService; @@ -937,7 +936,7 @@ public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationCo spacesImporterBootstrap.bootstrap(); // calculate any missing usages - UserUsageTrackingComponent userUsageTrackingComponent = (UserUsageTrackingComponent)ctx.getBean(UserUsageBootstrapJob.KEY_COMPONENT); + UserUsageTrackingComponent userUsageTrackingComponent = (UserUsageTrackingComponent)ctx.getBean("userUsageTrackingComponent"); userUsageTrackingComponent.bootstrapInternal(); logger.debug("Bootstrapped store: " + tenantService.getBaseName(bootstrapStoreRef)); diff --git a/source/java/org/alfresco/repo/usage/UserUsageBootstrapJob.java b/source/java/org/alfresco/repo/usage/UserUsageBootstrapJob.java deleted file mode 100644 index 0a7aa529e6..0000000000 --- a/source/java/org/alfresco/repo/usage/UserUsageBootstrapJob.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2005-2007 Alfresco Software Limited. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program 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 General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" - */ -package org.alfresco.repo.usage; - -import org.quartz.Job; -import org.quartz.JobDataMap; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; - -/** - * Bootstraps user's content usage. This job is performed once at startup. - * - * If usages are enabled (as specified by 'system.usages.enabled=true' repository property) then will calculate - * usages for all users that have no current usage. - * - * If usages are disabled (as specified by 'system.usages.enabled=false' repository property) then will clear - * current usages for all users. - */ -public class UserUsageBootstrapJob implements Job -{ - public static final String KEY_COMPONENT = "userUsageTrackingComponent"; - - public void execute(JobExecutionContext context) throws JobExecutionException - { - JobDataMap jobData = context.getJobDetail().getJobDataMap(); - UserUsageTrackingComponent usageComponent = (UserUsageTrackingComponent) jobData.get(KEY_COMPONENT); - if (usageComponent == null) - { - throw new JobExecutionException("Missing job data: " + KEY_COMPONENT); - } - // perform the content usage bootstrap - usageComponent.bootstrap(); - } -} diff --git a/source/java/org/alfresco/repo/usage/UserUsageTrackingComponent.java b/source/java/org/alfresco/repo/usage/UserUsageTrackingComponent.java index 2cf1edade8..dca599d840 100644 --- a/source/java/org/alfresco/repo/usage/UserUsageTrackingComponent.java +++ b/source/java/org/alfresco/repo/usage/UserUsageTrackingComponent.java @@ -48,17 +48,19 @@ import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.usage.UsageService; import org.alfresco.service.namespace.QName; +import org.alfresco.util.AbstractLifecycleBean; import org.alfresco.util.Pair; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.context.ApplicationEvent; /** * User Usage Tracking Component - to allow user usages to be collapsed or re-calculated * * - used by UserUsageCollapseJob to collapse usage deltas. - * - used by UserUsageBootstrapJob to either clear all usages or (re-)calculate all missing usages. + * - used on bootstrap to either clear all usages or (re-)calculate all missing usages. */ -public class UserUsageTrackingComponent +public class UserUsageTrackingComponent extends AbstractLifecycleBean { private static Log logger = LogFactory.getLog(UserUsageTrackingComponent.class); @@ -156,8 +158,9 @@ public class UserUsageTrackingComponent } } - // called once on startup - public void bootstrap() + + @Override + protected void onBootstrap(ApplicationEvent event) { // default domain bootstrapInternal(); @@ -176,7 +179,7 @@ public class UserUsageTrackingComponent } }, tenantAdminService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenant.getTenantDomain())); } - } + } } public void bootstrapInternal() @@ -212,6 +215,12 @@ public class UserUsageTrackingComponent } } + @Override + protected void onShutdown(ApplicationEvent event) + { + } + + /** * Clear content usage for all users that have a usage. */ diff --git a/source/java/org/alfresco/service/cmr/security/PersonService.java b/source/java/org/alfresco/service/cmr/security/PersonService.java index 0979ad3e76..f37abb6d1e 100644 --- a/source/java/org/alfresco/service/cmr/security/PersonService.java +++ b/source/java/org/alfresco/service/cmr/security/PersonService.java @@ -68,6 +68,22 @@ public interface PersonService @Auditable(parameters = {"userName"}) public NodeRef getPerson(String userName); + /** + * Retrieve the person NodeRef for a username key. Depending on the autoCreate parameter and + * configuration missing people will be created if not found, else a NoSuchPersonException exception will be thrown. + * + * @param userName + * of the person NodeRef to retrieve + * @param autoCreate + * should we auto-create the person node and home folder if they don't exist? (and configuration allows + * us to) + * @return NodeRef of the person as specified by the username + * @throws NoSuchPersonException + * if the person doesn't exist and can't be created + */ + @Auditable(parameters = {"userName", "autoCreate"}) + public NodeRef getPerson(final String userName, final boolean autoCreate); + /** * Check if a person exists. *