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));