From b794365eaa185de8af957b36c16dc712346ce220 Mon Sep 17 00:00:00 2001 From: Dave Ward Date: Thu, 25 Oct 2012 16:38:22 +0000 Subject: [PATCH] Merged V4.1-BUG-FIX to HEAD 42933: ALF-15328 could we add a sample log4j file in 'extension'? 42935: ALF-16455: Merged V3.4-BUG-FIX (3.4.12) to V4.1-BUG-FIX (4.1.2) 42934: ALF-16454 TransformerDebug id values have gaps 42955: ALF-15328 could we add a sample log4j file in 'extension'? - missing j in file name 42982: Merged DEV to V4.1-BUG-FIX 42873: ALF-16194: Checkout/Checkin leaves Lockable aspect on which disables autoVersionOnUpdateProps DoNothingCopyBehaviourCallback policy has been set for lockable aspect (implemented in LockServiceImpl); Unit test has been added. 43000: Merged BRANCHES/DEV/BELARUS/V4.1-BUG-FIX-2012_10_19 to BRANCHES/DEV/V4.1-BUG-FIX: 42936: ALF-11573: It's impossible to Modify settings for document versions 43010: ALF-16006 MT: Document Library is absent after upgrade from 3.4.x to 4.1.x (eg. 3.4.10 -> 4.1.1) - applied patch suggested in JIRA 43017: ALF-16457: "CmisObjectNotFoundException: No corresponding type found! Not a CMIS object?" thrown by AlfrescoCmisServiceImpl.getChildren - Check CMISNodeInfo for invalid type before processing. 43019: ALF-14353: Upgrade Activiti dependencies in Maven build 43022: ALF-14353: Upgrade Activiti dependencies in Maven build 43027: Merged DEV to V4.1-BUG-FIX 42426: ALF-15577: " does not support the method HEAD " when opening a MS Access file with "View In Browser" 43029: Merged DEV to 4.1-BUG-FIX (4.1.2) 42988: ALF-15791: Custom Types,Aspects defined with prefix using underscore cannot be loaded by API calls like api/classes/ Identical logic for old and new ClassDef API was moved to abstract super classes 42924: ALF-15791: Custom Types,Aspects defined with prefix using underscore cannot be loaded by API calls like api/classes/ New set of URL templates for class defenitions were provided to support requests with separated namespace prefixes and names 43031: ALF-16489: Typo in column-name of newly created index 43041: Merged DEV to 4.1-BUG-FIX (4.1.2) 43040: ALF-16425: API call to return all classes, returns wrong properties in classes Propertydefs and assocdefs are reordered to corelate with classdefs. Unit test was added for issue. 43052: ALF-16194: Checkout/Checkin leaves Lockable aspect on which disables autoVersionOnUpdateProps - Fix failing test 43055: Probable fix for ALF-15813. Replaced the 'skipCount' with the one in the query request, rather than query result. The Lucene query result does not support the reporting of the skipCount. 43065: Merged V3.4-BUG-FIX to V4.1-BUG-FIX 42958: ALF-14421: Inconsistencies when applying Versionable Aspect - We think the most preferable fix that will result in the best consistency between Share and old Explorer behaviour is to make the adding of the versionable aspect always result in an initial MAJOR version, if a version type has not been specified. Major/minor versions can still be controlled explicitly by checkout/checkin the versionable aspect properties and the version service API. 42998: ALF-14421: Fixed version label unit test fallout - back to what it used to be. 42999: Fix for ALF-16261 - IE script error occurs when email space users providing there are no users in this space 43006: Removed dependency on Apache Commons StringUtils. See ALF-12541, ALF-14254, AMZNSSS-17 43028: ALF-14722: Merged V4.1-BUG-FIX to V3.4-BUG-FIX 42902: Merged DEV to V4.1-BUG-FIX 42519: ALF-13588: Google Doc failed to authenticate after incorrect password being entered for google account Add ability to unregister class behaviours. Unregister googledocs behaviours when subsystem stops. 43066: ALF-16502: Merged PATCHES/V4.0.2 to V4.1-BUG-FIX 42969: Merged DEV to PATCHES/V4.0.2 42967: MNT-158: SharePoint Protocol Opening Documents in Read-Only for Site Consumer with Collaborator Privileges Remove manual throwing of AccessDeniedException is user has "consumer" or "contributor" role. Create "links" container from system user. 43067: Merged PATCHES/V4.1.1 to V4.1-BUG-FIX 42470: ALF-16503 / ALF-16256: Upgrade 3.4.6 HF to 4.1.1 - DuplicateChildNodeNameException: Duplicate child name not allowed: surf-config 42591: ALF-16504 / ALF-16332: Fixed synchronization around org.alfresco.repo.dictionary.NamespaceDAOImpl.namespaceRegistryCache - There was no 'double checking' after releasing the write lock, meaning that under high concurrency lots of threads would queue up to continuously re-initialize the registry. 42705: ALF-16504/ ALF-16332, ALF-16377: Revisited synchronization and initialization of mutually-dependent DictionaryDAO and NamespaceDAO to prevent deadlock and simultaneous re-initialization in more than one thread 43068: Merged DEV to V4.1-BUG-FIX - TODO: Update DB2 DDL in activiti 42388: ALF-15828: DB2: unexpected index found in database. Modify activity create script for db2 to create normal name for ACT_HI_PROCINST.PROC_INST_ID_ index. Introduce patch that will rename autogenerated name to normal name for ACT_HI_PROCINST.PROC_INST_ID_ index. Update schema reference file for DB2. 42429: ALF-15828: DB2: unexpected index found in database. Fix scripts from ALF-14983 and ALF-16038 to drop/recreate tables in DB2. 43069: ALF-11214: IMAP subsystem is not successfully restarted after incorrect modification of IMAP properties via Admin Console Stopped ChildApplicationContextFactory from caching a stale application context that didn't successfully refresh. 43071: ALF-13660: When using kerberos SSO, non domain explorer users requesting a download URL get a login page but after login do not get the requested document - Now the Web Client authentication filters use the same mechanism for preserving the request URL through a redirect to the login page 43076: ALF-15828: Fixed merge issue 43079: ALF-13602: Incorrect number of documents displayed in Share DocLib when a file is checked out - added ability for FileFolderService.list (-> FileFolder GetChildren CQ) to filter by one or more aspects, eg. cm:checkedOut 43080: ALF-14421: More version label unit test fallout 43092: Fix ALF-16460: Users may receive activity feed entries (from people they follow) for moderated sites to which they do not belong - also add unit test 43093: Fix for ALF-16091 - Unable to inline edit javascript file. 43096: Fix for ALF-16283 - When document is checked out, 'Edit Online' and 'Upload New Version' options should not be visible on the original document. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@43103 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/bootstrap-context.xml | 1 + .../rename-constraint-activiti.sql | 25 ++ .../extension/custom-log4j.properties.sample | 3 + .../messages/patch-service.properties | 1 + .../model-specific-services-context.xml | 1 + .../alfresco/patch/patch-services-context.xml | 17 ++ config/alfresco/version.properties | 2 +- .../opencmis/AlfrescoCmisServiceImpl.java | 5 + .../feed/local/LocalFeedTaskProcessor.java | 27 +- .../patch/impl/AVMToADMRemoteStorePatch.java | 21 +- .../repo/audit/access/AccessAuditorTest.java | 3 +- .../alfresco/repo/blog/BlogServiceImpl.java | 3 +- .../repo/coci/CheckOutCheckInServiceImpl.java | 1 + .../coci/CheckOutCheckInServiceImplTest.java | 21 ++ .../content/transform/TransformerDebug.java | 19 +- .../alfresco/repo/lock/LockServiceImpl.java | 26 +- .../ChildApplicationContextFactory.java | 5 +- .../filefolder/FileFolderServiceImpl.java | 56 +++- .../filefolder/FileFolderServiceImplTest.java | 172 ++++++++--- .../filefolder/GetChildrenCannedQuery.java | 77 +++-- .../GetChildrenCannedQueryFactory.java | 33 ++- .../ml/tools/EditionServiceImplTest.java | 62 ++-- .../repo/module/ModuleDetailsImpl.java | 46 ++- .../SubscriptionServiceActivitiesTest.java | 278 ++++++++++++++++-- .../repo/version/VersionServiceImplTest.java | 22 +- .../repo/version/VersionableAspect.java | 4 +- 26 files changed, 728 insertions(+), 203 deletions(-) create mode 100644 config/alfresco/dbscripts/upgrade/4.1/org.hibernate.dialect.Dialect/rename-constraint-activiti.sql create mode 100644 config/alfresco/extension/custom-log4j.properties.sample diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml index 25d15389a2..2e6730bd7a 100644 --- a/config/alfresco/bootstrap-context.xml +++ b/config/alfresco/bootstrap-context.xml @@ -173,6 +173,7 @@ + diff --git a/config/alfresco/dbscripts/upgrade/4.1/org.hibernate.dialect.Dialect/rename-constraint-activiti.sql b/config/alfresco/dbscripts/upgrade/4.1/org.hibernate.dialect.Dialect/rename-constraint-activiti.sql new file mode 100644 index 0000000000..a15669db7e --- /dev/null +++ b/config/alfresco/dbscripts/upgrade/4.1/org.hibernate.dialect.Dialect/rename-constraint-activiti.sql @@ -0,0 +1,25 @@ +-- +-- Title: Update ACT_HI_PROCINST table. Create normal name for unique constraint on PROC_INST_ID_ +-- Database: Generic +-- Since: V4.1 Schema 5116 +-- Author: Dmitry Vaserin +-- +-- Please contact support@alfresco.com if you need assistance with the upgrade. +-- +-- ALF-15828 : DB2: unexpected index found in database. + +-- Patch is applied only for DB2, see ALF-15828 + +-- +-- Record script finish +-- + + +DELETE FROM alf_applied_patch WHERE id = 'patch.db-V4.1-rename-constraint-activiti'; +INSERT INTO alf_applied_patch + (id, description, fixes_from_schema, fixes_to_schema, applied_to_schema, target_schema, applied_on_date, applied_to_server, was_executed, succeeded, report) + VALUES + ( + 'patch.db-V4.1-rename-constraint-activiti', 'Manually executed script upgrade V4.1: Rename PROC_INST_ID_ constraint', + 0, 6020, -1, 6021, null, 'UNKNOWN', ${TRUE}, ${TRUE}, 'Script completed' + ); \ No newline at end of file diff --git a/config/alfresco/extension/custom-log4j.properties.sample b/config/alfresco/extension/custom-log4j.properties.sample new file mode 100644 index 0000000000..18027bc568 --- /dev/null +++ b/config/alfresco/extension/custom-log4j.properties.sample @@ -0,0 +1,3 @@ +#log4j.logger.org.alfresco.repo.content.transform.TransformerDebug=debug +#log4j.logger.org.alfresco.util.exec.RuntimeExecBootstrapBean=debug +#log4j.logger.org.alfresco.util.exec.RuntimeExec=debug \ No newline at end of file diff --git a/config/alfresco/messages/patch-service.properties b/config/alfresco/messages/patch-service.properties index c40c9a3184..af3422b363 100644 --- a/config/alfresco/messages/patch-service.properties +++ b/config/alfresco/messages/patch-service.properties @@ -487,4 +487,5 @@ patch.show.audit.success=show_audit.ftl was updated successfully patch.increaseColumnSizeActiviti.description=ALF-14983 : Upgrade scripts to increase column sizes for Activiti patch.removeColumnActiviti.description=ALF-16038 : DB2: Upgrade script to remove ALFUSER.ACT_HI_ACTINST.OWNER_ +patch.renameConstraintActiviti.description=ALF-15828 : DB2: Upgrade script to rename ACT_HI_PROCINST.PROC_INST_ID_ index patch.upgradeToActiviti5-10.description=Upgraded Activiti tables to 5.10 version \ No newline at end of file diff --git a/config/alfresco/model-specific-services-context.xml b/config/alfresco/model-specific-services-context.xml index a21a4e76c5..868ef2ef88 100644 --- a/config/alfresco/model-specific-services-context.xml +++ b/config/alfresco/model-specific-services-context.xml @@ -91,6 +91,7 @@ + diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml index e7325a9b2f..ebac8debb0 100644 --- a/config/alfresco/patch/patch-services-context.xml +++ b/config/alfresco/patch/patch-services-context.xml @@ -2767,6 +2767,12 @@ sitestore /alfresco/site-data + + + + + + @@ -3406,4 +3412,15 @@ + + patch.db-V4.1-rename-constraint-activiti + patch.renameConstraintActiviti.description + 0 + 6020 + 6021 + + classpath:alfresco/dbscripts/upgrade/4.1/${db.script.dialect}/rename-constraint-activiti.sql + + + diff --git a/config/alfresco/version.properties b/config/alfresco/version.properties index b6828afc81..e3cc3f112b 100644 --- a/config/alfresco/version.properties +++ b/config/alfresco/version.properties @@ -19,4 +19,4 @@ version.build=@build-number@ # Schema number -version.schema=6020 +version.schema=6021 diff --git a/source/java/org/alfresco/opencmis/AlfrescoCmisServiceImpl.java b/source/java/org/alfresco/opencmis/AlfrescoCmisServiceImpl.java index e28d799107..0b59f708fb 100644 --- a/source/java/org/alfresco/opencmis/AlfrescoCmisServiceImpl.java +++ b/source/java/org/alfresco/opencmis/AlfrescoCmisServiceImpl.java @@ -566,6 +566,11 @@ public class AlfrescoCmisServiceImpl extends AbstractCmisService implements Alfr { // create a child CMIS object CMISNodeInfo ni = createNodeInfo(child.getNodeRef()); + if (getObjectInfo(repositoryId, ni.getObjectId())==null) + { + // ignore invalid children + continue; + } ObjectData object = connector.createCMISObject(ni, child, filter, includeAllowableActions, includeRelationships, renditionFilter, false, false); diff --git a/source/java/org/alfresco/repo/activities/feed/local/LocalFeedTaskProcessor.java b/source/java/org/alfresco/repo/activities/feed/local/LocalFeedTaskProcessor.java index ba30196c3b..d137852267 100644 --- a/source/java/org/alfresco/repo/activities/feed/local/LocalFeedTaskProcessor.java +++ b/source/java/org/alfresco/repo/activities/feed/local/LocalFeedTaskProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2011 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -48,7 +48,9 @@ import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.site.SiteInfo; import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.service.cmr.site.SiteVisibility; import org.alfresco.service.cmr.subscriptions.PagingFollowingResults; import org.alfresco.service.cmr.subscriptions.SubscriptionService; import org.apache.commons.logging.Log; @@ -269,7 +271,7 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica } @Override - protected boolean canReadSite(final RepoCtx ctx, String siteIdIn, String connectedUser, final String tenantDomain) throws Exception + protected boolean canReadSite(final RepoCtx ctx, String siteIdIn, final String connectedUser, final String tenantDomain) throws Exception { if (useRemoteCallbacks) { @@ -283,7 +285,26 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica { public Boolean doWork() throws Exception { - return (siteService.getSite(siteId) != null); + boolean canRead = false; + SiteInfo siteInfo = siteService.getSite(siteId); + if (siteInfo != null) + { + switch (siteInfo.getVisibility()) + { + case MODERATED: + // moderated - note: need to check site membership + canRead = siteService.isMember(siteId, connectedUser); + break; + case PUBLIC: + case PRIVATE: + // public or private - note: for private site, membership is implied (since getSite did not return null) + canRead = true; + break; + default: + break; + } + } + return canRead; } }, connectedUser); } diff --git a/source/java/org/alfresco/repo/admin/patch/impl/AVMToADMRemoteStorePatch.java b/source/java/org/alfresco/repo/admin/patch/impl/AVMToADMRemoteStorePatch.java index b6973b3e5e..e39e7e06d3 100644 --- a/source/java/org/alfresco/repo/admin/patch/impl/AVMToADMRemoteStorePatch.java +++ b/source/java/org/alfresco/repo/admin/patch/impl/AVMToADMRemoteStorePatch.java @@ -319,11 +319,15 @@ public class AVMToADMRemoteStorePatch extends AbstractPatch public void process(String siteName) throws Throwable { // get the Site NodeRef - NodeRef siteRef = getSiteNodeRef(siteName); - if (siteRef != null) + SiteInfo siteInfo = AVMToADMRemoteStorePatch.this.siteService.getSite(siteName); + + // ALF-16256: We've actually looked up the site by case insensitive name. But there may actually be + // paths in existence for the same site name but with different cases. We are only interested in the + // site whose name matches EXACTLY. + if (siteInfo != null && siteInfo.getShortName().equals(siteName)) { // create the 'surf-config' folder for the site and cache the NodeRef to it - NodeRef surfConfigRef = getSurfConfigNodeRef(siteRef); + NodeRef surfConfigRef = getSurfConfigNodeRef(siteInfo.getNodeRef()); siteReferenceCache.put(siteName, surfConfigRef); // pre-create folders that may cause contention later during multi-threaded batch processing @@ -598,17 +602,6 @@ public class AVMToADMRemoteStorePatch extends AbstractPatch } } - /** - * @param shortName Site shortname - * - * @return the given Site folder node reference - */ - private NodeRef getSiteNodeRef(String shortName) - { - SiteInfo siteInfo = this.siteService.getSite(shortName); - return siteInfo != null ? siteInfo.getNodeRef() : null; - } - /** * Return the "surf-config" noderef under the given root. Create the folder if it * does not exist yet. diff --git a/source/java/org/alfresco/repo/audit/access/AccessAuditorTest.java b/source/java/org/alfresco/repo/audit/access/AccessAuditorTest.java index 43566ad097..c6eadc5070 100644 --- a/source/java/org/alfresco/repo/audit/access/AccessAuditorTest.java +++ b/source/java/org/alfresco/repo/audit/access/AccessAuditorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2011 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -541,7 +541,6 @@ public class AccessAuditorTest // original file assertEquals("CHECK IN", origMap.get("action")); assertContains("deleteNodeAspect", origMap.get("sub-actions")); - assertContains("addNodeAspect", origMap.get("sub-actions")); assertContains("copyNode", origMap.get("sub-actions")); assertContains("createVersion", origMap.get("sub-actions")); assertContains("updateNodeProperties", origMap.get("sub-actions")); diff --git a/source/java/org/alfresco/repo/blog/BlogServiceImpl.java b/source/java/org/alfresco/repo/blog/BlogServiceImpl.java index 0525a6e3cd..5b5a576c76 100644 --- a/source/java/org/alfresco/repo/blog/BlogServiceImpl.java +++ b/source/java/org/alfresco/repo/blog/BlogServiceImpl.java @@ -573,9 +573,8 @@ public class BlogServiceImpl implements BlogService @Override public Pair getTotalResultCount() { - int skipCount = finalLuceneResults.getStart(); int itemsRemainingAfterThisPage = finalLuceneResults.length(); - final int totalItemsInUnpagedResultSet = skipCount + itemsRemainingAfterThisPage; + final int totalItemsInUnpagedResultSet = pagingReq.getSkipCount() + itemsRemainingAfterThisPage; return new Pair(totalItemsInUnpagedResultSet, totalItemsInUnpagedResultSet); } diff --git a/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImpl.java b/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImpl.java index df4ba6d8ea..fe0e219d52 100644 --- a/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImpl.java +++ b/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImpl.java @@ -468,6 +468,7 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService workingCopyProperties.put(ContentModel.PROP_WORKING_COPY_OWNER, userName); workingCopyProperties.put(ContentModel.PROP_WORKING_COPY_LABEL, workingCopyLabel); nodeService.addAspect(workingCopy, ContentModel.ASPECT_WORKING_COPY, workingCopyProperties); + nodeService.addAspect(workingCopy, ContentModel.ASPECT_LOCKABLE, null); nodeService.addAspect(nodeRef, ContentModel.ASPECT_CHECKED_OUT, null); nodeService.createAssociation(nodeRef, workingCopy, ContentModel.ASSOC_WORKING_COPY_LINK); } diff --git a/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImplTest.java b/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImplTest.java index ec45cb379e..759cd721bd 100644 --- a/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImplTest.java +++ b/source/java/org/alfresco/repo/coci/CheckOutCheckInServiceImplTest.java @@ -847,6 +847,27 @@ public class CheckOutCheckInServiceImplTest extends BaseSpringTest } } + public void testCheckInLockableAspectDoesntCopies_ALF16194() + { + // Check-out nodeRef + NodeRef workingCopy = this.cociService.checkout( + this.nodeRef, + this.rootNodeRef, + ContentModel.ASSOC_CHILDREN, + QName.createQName("workingCopy")); + assertNotNull(workingCopy); + + // Check-in + Map versionProperties = new HashMap(); + versionProperties.put(Version.PROP_DESCRIPTION, "This is a test version"); + cociService.checkin(workingCopy, versionProperties); + + if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_LOCKABLE)) + { + fail("Lockable aspect should not be copied from the working copy to the original document"); + } + } + private NodeRef createFolderWithPermission(NodeRef parent, String username, String permission) { // Authenticate as system user because the current user should not be node owner diff --git a/source/java/org/alfresco/repo/content/transform/TransformerDebug.java b/source/java/org/alfresco/repo/content/transform/TransformerDebug.java index fc5320e525..269a96e514 100644 --- a/source/java/org/alfresco/repo/content/transform/TransformerDebug.java +++ b/source/java/org/alfresco/repo/content/transform/TransformerDebug.java @@ -108,7 +108,7 @@ public class TransformerDebug { private static final AtomicInteger uniqueId = new AtomicInteger(0); - private final int id; + private int id; private final String fromUrl; private final String sourceMimetype; private final String targetMimetype; @@ -125,7 +125,7 @@ public class TransformerDebug private Frame(Frame parent, String fromUrl, String sourceMimetype, String targetMimetype, TransformationOptions options, Call pushCall, boolean origDebugOutput) { - this.id = parent == null ? uniqueId.getAndIncrement() : ++parent.childId; + this.id = parent == null ? -1 : ++parent.childId; this.fromUrl = fromUrl; this.sourceMimetype = sourceMimetype; this.targetMimetype = targetMimetype; @@ -134,6 +134,15 @@ public class TransformerDebug this.origDebugOutput = origDebugOutput; start = System.currentTimeMillis(); } + + private int getId() + { + if (id == -1) + { + id = uniqueId.getAndIncrement(); + } + return id; + } } private class UnavailableTransformer @@ -587,7 +596,7 @@ public class TransformerDebug { logger.debug(getReference()+message, t); } - else + else if (logger.isTraceEnabled()) { logger.trace(getReference()+message, t); } @@ -623,13 +632,13 @@ public class TransformerDebug frame = iterator.next(); if (sb.length() == 0) { - sb.append(frame.id); + sb.append(frame.getId()); lengthOfFirstId = sb.length(); } else { sb.append('.'); - sb.append(frame.id); + sb.append(frame.getId()); } } if (frame != null) diff --git a/source/java/org/alfresco/repo/lock/LockServiceImpl.java b/source/java/org/alfresco/repo/lock/LockServiceImpl.java index 3ef4961a80..ffcb227b79 100644 --- a/source/java/org/alfresco/repo/lock/LockServiceImpl.java +++ b/source/java/org/alfresco/repo/lock/LockServiceImpl.java @@ -34,6 +34,7 @@ import org.alfresco.repo.copy.CopyBehaviourCallback; import org.alfresco.repo.copy.CopyDetails; import org.alfresco.repo.copy.CopyServicePolicies; import org.alfresco.repo.copy.DefaultCopyBehaviourCallback; +import org.alfresco.repo.copy.DoNothingCopyBehaviourCallback; import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.policy.BehaviourFilter; import org.alfresco.repo.policy.JavaBehaviour; @@ -537,32 +538,11 @@ public class LockServiceImpl implements LockService, } /** - * @return Returns {@link LockableAspectCopyBehaviourCallback} + * @return Returns {@link DoNothingCopyBehaviourCallback} */ public CopyBehaviourCallback getCopyCallback(QName classRef, CopyDetails copyDetails) { - return LockableAspectCopyBehaviourCallback.INSTANCE; - } - - /** - * Extends the default copy behaviour to prevent copying of lockable properties. - * - * @author Derek Hulley - * @since 3.2 - */ - private static class LockableAspectCopyBehaviourCallback extends DefaultCopyBehaviourCallback - { - private static final CopyBehaviourCallback INSTANCE = new LockableAspectCopyBehaviourCallback(); - - /** - * @return Returns an empty map - */ - @Override - public Map getCopyProperties( - QName classQName, CopyDetails copyDetails, Map properties) - { - return Collections.emptyMap(); - } + return DoNothingCopyBehaviourCallback.getInstance(); } /** diff --git a/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java b/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java index e122f8b15d..f7a0403214 100644 --- a/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java +++ b/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java @@ -715,9 +715,10 @@ public class ChildApplicationContextFactory extends AbstractPropertyBackedBean i { ChildApplicationContextFactory.logger .info("Starting '" + getCategory() + "' subsystem, ID: " + getId()); - this.applicationContext = ChildApplicationContextFactory.this.new ChildApplicationContext( + ClassPathXmlApplicationContext applicationContext = ChildApplicationContextFactory.this.new ChildApplicationContext( this.properties, this.compositeProperties); - this.applicationContext.refresh(); + applicationContext.refresh(); + this.applicationContext = applicationContext; ChildApplicationContextFactory.logger.info("Startup of '" + getCategory() + "' subsystem, ID: " + getId() + " complete"); } diff --git a/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java b/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java index e7487b95d4..99e0457a4f 100644 --- a/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java +++ b/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2011 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -40,7 +40,6 @@ import org.alfresco.query.PagingRequest; import org.alfresco.query.PagingResults; import org.alfresco.repo.model.filefolder.HiddenAspect.Visibility; import org.alfresco.repo.node.getchildren.GetChildrenCannedQuery; -import org.alfresco.repo.node.getchildren.GetChildrenCannedQueryFactory; import org.alfresco.repo.search.QueryParameterDefImpl; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.permissions.PermissionCheckedCollection.PermissionCheckedCollectionMixin; @@ -425,59 +424,63 @@ public class FileFolderServiceImpl implements FileFolderService /* (non-Javadoc) * @see org.alfresco.service.cmr.model.FileFolderService#list(org.alfresco.service.cmr.repository.NodeRef, boolean, boolean, java.util.Set, org.alfresco.service.cmr.model.PagingSortRequest) */ - @Auditable(parameters = {"contextNodeRef", "files", "folders", "ignoreTypeQNames", "sortProps", "pagingRequest"}) + @Auditable(parameters = {"contextNodeRef", "files", "folders", "ignoreQNames", "sortProps", "pagingRequest"}) public PagingResults list(NodeRef contextNodeRef, boolean files, boolean folders, - Set ignoreTypeQNames, + Set ignoreQNames, List> sortProps, PagingRequest pagingRequest) { ParameterCheck.mandatory("contextNodeRef", contextNodeRef); ParameterCheck.mandatory("pagingRequest", pagingRequest); - Set searchTypeQNames = buildTypes(files, folders, ignoreTypeQNames); + Pair,Set> pair = buildSearchTypesAndIgnoreAspects(files, folders, ignoreQNames); + Set searchTypeQNames = pair.getFirst(); + Set ignoreAspectQNames = pair.getSecond(); // execute query - final CannedQueryResults results = listImpl(contextNodeRef, null, searchTypeQNames, sortProps, pagingRequest); + final CannedQueryResults results = listImpl(contextNodeRef, null, searchTypeQNames, ignoreAspectQNames, sortProps, pagingRequest); return getPagingResults(pagingRequest, results); } /* (non-Javadoc) * @see org.alfresco.service.cmr.model.FileFolderService#list(org.alfresco.service.cmr.repository.NodeRef, boolean, boolean, String, java.util.Set, org.alfresco.service.cmr.model.PagingSortRequest) */ - public PagingResults list(NodeRef contextNodeRef, boolean files, boolean folders, String pattern, Set ignoreQNameTypes, List> sortProps, PagingRequest pagingRequest) + public PagingResults list(NodeRef contextNodeRef, boolean files, boolean folders, String pattern, Set ignoreQNames, List> sortProps, PagingRequest pagingRequest) { ParameterCheck.mandatory("contextNodeRef", contextNodeRef); ParameterCheck.mandatory("pagingRequest", pagingRequest); - Set searchTypeQNames = buildTypes(files, folders, ignoreQNameTypes); + Pair,Set> pair = buildSearchTypesAndIgnoreAspects(files, folders, ignoreQNames); + Set searchTypeQNames = pair.getFirst(); + Set ignoreAspectQNames = pair.getSecond(); // execute query - final CannedQueryResults results = listImpl(contextNodeRef, pattern, searchTypeQNames, sortProps, pagingRequest); + final CannedQueryResults results = listImpl(contextNodeRef, pattern, searchTypeQNames, ignoreAspectQNames, sortProps, pagingRequest); return getPagingResults(pagingRequest, results); } private CannedQueryResults listImpl(NodeRef contextNodeRef, boolean files, boolean folders) { - Set searchTypeQNames = buildTypes(files, folders, null); + Set searchTypeQNames = buildSearchTypesAndIgnoreAspects(files, folders, null).getFirst(); return listImpl(contextNodeRef, searchTypeQNames); } private CannedQueryResults listImpl(NodeRef contextNodeRef, Set searchTypeQNames) { - return listImpl(contextNodeRef, null, searchTypeQNames, null, new PagingRequest(defaultListMaxResults, null)); + return listImpl(contextNodeRef, null, searchTypeQNames, null, null, new PagingRequest(defaultListMaxResults, null)); } // note: similar to getChildAssocs(contextNodeRef, searchTypeQNames) but enables paging features, including max items, sorting etc (with permissions per-applied) - private CannedQueryResults listImpl(NodeRef contextNodeRef, String pattern, Set searchTypeQNames, List> sortProps, PagingRequest pagingRequest) + private CannedQueryResults listImpl(NodeRef contextNodeRef, String pattern, Set searchTypeQNames, Set ignoreAspectQNames, List> sortProps, PagingRequest pagingRequest) { Long start = (logger.isDebugEnabled() ? System.currentTimeMillis() : null); // get canned query GetChildrenCannedQueryFactory getChildrenCannedQueryFactory = (GetChildrenCannedQueryFactory)cannedQueryRegistry.getNamedObject(CANNED_QUERY_FILEFOLDER_LIST); - GetChildrenCannedQuery cq = (GetChildrenCannedQuery)getChildrenCannedQueryFactory.getCannedQuery(contextNodeRef, pattern, Collections.singleton(ContentModel.ASSOC_CONTAINS), searchTypeQNames, null, sortProps, pagingRequest); + GetChildrenCannedQuery cq = (GetChildrenCannedQuery)getChildrenCannedQueryFactory.getCannedQuery(contextNodeRef, pattern, Collections.singleton(ContentModel.ASSOC_CONTAINS), searchTypeQNames, ignoreAspectQNames, null, sortProps, pagingRequest); // execute canned query CannedQueryResults results = cq.execute(); @@ -747,9 +750,10 @@ public class FileFolderServiceImpl implements FileFolderService return PermissionCheckedValueMixin.create(results); } - private Set buildTypes(boolean files, boolean folders, Set ignoreQNameTypes) + private Pair, Set> buildSearchTypesAndIgnoreAspects(boolean files, boolean folders, Set ignoreQNameTypes) { Set searchTypeQNames = new HashSet(100); + Set ignoreAspectQNames = null; // Build a list of file and folder types if (folders) @@ -763,10 +767,32 @@ public class FileFolderServiceImpl implements FileFolderService if (ignoreQNameTypes != null) { + Set ignoreQNamesNotSearchTypes = new HashSet(ignoreQNameTypes); + ignoreQNamesNotSearchTypes.removeAll(searchTypeQNames); + ignoreQNamesNotSearchTypes.remove(ContentModel.TYPE_SYSTEM_FOLDER); // note: not included in buildFolderTypes() + + if (ignoreQNamesNotSearchTypes.size() > 0) + { + ignoreAspectQNames = getAspectsToIgnore(ignoreQNamesNotSearchTypes); + } + searchTypeQNames.removeAll(ignoreQNameTypes); } - return searchTypeQNames; + return new Pair, Set>(searchTypeQNames, ignoreAspectQNames); + } + + private Set getAspectsToIgnore(Set ignoreQNames) + { + Set ignoreQNameAspects = new HashSet(ignoreQNames.size()); + for (QName qname : ignoreQNames) + { + if (dictionaryService.getAspect(qname) != null) + { + ignoreQNameAspects.add(qname); + } + } + return ignoreQNameAspects; } private Set buildFolderTypes() diff --git a/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImplTest.java b/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImplTest.java index 75420b8543..a7e79585a1 100644 --- a/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImplTest.java +++ b/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImplTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2011 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -24,8 +24,10 @@ import java.io.OutputStream; import java.io.Reader; import java.util.ArrayList; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Set; import javax.transaction.Status; import javax.transaction.UserTransaction; @@ -49,6 +51,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.tenant.TenantService; import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.coci.CheckOutCheckInService; import org.alfresco.service.cmr.model.FileExistsException; import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileFolderServiceType; @@ -107,6 +110,8 @@ public class FileFolderServiceImplTest extends TestCase private PermissionService permissionService; private TenantService tenantService; private MutableAuthenticationService authenticationService; + private CheckOutCheckInService cociService; + private DictionaryDAO dictionaryDAO; private UserTransaction txn; private NodeRef rootNodeRef; @@ -124,6 +129,7 @@ public class FileFolderServiceImplTest extends TestCase authenticationService = (MutableAuthenticationService) ctx.getBean("AuthenticationService"); dictionaryDAO = (DictionaryDAO) ctx.getBean("dictionaryDAO"); tenantService = (TenantService) ctx.getBean("tenantService"); + cociService = serviceRegistry.getCheckOutCheckInService(); // start the transaction txn = transactionService.getUserTransaction(); @@ -266,37 +272,6 @@ public class FileFolderServiceImplTest extends TestCase } } - public void testListPage() throws Exception - { - // sanity checks only (see also GetChildrenCannedQueryTest) - - PagingRequest pagingRequest = new PagingRequest(100, null); - PagingResults pagingResults = fileFolderService.list(workingRootNodeRef, true, true, null, null, null, pagingRequest); - - assertNotNull(pagingResults); - assertFalse(pagingResults.hasMoreItems()); - assertTrue((pagingResults.getQueryExecutionId() != null) && (pagingResults.getQueryExecutionId().length() > 0)); - assertNull(pagingResults.getTotalResultCount()); - - List files = pagingResults.getPage(); - - // check - String[] expectedNames = new String[] - { NAME_L0_FILE_A, NAME_L0_FILE_B, NAME_L0_FOLDER_A, NAME_L0_FOLDER_B, NAME_L0_FOLDER_C }; - checkFileList(files, 2, 3, expectedNames); - - - // empty list if skip count greater than number of results (ALF-7884) - pagingRequest = new PagingRequest(1000, 3, null); - pagingResults = fileFolderService.list(workingRootNodeRef, true, true, null, null, null, pagingRequest); - - assertNotNull(pagingResults); - assertFalse(pagingResults.hasMoreItems()); - assertEquals(0, pagingResults.getPage().size()); - - // TODO add more here - } - public void testShallowFilesOnlyList() throws Exception { List files = fileFolderService.listFiles(workingRootNodeRef); @@ -1373,7 +1348,38 @@ public class FileFolderServiceImplTest extends TestCase assertEquals(1, pagingResults.getPage().size()); } - public void testListHiddenFiles() + public void testListPage() throws Exception + { + // sanity checks only (see also GetChildrenCannedQueryTest) + + PagingRequest pagingRequest = new PagingRequest(100, null); + PagingResults pagingResults = fileFolderService.list(workingRootNodeRef, true, true, null, null, null, pagingRequest); + + assertNotNull(pagingResults); + assertFalse(pagingResults.hasMoreItems()); + assertTrue((pagingResults.getQueryExecutionId() != null) && (pagingResults.getQueryExecutionId().length() > 0)); + assertNull(pagingResults.getTotalResultCount()); + + List files = pagingResults.getPage(); + + // check + String[] expectedNames = new String[] + { NAME_L0_FILE_A, NAME_L0_FILE_B, NAME_L0_FOLDER_A, NAME_L0_FOLDER_B, NAME_L0_FOLDER_C }; + checkFileList(files, 2, 3, expectedNames); + + + // empty list if skip count greater than number of results (ALF-7884) + pagingRequest = new PagingRequest(1000, 3, null); + pagingResults = fileFolderService.list(workingRootNodeRef, true, true, null, null, null, pagingRequest); + + assertNotNull(pagingResults); + assertFalse(pagingResults.hasMoreItems()); + assertEquals(0, pagingResults.getPage().size()); + + // TODO add more here + } + + public void testList_HiddenFiles() { // Test that hidden files are not returned for clients that should not be able to see them, // and that the total result count is correct. @@ -1417,4 +1423,104 @@ public class FileFolderServiceImplTest extends TestCase FileFilterMode.setClient(saveClient); } } + + public void testList_notCheckedOut_ALF_13602() + { + // Test that, eg. in the case of Share doclib, when listing files that have been checked-out we only list the working copy (ie. not the original checkedOut copy) + + int totalItems = 165; + int pageSize = 50; + + // create some files + NodeRef nodeRef = fileFolderService.create(workingRootNodeRef, "" + System.currentTimeMillis(), ContentModel.TYPE_CONTENT).getNodeRef(); + NodeRef nodeRef1 = fileFolderService.create(nodeRef, "parent", ContentModel.TYPE_CONTENT).getNodeRef(); + + NodeRef[] children = new NodeRef[totalItems]; + for (int i = 0; i < totalItems; i++) + { + String suffix = String.format("%05d", i); + children[i] = fileFolderService.create(nodeRef1, "child-" + suffix, ContentModel.TYPE_CONTENT).getNodeRef(); + } + + checkPages(nodeRef1, pageSize, totalItems, false, -1); + + // checkout 5th child + cociService.checkout(children[4]); + + checkPages(nodeRef1, pageSize, totalItems, false, 4); + + checkPages(nodeRef1, pageSize, totalItems, true, 4); + } + + private void checkPages(NodeRef parentRef, int pageSize, int totalItems, boolean hideCheckedOut, int checkedOutChildIdx) + { + Set ignoreQNameTypes = null; + if (hideCheckedOut) + { + ignoreQNameTypes = new HashSet(1); + ignoreQNameTypes.add(ContentModel.ASPECT_CHECKED_OUT); + } + else + { + if (checkedOutChildIdx > -1) + { + totalItems++; + } + } + + List> sortProps = new ArrayList>(1); + sortProps.add(new Pair(ContentModel.PROP_NAME, true)); + + int pageCount = (totalItems / pageSize) + 1; + + for (int i = 1; i <= pageCount; i++) + { + int offset = (i-1)*pageSize; + + PagingRequest pagingRequest = new PagingRequest(offset, pageSize); + pagingRequest.setRequestTotalCountMax(10000); // need this so that total count is set + + PagingResults results = fileFolderService.list(parentRef, true, true, ignoreQNameTypes, sortProps, pagingRequest); + + Pair totalResultCount = results.getTotalResultCount(); + assertNotNull(totalResultCount.getFirst()); + assertEquals(totalItems, totalResultCount.getFirst().intValue()); + assertNotNull(totalResultCount.getSecond()); + assertEquals(totalItems, totalResultCount.getSecond().intValue()); + + assertEquals((i != pageCount ? pageSize : (totalItems - ((pageCount-1)*pageSize))), results.getPage().size()); + + int j = offset; + for (FileInfo fileInfo : results.getPage()) + { + String suffix = String.format("%05d", j); + if (checkedOutChildIdx > -1) + { + if (! hideCheckedOut) + { + if (j == checkedOutChildIdx+1) + { + suffix = String.format("%05d", j-1) + " (Working Copy)"; + } + else if (j > checkedOutChildIdx+1) + { + suffix = String.format("%05d", j-1); + } + } + else + { + if (j == checkedOutChildIdx) + { + suffix = String.format("%05d", j) + " (Working Copy)"; + } + } + } + + String actual = fileInfo.getName(); + String expected = "child-"+suffix; + assertTrue("Expected: "+expected+", Actual: "+actual+" (j="+j+")", expected.equals(actual)); + j++; + } + } + } } diff --git a/source/java/org/alfresco/repo/model/filefolder/GetChildrenCannedQuery.java b/source/java/org/alfresco/repo/model/filefolder/GetChildrenCannedQuery.java index 30e157cf94..632abf95f5 100644 --- a/source/java/org/alfresco/repo/model/filefolder/GetChildrenCannedQuery.java +++ b/source/java/org/alfresco/repo/model/filefolder/GetChildrenCannedQuery.java @@ -22,6 +22,7 @@ import java.io.Serializable; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import org.alfresco.model.ContentModel; import org.alfresco.query.CannedQueryParameters; @@ -36,6 +37,7 @@ import org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityBean; import org.alfresco.repo.tenant.TenantService; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.namespace.QName; import org.alfresco.util.FileFilterMode; import org.alfresco.util.FileFilterMode.Client; @@ -46,7 +48,8 @@ import org.alfresco.util.FileFilterMode.Client; * To get paged list of files and folders of a parent folder filtered by child type. * Also optionally filtered and/or sorted by one or more properties (up to three). * - * This is the same as the nodes getchildren canned query, except it takes into account hidden files and folders. + * This is the same as the nodes getchildren canned query, except it takes into account hidden files and folders (with respect to client visibility) + * and other aspect(s) to ignore - eg. optionally "cm:checkedOut" in case of Share DocLib. * * @since 4.1.1 * @author steveglover, janv @@ -56,6 +59,8 @@ public class GetChildrenCannedQuery extends org.alfresco.repo.node.getchildren.G { private HiddenAspect hiddenAspect; private DictionaryService dictionaryService; + private NodeService nodeService; + private Set ignoreAspectQNames; public GetChildrenCannedQuery( NodeDAO nodeDAO, @@ -66,12 +71,17 @@ public class GetChildrenCannedQuery extends org.alfresco.repo.node.getchildren.G MethodSecurityBean methodSecurity, CannedQueryParameters params, HiddenAspect hiddenAspect, - DictionaryService dictionaryService) + DictionaryService dictionaryService, + NodeService nodeService, + Set ignoreAspectQNames) { super(nodeDAO, qnameDAO, cannedQueryDAO, nodePropertyHelper, tenantService, methodSecurity, params); this.hiddenAspect = hiddenAspect; this.dictionaryService = dictionaryService; + + this.nodeService = nodeService; + this.ignoreAspectQNames = ignoreAspectQNames; } @Override @@ -101,18 +111,7 @@ public class GetChildrenCannedQuery extends org.alfresco.repo.node.getchildren.G protected boolean include(FilterSortNode node) { boolean ret = super.include(node); - - // only visible files are returned, relative to the client type. - try - { - final Client client = FileFilterMode.getClient(); - return ret && hiddenAspect.getVisibility(client, node.getNodeRef()) != Visibility.NotVisible; - } - catch(AccessDeniedException e) - { - // user may not have permission to determine the visibility of the node - return ret; - } + return ret && includeImpl(ret, node.getNodeRef()); } @Override @@ -151,20 +150,42 @@ public class GetChildrenCannedQuery extends org.alfresco.repo.node.getchildren.G protected boolean include(NodeRef nodeRef) { boolean ret = super.include(nodeRef); - - // only visible files are returned, relative to the client type. - try - { - final Client client = FileFilterMode.getClient(); - return ret && hiddenAspect.getVisibility(client, nodeRef) != Visibility.NotVisible; - } - catch(AccessDeniedException e) - { - // user may not have permission to determine the visibility of the node - return ret; - } + + return ret && includeImpl(ret, nodeRef); } - } - + + protected boolean includeImpl(boolean ret, NodeRef nodeRef) + { + // only visible files are returned, relative to the client type. + try + { + final Client client = FileFilterMode.getClient(); + boolean notHidden = hiddenAspect.getVisibility(client, nodeRef) != Visibility.NotVisible; + + boolean notIgnore = true; + if (ignoreAspectQNames != null) + { + if (ignoreAspectQNames.size() > 1) + { + Set nodeAspects = nodeService.getAspects(nodeRef); + notIgnore = (! nodeAspects.removeAll(ignoreAspectQNames)); + } + else if (ignoreAspectQNames.size() == 1) + { + if (nodeService.hasAspect(nodeRef, ignoreAspectQNames.iterator().next())) + { + notIgnore = false; + } + } + } + + return ret && notHidden && notIgnore; + } + catch (AccessDeniedException e) + { + // user may not have permission to determine the visibility of the node + return ret; + } + } } diff --git a/source/java/org/alfresco/repo/model/filefolder/GetChildrenCannedQueryFactory.java b/source/java/org/alfresco/repo/model/filefolder/GetChildrenCannedQueryFactory.java index 5ac6871c27..78fd742381 100644 --- a/source/java/org/alfresco/repo/model/filefolder/GetChildrenCannedQueryFactory.java +++ b/source/java/org/alfresco/repo/model/filefolder/GetChildrenCannedQueryFactory.java @@ -18,32 +18,55 @@ */ package org.alfresco.repo.model.filefolder; +import java.util.List; +import java.util.Set; + import org.alfresco.query.CannedQuery; import org.alfresco.query.CannedQueryParameters; +import org.alfresco.query.PagingRequest; import org.alfresco.repo.domain.node.NodePropertyHelper; +import org.alfresco.repo.node.getchildren.FilterProp; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.Pair; /** * GetChidren canned query factory for files and folders. * * @since 4.1.1 - * @author steveglover + * @author steveglover, janv * */ public class GetChildrenCannedQueryFactory extends org.alfresco.repo.node.getchildren.GetChildrenCannedQueryFactory { private HiddenAspect hiddenAspect; + private Set ignoreAspectQNames; + + protected NodeService nodeService; + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } public void setHiddenAspect(HiddenAspect hiddenAspect) { - this.hiddenAspect = hiddenAspect; - } - + this.hiddenAspect = hiddenAspect; + } + + public CannedQuery getCannedQuery(NodeRef parentRef, String pattern, Set assocTypeQNames, Set childTypeQNames, Set ignoreAspectQNames, List filterProps, List> sortProps, PagingRequest pagingRequest) + { + this.ignoreAspectQNames = ignoreAspectQNames; + + return super.getCannedQuery(parentRef, pattern, assocTypeQNames, childTypeQNames, filterProps, sortProps, pagingRequest); + } + @Override public CannedQuery getCannedQuery(CannedQueryParameters parameters) { NodePropertyHelper nodePropertyHelper = new NodePropertyHelper(dictionaryService, qnameDAO, localeDAO, contentDataDAO); - return (CannedQuery) new GetChildrenCannedQuery(nodeDAO, qnameDAO, cannedQueryDAO, nodePropertyHelper, tenantService, methodSecurity, parameters, hiddenAspect, dictionaryService); + return (CannedQuery) new GetChildrenCannedQuery(nodeDAO, qnameDAO, cannedQueryDAO, nodePropertyHelper, tenantService, methodSecurity, parameters, hiddenAspect, dictionaryService, nodeService, ignoreAspectQNames); } } diff --git a/source/java/org/alfresco/repo/model/ml/tools/EditionServiceImplTest.java b/source/java/org/alfresco/repo/model/ml/tools/EditionServiceImplTest.java index f24e0cceb1..9fdc9b2f1c 100644 --- a/source/java/org/alfresco/repo/model/ml/tools/EditionServiceImplTest.java +++ b/source/java/org/alfresco/repo/model/ml/tools/EditionServiceImplTest.java @@ -80,7 +80,7 @@ public class EditionServiceImplTest extends AbstractMultilingualTestCases Version rootEdition = editionService.getEditions(mlContainerNodeRef).getAllVersions().iterator().next(); // Ensure that the version label is 1.0 - assertTrue("The edition label would be 0.1 and not " + rootEdition.getVersionLabel(), rootEdition.getVersionLabel().equals("0.1")); + assertTrue("The edition label would be 1.0 and not " + rootEdition.getVersionLabel(), rootEdition.getVersionLabel().equals("1.0")); /* * default (1.1) @@ -90,7 +90,7 @@ public class EditionServiceImplTest extends AbstractMultilingualTestCases editions = new ArrayList(editionService.getEditions(mlContainerNodeRef).getAllVersions()); Version firstEdition = editions.get(0); // Ensure that the version label is 1.1 - assertTrue("The edition label would be 0.2 and not " + firstEdition.getVersionLabel(), firstEdition.getVersionLabel().equals("0.2")); + assertTrue("The edition label would be 1.1 and not " + firstEdition.getVersionLabel(), firstEdition.getVersionLabel().equals("1.1")); /* * major (2.0) @@ -101,8 +101,8 @@ public class EditionServiceImplTest extends AbstractMultilingualTestCases pivot = editionService.createEdition(pivot, versionProperties); editions = new ArrayList(editionService.getEditions(mlContainerNodeRef).getAllVersions()); Version secondEdition = editions.get(0); - // Ensure that the version label is 1.0 - assertTrue("The edition label would be 1.0 and not " + secondEdition.getVersionLabel(), secondEdition.getVersionLabel().equals("1.0")); + // Ensure that the version label is 2.0 + assertTrue("The edition label would be 2.0 and not " + secondEdition.getVersionLabel(), secondEdition.getVersionLabel().equals("2.0")); /* * minor (2.1) @@ -114,7 +114,7 @@ public class EditionServiceImplTest extends AbstractMultilingualTestCases editions = new ArrayList(editionService.getEditions(mlContainerNodeRef).getAllVersions()); Version thirdEdition = editions.get(0); // Ensure that the version label is 2.1 - assertTrue("The edition label would be 1.1 and not " + thirdEdition.getVersionLabel(), thirdEdition.getVersionLabel().equals("1.1")); + assertTrue("The edition label would be 2.1 and not " + thirdEdition.getVersionLabel(), thirdEdition.getVersionLabel().equals("2.1")); } public void testCreateEdition() throws Exception @@ -138,8 +138,8 @@ public class EditionServiceImplTest extends AbstractMultilingualTestCases assertTrue("The locale of the conatiner should be changed", nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE).equals(Locale.FRENCH)); // get the two editions - Version rootEdition = editionHistory.getVersion("0.1"); - Version actualEdition = editionHistory.getVersion("0.2"); + Version rootEdition = editionHistory.getVersion("1.0"); + Version actualEdition = editionHistory.getVersion("1.1"); // get the translations of the root versions List rootVersionTranslations = editionService.getVersionedTranslations(rootEdition); @@ -181,7 +181,7 @@ public class EditionServiceImplTest extends AbstractMultilingualTestCases public void testEditionServiceWithContent() { // create a mlContainer with some content - NodeRef mlContainerNodeRef = createMLContainerWithContent("0.1"); + NodeRef mlContainerNodeRef = createMLContainerWithContent("1.0"); // get the french translation NodeRef frenchContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.FRENCH); @@ -189,24 +189,24 @@ public class EditionServiceImplTest extends AbstractMultilingualTestCases // create a new edition starting from the french translation NodeRef newStartingPoint = editionService.createEdition(frenchContentNodeRef, null); frenchContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.FRENCH); - modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "0.2" + "-" + "0.2"); + modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.1" + "-" + "0.2"); checkContentVersionValuesForEditions(mlContainerNodeRef); - modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "0.2" + "-" + "0.3"); + modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.1" + "-" + "0.3"); checkContentVersionValuesForEditions(mlContainerNodeRef); - modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "0.2" + "-" + "0.4"); + modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.1" + "-" + "0.4"); // checkContentVersionValuesForEditions(mlContainerNodeRef); frenchContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.FRENCH); newStartingPoint = editionService.createEdition(frenchContentNodeRef, null); frenchContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.FRENCH); - modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "0.3" + "-" + "0.2"); + modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.2" + "-" + "0.2"); checkContentVersionValuesForEditions(mlContainerNodeRef); - modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "0.3" + "-" + "0.3"); + modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.2" + "-" + "0.3"); checkContentVersionValuesForEditions(mlContainerNodeRef); - NodeRef chineseContentNodeRef = createContent(CHINESE_CONTENT + "-" + Locale.CHINESE + "-" + "0.3" + "-0.1"); + NodeRef chineseContentNodeRef = createContent(CHINESE_CONTENT + "-" + Locale.CHINESE + "-" + "1.2" + "-1.0"); multilingualContentService.addTranslation(chineseContentNodeRef, mlContainerNodeRef, Locale.CHINESE); checkContentVersionValuesForEditions(mlContainerNodeRef); - NodeRef japaneseContentNodeRef = createContent(JAPANESE_CONTENT + "-" + Locale.JAPANESE + "-" + "0.3" + "-0.1"); + NodeRef japaneseContentNodeRef = createContent(JAPANESE_CONTENT + "-" + Locale.JAPANESE + "-" + "1.2" + "-1.0"); multilingualContentService.addTranslation(japaneseContentNodeRef, mlContainerNodeRef, Locale.JAPANESE); checkContentVersionValuesForEditions(mlContainerNodeRef); @@ -216,19 +216,19 @@ public class EditionServiceImplTest extends AbstractMultilingualTestCases checkContentVersionValuesForEditions(mlContainerNodeRef); japaneseContentNodeRef = multilingualContentService .getTranslationForLocale(mlContainerNodeRef, Locale.JAPANESE); - modifyContent(japaneseContentNodeRef, JAPANESE_CONTENT + "-" + Locale.JAPANESE + "-" + "0.4" + "-0.2"); - chineseContentNodeRef = createContent(CHINESE_CONTENT + "-" + Locale.CHINESE + "-" + "0.4" + "-0.1"); + modifyContent(japaneseContentNodeRef, JAPANESE_CONTENT + "-" + Locale.JAPANESE + "-" + "1.3" + "-0.2"); + chineseContentNodeRef = createContent(CHINESE_CONTENT + "-" + Locale.CHINESE + "-" + "1.3" + "-1.0"); multilingualContentService.addTranslation(chineseContentNodeRef, mlContainerNodeRef, Locale.CHINESE); checkContentVersionValuesForEditions(mlContainerNodeRef); - frenchContentNodeRef = createContent(FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "0.4" + "-0.1"); + frenchContentNodeRef = createContent(FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.3" + "-1.0"); multilingualContentService.addTranslation(frenchContentNodeRef, mlContainerNodeRef, Locale.FRENCH); checkContentVersionValuesForEditions(mlContainerNodeRef); frenchContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.FRENCH); newStartingPoint = editionService.createEdition(frenchContentNodeRef, null); frenchContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.FRENCH); - modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "0.5" + "-" + "0.2"); + modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.4" + "-" + "0.2"); checkContentVersionValuesForEditions(mlContainerNodeRef); @@ -241,9 +241,9 @@ public class EditionServiceImplTest extends AbstractMultilingualTestCases Version secondEdition = editions.iterator().next(); // Ensure that the version label is 2.0 assertTrue("The edition label would be 2.0 and not " + secondEdition.getVersionLabel(), secondEdition - .getVersionLabel().equals("1.0")); - frenchContentNodeRef = createContent(FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.0" + "-0.1"); - modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.0" + "-" + "0.2"); + .getVersionLabel().equals("2.0")); + frenchContentNodeRef = createContent(FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.0" + "-1.0"); + modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.0" + "-" + "1.1"); checkContentVersionValuesForEditions(mlContainerNodeRef); frenchContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.FRENCH); @@ -254,10 +254,10 @@ public class EditionServiceImplTest extends AbstractMultilingualTestCases editions = editionService.getEditions(mlContainerNodeRef).getAllVersions(); secondEdition = editions.iterator().next(); - // Ensure that the version label is 2.0 + // Ensure that the version label is 3.0 assertTrue("The edition label would be 3.0 and not " + secondEdition.getVersionLabel(), secondEdition - .getVersionLabel().equals("2.0")); - modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "2.0" + "-" + "0.2"); + .getVersionLabel().equals("3.0")); + modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "3.0" + "-" + "0.2"); checkContentVersionValuesForEditions(mlContainerNodeRef); @@ -404,9 +404,9 @@ public class EditionServiceImplTest extends AbstractMultilingualTestCases { // it is not a root version therefore it should respect the conventions Triplet testTriplet = new Triplet(versionnedContent); - assertTrue(testTriplet.locale.equals(versionLocale.toString())); - assertTrue(testTriplet.edition.equals(editionLabel)); - assertTrue(testTriplet.version.equals(versionLabel)); + assertEquals(testTriplet.locale, versionLocale.toString()); + assertEquals(testTriplet.edition, editionLabel); + assertEquals(testTriplet.version, versionLabel); } } @@ -504,11 +504,11 @@ public class EditionServiceImplTest extends AbstractMultilingualTestCases NodeRef createMLContainerWithContent(String editionSuffix) { NodeRef chineseContentNodeRef = createContent(CHINESE_CONTENT + "-" + Locale.CHINESE + "-" + editionSuffix - + "-0.1"); + + "-1.0"); NodeRef frenchContentNodeRef = createContent(FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + editionSuffix - + "-0.1"); + + "-1.0"); NodeRef japaneseContentNodeRef = createContent(JAPANESE_CONTENT + "-" + Locale.JAPANESE + "-" + editionSuffix - + "-0.1"); + + "-1.0"); multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE); multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH); diff --git a/source/java/org/alfresco/repo/module/ModuleDetailsImpl.java b/source/java/org/alfresco/repo/module/ModuleDetailsImpl.java index b016ca7672..fe01dfe55b 100644 --- a/source/java/org/alfresco/repo/module/ModuleDetailsImpl.java +++ b/source/java/org/alfresco/repo/module/ModuleDetailsImpl.java @@ -32,7 +32,6 @@ import org.alfresco.service.cmr.module.ModuleInstallState; import org.springframework.extensions.surf.util.ISO8601DateFormat; import org.alfresco.util.Pair; import org.alfresco.util.VersionNumber; -import org.apache.commons.lang.StringUtils; /** * Module details implementation. @@ -283,7 +282,7 @@ public class ModuleDetailsImpl implements ModuleDetails } if (editions != null) { - properties.setProperty(PROP_EDITIONS, StringUtils.join(editions,",")); + properties.setProperty(PROP_EDITIONS, join(editions.toArray(new String[editions.size()]), ',')); } if (dependencies.size() > 0) { @@ -409,6 +408,49 @@ public class ModuleDetailsImpl implements ModuleDetails this.editions = editions; } + /** + * Grateful received from Apache Commons StringUtils class + * + */ + private static String join(Object[] array, char separator) { + if (array == null) { + return null; + } + return join(array, separator, 0, array.length); + } + + /** + * Grateful received from Apache Commons StringUtils class + * + * @param array + * @param separator + * @param startIndex + * @param endIndex + * @return + */ + private static String join(Object[] array, char separator, int startIndex, int endIndex) { + if (array == null) { + return null; + } + int bufSize = (endIndex - startIndex); + if (bufSize <= 0) { + return ""; + } + + bufSize *= ((array[startIndex] == null ? 16 : array[startIndex].toString().length()) + 1); + StringBuffer buf = new StringBuffer(bufSize); + + for (int i = startIndex; i < endIndex; i++) { + if (i > startIndex) { + buf.append(separator); + } + if (array[i] != null) { + buf.append(array[i]); + } + } + return buf.toString(); + } + /** * @author Derek Hulley */ diff --git a/source/java/org/alfresco/repo/subscriptions/SubscriptionServiceActivitiesTest.java b/source/java/org/alfresco/repo/subscriptions/SubscriptionServiceActivitiesTest.java index 54c1dbf88a..5482788431 100644 --- a/source/java/org/alfresco/repo/subscriptions/SubscriptionServiceActivitiesTest.java +++ b/source/java/org/alfresco/repo/subscriptions/SubscriptionServiceActivitiesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2011 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -18,8 +18,11 @@ */ package org.alfresco.repo.subscriptions; +import java.io.Serializable; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import junit.framework.TestCase; @@ -27,11 +30,23 @@ import org.alfresco.model.ContentModel; import org.alfresco.repo.activities.feed.FeedGenerator; import org.alfresco.repo.activities.feed.local.LocalFeedTaskProcessor; import org.alfresco.repo.activities.post.lookup.PostLookup; +import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.site.SiteModel; +import org.alfresco.service.cmr.activities.ActivityService; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.service.cmr.site.SiteVisibility; import org.alfresco.service.cmr.subscriptions.SubscriptionService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; import org.alfresco.util.ApplicationContextHelper; import org.alfresco.util.PropertyMap; import org.quartz.Scheduler; @@ -42,13 +57,17 @@ public class SubscriptionServiceActivitiesTest extends TestCase // Location of activity type templates (for site activities) // assumes test-resources is on classpath protected static final String TEST_TEMPLATES_LOCATION = "activities"; - + protected ApplicationContext ctx = ApplicationContextHelper.getApplicationContext(); protected SubscriptionService subscriptionService; protected PersonService personService; + protected SiteService siteService; + protected ActivityService activityService; + protected NodeService nodeService; + protected ContentService contentService; protected PostLookup postLookup; protected FeedGenerator feedGenerator; - + @Override public void setUp() throws Exception { @@ -57,58 +76,155 @@ public class SubscriptionServiceActivitiesTest extends TestCase // feed generator jobs Scheduler scheduler = (Scheduler) ctx.getBean("schedulerFactory"); scheduler.shutdown(); - + // Get the required services subscriptionService = (SubscriptionService) ctx.getBean("SubscriptionService"); personService = (PersonService) ctx.getBean("PersonService"); - + siteService = (SiteService) ctx.getBean("SiteService"); + activityService = (ActivityService) ctx.getBean("activityService"); + nodeService = (NodeService) ctx.getBean("NodeService"); + contentService = (ContentService) ctx.getBean("ContentService"); + ChildApplicationContextFactory activitiesFeed = (ChildApplicationContextFactory) ctx.getBean("ActivitiesFeed"); ApplicationContext activitiesFeedCtx = activitiesFeed.getApplicationContext(); postLookup = (PostLookup) activitiesFeedCtx.getBean("postLookup"); feedGenerator = (FeedGenerator) activitiesFeedCtx.getBean("feedGenerator"); - + LocalFeedTaskProcessor feedProcessor = (LocalFeedTaskProcessor) activitiesFeedCtx.getBean("feedTaskProcessor"); - + List templateSearchPaths = new ArrayList(1); templateSearchPaths.add(TEST_TEMPLATES_LOCATION); feedProcessor.setTemplateSearchPaths(templateSearchPaths); feedProcessor.setUseRemoteCallbacks(false); - - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName()); } - + protected void deletePerson(String userId) { personService.deletePerson(userId); } - + protected NodeRef createPerson(String userId) { deletePerson(userId); - + PropertyMap properties = new PropertyMap(5); properties.put(ContentModel.PROP_USERNAME, userId); properties.put(ContentModel.PROP_FIRSTNAME, userId); properties.put(ContentModel.PROP_LASTNAME, "Test"); properties.put(ContentModel.PROP_EMAIL, userId + "@email.com"); - + return personService.createPerson(properties); } - + + protected void deleteSite(String siteId) + { + if (siteService.getSite(siteId) != null) + { + siteService.deleteSite(siteId); + } + } + + protected SiteInfo createSite(String siteId, SiteVisibility visibility) + { + deleteSite(siteId); + return siteService.createSite("sitePreset", siteId, null, null, visibility); + } + + protected NodeRef addTextContent(String siteId, String name) + { + String textData = name; + String mimeType = MimetypeMap.MIMETYPE_TEXT_PLAIN; + + Map contentProps = new HashMap(); + contentProps.put(ContentModel.PROP_NAME, name); + + // ensure that the Document Library folder is pre-created so that test code can start creating content straight away. + // At the time of writing V4.1 does not create this folder automatically, but Thor does + NodeRef parentRef = siteService.getContainer(siteId, SiteService.DOCUMENT_LIBRARY); + if (parentRef == null) + { + parentRef = siteService.createContainer(siteId, SiteService.DOCUMENT_LIBRARY, ContentModel.TYPE_FOLDER, null); + } + + ChildAssociationRef association = nodeService.createNode(parentRef, + ContentModel.ASSOC_CONTAINS, + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, name), + ContentModel.TYPE_CONTENT, + contentProps); + + NodeRef content = association.getChildRef(); + + // add titled aspect (for Web Client display) + Map titledProps = new HashMap(); + titledProps.put(ContentModel.PROP_TITLE, name); + titledProps.put(ContentModel.PROP_DESCRIPTION, name); + this.nodeService.addAspect(content, ContentModel.ASPECT_TITLED, titledProps); + + ContentWriter writer = contentService.getWriter(content, ContentModel.PROP_CONTENT, true); + + writer.setMimetype(mimeType); + writer.setEncoding("UTF-8"); + + writer.putContent(textData); + + activityService.postActivity("org.alfresco.documentlibrary.file-added", siteId, "documentlibrary", content, name, ContentModel.PROP_CONTENT, parentRef); + + return content; + } + protected void generateFeed() throws Exception { postLookup.execute(); feedGenerator.execute(); } - + public void testFollowingActivity() throws Exception { final String userId1 = "bob"; final String userId2 = "tom"; - - createPerson(userId1); - createPerson(userId2); - + + AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() + { + @Override + public Object doWork() throws Exception + { + createPerson(userId1); + createPerson(userId2); + + createSite(userId1+"pub", SiteVisibility.PUBLIC); + siteService.setMembership(userId1+"pub", userId1, SiteModel.SITE_MANAGER); + + createSite(userId1+"priv1", SiteVisibility.PRIVATE); + siteService.setMembership(userId1+"priv1", userId1, SiteModel.SITE_MANAGER); + + createSite(userId1+"priv2", SiteVisibility.PRIVATE); + siteService.setMembership(userId1+"priv2", userId1, SiteModel.SITE_MANAGER); + + createSite(userId1+"mod1", SiteVisibility.MODERATED); + siteService.setMembership(userId1+"mod1", userId1, SiteModel.SITE_MANAGER); + + createSite(userId1+"mod2", SiteVisibility.MODERATED); + siteService.setMembership(userId1+"mod2", userId1, SiteModel.SITE_MANAGER); + + return null; + } + }, AuthenticationUtil.getAdminUserName()); + + List feed = activityService.getUserFeedEntries(userId1, "json", null, false, false, null, null); + assertEquals(feed.toString(), 0, feed.size()); + + feed = activityService.getUserFeedEntries(userId2, "json", null, false, false, null, null); + assertEquals(feed.toString(), 0, feed.size()); + + // userId1 + 5, userId2 + 0 + generateFeed(); + + feed = activityService.getUserFeedEntries(userId1, "json", null, false, false, null, null); + assertEquals(feed.toString(), 5, feed.size()); + + feed = activityService.getUserFeedEntries(userId2, "json", null, false, false, null, null); + assertEquals(feed.toString(), 0, feed.size()); + AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() { @Override @@ -118,7 +234,7 @@ public class SubscriptionServiceActivitiesTest extends TestCase return null; } }, userId1); - + AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() { @Override @@ -128,10 +244,124 @@ public class SubscriptionServiceActivitiesTest extends TestCase return null; } }, userId2); - + + // userId1 + 5, userId2 + 2 generateFeed(); - - deletePerson(userId1); - deletePerson(userId2); + + feed = activityService.getUserFeedEntries(userId1, "json", null, false, false, null, null); + assertEquals(feed.toString(), 7, feed.size()); + + feed = activityService.getUserFeedEntries(userId2, "json", null, false, false, null, null); + assertEquals(feed.toString(), 2, feed.size()); + + AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() + { + @Override + public Object doWork() throws Exception + { + addTextContent(userId1+"pub", userId1+"pub-a"); + addTextContent(userId1+"priv1", userId1+"priv1-a"); + addTextContent(userId1+"priv2", userId1+"priv2-a"); + addTextContent(userId1+"mod1", userId1+"mod1-a"); + addTextContent(userId1+"mod2", userId1+"mod2-a"); + return null; + } + }, userId1); + + // userId1 + 5, userId2 + 1 + generateFeed(); + + feed = activityService.getUserFeedEntries(userId1, "json", null, false, false, null, null); + assertEquals(feed.toString(), 12, feed.size()); + + // note: userId2 should not see activities from followers in moderated sites that they do not belong do (ALF-16460) + feed = activityService.getUserFeedEntries(userId2, "json", null, false, false, null, null); + assertEquals(feed.toString(), 3, feed.size()); + + AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() + { + @Override + public Object doWork() throws Exception + { + siteService.setMembership(userId1+"priv2", userId2, SiteModel.SITE_CONSUMER); + siteService.setMembership(userId1+"mod2", userId2, SiteModel.SITE_MANAGER); + + return null; + } + }, AuthenticationUtil.getAdminUserName()); + + // userId1 + 2, userId2 + 2 + generateFeed(); + + feed = activityService.getUserFeedEntries(userId1, "json", null, false, false, null, null); + assertEquals(feed.toString(), 14, feed.size()); + + // note: userId2 should not see activities from followers in moderated sites that they do not belong do (ALF-16460) + feed = activityService.getUserFeedEntries(userId2, "json", null, false, false, null, null); + assertEquals(feed.toString(), 5, feed.size()); + + AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() + { + @Override + public Object doWork() throws Exception + { + addTextContent(userId1+"pub", userId1+"pub-b"); + addTextContent(userId1+"priv1", userId1+"priv1-b"); + addTextContent(userId1+"priv2", userId1+"priv2-b"); + addTextContent(userId1+"mod1", userId1+"mod1-b"); + addTextContent(userId1+"mod2", userId1+"mod2-b"); + + return null; + } + }, userId1); + + // userId1 + 5, userId2 + 3 + generateFeed(); + + feed = activityService.getUserFeedEntries(userId1, "json", null, false, false, null, null); + assertEquals(feed.toString(), 19, feed.size()); + + // note: userId2 should not see activities from followers in moderated sites that they do not belong do (ALF-16460) + feed = activityService.getUserFeedEntries(userId2, "json", null, false, false, null, null); + assertEquals(feed.toString(), 8, feed.size()); + + AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() + { + @Override + public Object doWork() throws Exception + { + deleteSite(userId1+"pub"); + deleteSite(userId1+"priv1"); + deleteSite(userId1+"priv2"); + deleteSite(userId1+"mod1"); + deleteSite(userId1+"mod2"); + + return null; + } + }, AuthenticationUtil.getAdminUserName()); + + feed = activityService.getUserFeedEntries(userId1, "json", null, false, false, null, null); + assertEquals(feed.toString(), 2, feed.size()); + + feed = activityService.getUserFeedEntries(userId2, "json", null, false, false, null, null); + assertEquals(feed.toString(), 2, feed.size()); + + AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() + { + @Override + public Object doWork() throws Exception + { + deletePerson(userId1); + deletePerson(userId2); + + return null; + } + }, AuthenticationUtil.getAdminUserName()); + + feed = activityService.getUserFeedEntries(userId1, "json", null, false, false, null, null); + assertEquals(feed.toString(), 0, feed.size()); + + feed = activityService.getUserFeedEntries(userId2, "json", null, false, false, null, null); + assertEquals(feed.toString(), 0, feed.size()); } } diff --git a/source/java/org/alfresco/repo/version/VersionServiceImplTest.java b/source/java/org/alfresco/repo/version/VersionServiceImplTest.java index a6807ad5ef..0a979c290c 100644 --- a/source/java/org/alfresco/repo/version/VersionServiceImplTest.java +++ b/source/java/org/alfresco/repo/version/VersionServiceImplTest.java @@ -1081,7 +1081,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest NodeRef nodeRef = createNodeWithVersionType(null); setComplete(); endTransaction(); - assertCorrectVersionLabel(nodeRef, "0.1"); + assertCorrectVersionLabel(nodeRef, "1.0"); } public void testAddVersionableAspectWithMinorVersionType() @@ -1400,8 +1400,8 @@ public class VersionServiceImplTest extends BaseVersionStoreTest // Check version labels, should be 0.2 and 0.1 as property changes // are minor updates, and we had no initial label set Version[] versions = versionHistory.getAllVersions().toArray(new Version[2]); - assertEquals("0.2", versions[0].getVersionLabel()); - assertEquals("0.1", versions[1].getVersionLabel()); + assertEquals("1.1", versions[0].getVersionLabel()); + assertEquals("1.0", versions[1].getVersionLabel()); return null; } @@ -1486,9 +1486,9 @@ public class VersionServiceImplTest extends BaseVersionStoreTest // Check the versions, Version[] versions = versionHistory.getAllVersions().toArray(new Version[3]); - assertEquals("0.3", versions[0].getVersionLabel()); - assertEquals("0.2", versions[1].getVersionLabel()); - assertEquals("0.1", versions[2].getVersionLabel()); + assertEquals("1.2", versions[0].getVersionLabel()); + assertEquals("1.1", versions[1].getVersionLabel()); + assertEquals("1.0", versions[2].getVersionLabel()); return null; } @@ -1503,7 +1503,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest Version[] versions = versionHistory.getAllVersions().toArray(new Version[3]); Version v = versions[1]; - assertEquals("0.2", v.getVersionLabel()); + assertEquals("1.1", v.getVersionLabel()); versionService.deleteVersion(versionableNode, v); return null; } @@ -1518,8 +1518,8 @@ public class VersionServiceImplTest extends BaseVersionStoreTest // Check the versions, will now have a gap Version[] versions = versionHistory.getAllVersions().toArray(new Version[2]); - assertEquals("0.3", versions[0].getVersionLabel()); - assertEquals("0.1", versions[1].getVersionLabel()); + assertEquals("1.2", versions[0].getVersionLabel()); + assertEquals("1.0", versions[1].getVersionLabel()); return null; } }); @@ -1530,7 +1530,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest public Object execute() throws Exception { Version v = versionService.getCurrentVersion(versionableNode); - assertEquals("0.3", v.getVersionLabel()); + assertEquals("1.2", v.getVersionLabel()); versionService.deleteVersion(versionableNode, v); return null; } @@ -1545,7 +1545,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest // Check the version Version[] versions = versionHistory.getAllVersions().toArray(new Version[1]); - assertEquals("0.1", versions[0].getVersionLabel()); + assertEquals("1.0", versions[0].getVersionLabel()); return null; } }); diff --git a/source/java/org/alfresco/repo/version/VersionableAspect.java b/source/java/org/alfresco/repo/version/VersionableAspect.java index 3d3551bb2a..d4a90b808a 100644 --- a/source/java/org/alfresco/repo/version/VersionableAspect.java +++ b/source/java/org/alfresco/repo/version/VersionableAspect.java @@ -380,9 +380,9 @@ public class VersionableAspect implements ContentServicePolicies.OnContentUpdate // If a major version is requested, indicate it in the versionProperties map String versionType = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_VERSION_TYPE); - if (versionType != null && versionType.equals(VersionType.MAJOR.toString())) + if (versionType == null || !versionType.equals(VersionType.MINOR.toString())) { - versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR); + versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR); } versionProperties.put(Version.PROP_DESCRIPTION, I18NUtil.getMessage(MSG_INITIAL_VERSION));