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