Merged HEAD-BUG-FIX (5.0/Cloud) to HEAD (5.0/Cloud)

82375: Merged WAT2 (5.0/Cloud) to HEAD-BUG-FIX (5.0/Cloud)
      76480: Re-worked download activity posting following Kev's changes


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@83218 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Erik Winlof
2014-09-04 06:50:52 +00:00
parent a8aac98030
commit 5dc1d70853
8 changed files with 315 additions and 234 deletions

View File

@@ -24,5 +24,18 @@
</list> </list>
</property> </property>
</bean> </bean>
<bean id="activitiesPoster" class="org.alfresco.repo.management.subsystems.SubsystemProxyFactory">
<property name="sourceApplicationContextFactory">
<ref bean="ActivitiesFeed"/>
</property>
<property name="sourceBeanName">
<value>ffActivitiesPoster</value>
</property>
<property name="interfaces">
<list>
<value>org.alfresco.service.cmr.activities.ActivityPoster</value>
</list>
</property>
</bean>
</beans> </beans>

View File

@@ -115,7 +115,7 @@
</bean> </bean>
<bean id="cmisActivityPoster" class="org.alfresco.opencmis.ActivityPosterImpl"> <bean id="cmisActivityPoster" class="org.alfresco.opencmis.ActivityPosterImpl">
<property name="activityService" ref="activityService" /> <property name="poster" ref="activitiesPoster" />
<property name="siteService" ref="SiteService" /> <property name="siteService" ref="SiteService" />
<property name="tenantService" ref="tenantService" /> <property name="tenantService" ref="tenantService" />
<property name="nodeService" ref="NodeService" /> <property name="nodeService" ref="NodeService" />

View File

@@ -26,6 +26,10 @@
<property name="maxFeedItems" value="${activities.feed.max.size}"/> <property name="maxFeedItems" value="${activities.feed.max.size}"/>
</bean> </bean>
<bean id="ffActivitiesPoster" class="org.alfresco.service.cmr.activities.FileFolderActivityPosterImpl">
<property name="activityService" ref="activityService" />
</bean>
<!-- cleans out-of-date feed entries --> <!-- cleans out-of-date feed entries -->
<bean id="feedCleaner" class="org.alfresco.repo.activities.feed.cleanup.FeedCleaner" init-method="init"> <bean id="feedCleaner" class="org.alfresco.repo.activities.feed.cleanup.FeedCleaner" init-method="init">
<property name="feedDAO" ref="feedDAO"/> <property name="feedDAO" ref="feedDAO"/>

View File

@@ -20,14 +20,13 @@ package org.alfresco.opencmis;
import java.util.List; import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.Client; import org.alfresco.repo.Client;
import org.alfresco.repo.Client.ClientType; import org.alfresco.repo.Client.ClientType;
import org.alfresco.repo.activities.ActivityType; import org.alfresco.repo.activities.ActivityType;
import org.alfresco.repo.model.filefolder.HiddenAspect; import org.alfresco.repo.model.filefolder.HiddenAspect;
import org.alfresco.repo.tenant.TenantService; import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.activities.ActivityService; import org.alfresco.service.cmr.activities.ActivityPoster;
import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileFolderServiceType; import org.alfresco.service.cmr.model.FileFolderServiceType;
import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.model.FileInfo;
@@ -40,26 +39,23 @@ import org.alfresco.service.namespace.QName;
import org.alfresco.util.PropertyCheck; import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
/** /**
* OpenCMIS methods may use an instance of this class to post activity data. * OpenCMIS methods may use an instance of this class to post activity data.
* *
* @see ActivityPoster * @see CmisActivityPoster
* @author sglover * @author sglover
*/ */
// TODO consolidate with ActivityPost for WebDAV public class ActivityPosterImpl implements CmisActivityPoster, InitializingBean
public class ActivityPosterImpl implements ActivityPoster, InitializingBean
{ {
private static final String APP_TOOL = "CMIS"; private static final String APP_TOOL = "CMIS";
public static final char PathSeperatorChar = '/'; public static final char PathSeperatorChar = '/';
// Logging // Logging
private static Log logger = LogFactory.getLog(ActivityPoster.class); private static Log logger = LogFactory.getLog(CmisActivityPoster.class);
private ActivityService activityService; private ActivityPoster poster;
private SiteService siteService; private SiteService siteService;
private TenantService tenantService; private TenantService tenantService;
private NodeService nodeService; private NodeService nodeService;
@@ -68,48 +64,48 @@ public class ActivityPosterImpl implements ActivityPoster, InitializingBean
private boolean activitiesEnabled = true; private boolean activitiesEnabled = true;
/** /**
* Constructor * Constructor
*/ */
public ActivityPosterImpl() public ActivityPosterImpl()
{ {
} }
public void setHiddenAspect(HiddenAspect hiddenAspect) public void setHiddenAspect(HiddenAspect hiddenAspect)
{
this.hiddenAspect = hiddenAspect;
}
public void setFileFolderService(FileFolderService fileFolderService)
{ {
this.fileFolderService = fileFolderService; this.hiddenAspect = hiddenAspect;
} }
public void setTenantService(TenantService tenantService) public void setFileFolderService(FileFolderService fileFolderService)
{
this.tenantService = tenantService;
}
public void setSiteService(SiteService siteService)
{ {
this.siteService = siteService; this.fileFolderService = fileFolderService;
} }
public void setNodeService(NodeService nodeService) public void setTenantService(TenantService tenantService)
{
this.nodeService = nodeService;
}
public void setActivityService(ActivityService activityService)
{ {
this.activityService = activityService; this.tenantService = tenantService;
} }
public void setActivitiesEnabled(boolean activitiesEnabled) public void setSiteService(SiteService siteService)
{ {
this.activitiesEnabled = activitiesEnabled; this.siteService = siteService;
} }
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setActivitiesEnabled(boolean activitiesEnabled)
{
this.activitiesEnabled = activitiesEnabled;
}
public void setPoster(ActivityPoster poster)
{
this.poster = poster;
}
private final String getPathFromNode(NodeRef rootNodeRef, NodeRef nodeRef) throws FileNotFoundException private final String getPathFromNode(NodeRef rootNodeRef, NodeRef nodeRef) throws FileNotFoundException
{ {
// Check if the nodes are valid, or equal // Check if the nodes are valid, or equal
@@ -147,12 +143,12 @@ public class ActivityPosterImpl implements ActivityPoster, InitializingBean
*/ */
public void afterPropertiesSet() throws Exception public void afterPropertiesSet() throws Exception
{ {
PropertyCheck.mandatory(this, "activityService", activityService); PropertyCheck.mandatory(this, "poster", poster);
PropertyCheck.mandatory(this, "siteService", siteService); PropertyCheck.mandatory(this, "siteService", siteService);
PropertyCheck.mandatory(this, "tenantService", tenantService); PropertyCheck.mandatory(this, "tenantService", tenantService);
PropertyCheck.mandatory(this, "nodeService", nodeService); PropertyCheck.mandatory(this, "nodeService", nodeService);
PropertyCheck.mandatory(this, "fileFolderService", fileFolderService); PropertyCheck.mandatory(this, "fileFolderService", fileFolderService);
} }
private String getCurrentTenantDomain() private String getCurrentTenantDomain()
{ {
@@ -166,10 +162,10 @@ public class ActivityPosterImpl implements ActivityPoster, InitializingBean
private boolean isFolder(NodeRef nodeRef) private boolean isFolder(NodeRef nodeRef)
{ {
QName typeQName = nodeService.getType(nodeRef); QName typeQName = nodeService.getType(nodeRef);
FileFolderServiceType type = fileFolderService.getType(typeQName); FileFolderServiceType type = fileFolderService.getType(typeQName);
boolean isFolder = type.equals(FileFolderServiceType.FOLDER); boolean isFolder = type.equals(FileFolderServiceType.FOLDER);
return isFolder; return isFolder;
} }
/** /**
@@ -178,40 +174,42 @@ public class ActivityPosterImpl implements ActivityPoster, InitializingBean
@Override @Override
public void postFileFolderAdded(NodeRef nodeRef) public void postFileFolderAdded(NodeRef nodeRef)
{ {
if(activitiesEnabled && !hiddenAspect.hasHiddenAspect(nodeRef)) if(activitiesEnabled && !hiddenAspect.hasHiddenAspect(nodeRef))
{ {
SiteInfo siteInfo = siteService.getSite(nodeRef); SiteInfo siteInfo = siteService.getSite(nodeRef);
String siteId = (siteInfo != null ? siteInfo.getShortName() : null); String siteId = (siteInfo != null ? siteInfo.getShortName() : null);
if(siteId != null && !siteId.equals("")) if(siteId != null && !siteId.equals(""))
{ {
// post only for nodes within sites // post only for nodes within sites
NodeRef parentNodeRef = nodeService.getPrimaryParent(nodeRef).getParentRef(); NodeRef parentNodeRef = nodeService.getPrimaryParent(nodeRef).getParentRef();
String path = null; String path = null;
boolean isFolder = isFolder(nodeRef); boolean isFolder = isFolder(nodeRef);
String name = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); String name = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
if(isFolder) if(isFolder)
{ {
NodeRef documentLibrary = siteService.getContainer(siteId, SiteService.DOCUMENT_LIBRARY); NodeRef documentLibrary = siteService.getContainer(siteId, SiteService.DOCUMENT_LIBRARY);
path = "/"; path = "/";
try try
{ {
path = getPathFromNode(documentLibrary, nodeRef); path = getPathFromNode(documentLibrary, nodeRef);
} }
catch (FileNotFoundException error) catch (FileNotFoundException error)
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("No " + SiteService.DOCUMENT_LIBRARY + " container found."); logger.debug("No " + SiteService.DOCUMENT_LIBRARY + " container found.");
} }
} }
} }
FileInfo fileInfo = fileFolderService.getFileInfo(nodeRef); FileInfo fileInfo = fileFolderService.getFileInfo(nodeRef);
postFileFolderActivity((isFolder ? ActivityType.FOLDER_ADDED : ActivityType.FILE_ADDED), path, parentNodeRef, nodeRef, siteId, name, fileInfo); poster.postFileFolderActivity((isFolder ? ActivityType.FOLDER_ADDED : ActivityType.FILE_ADDED), path, getCurrentTenantDomain(),
} siteId, parentNodeRef, nodeRef, name, APP_TOOL, Client.asType(ClientType.cmis), fileInfo);
}
}
}
} }
/** /**
@@ -220,22 +218,23 @@ public class ActivityPosterImpl implements ActivityPoster, InitializingBean
@Override @Override
public void postFileFolderUpdated(boolean isFolder, NodeRef nodeRef) public void postFileFolderUpdated(boolean isFolder, NodeRef nodeRef)
{ {
if(activitiesEnabled && !hiddenAspect.hasHiddenAspect(nodeRef)) if(activitiesEnabled && !hiddenAspect.hasHiddenAspect(nodeRef))
{ {
SiteInfo siteInfo = siteService.getSite(nodeRef); SiteInfo siteInfo = siteService.getSite(nodeRef);
String siteId = (siteInfo != null ? siteInfo.getShortName() : null); String siteId = (siteInfo != null ? siteInfo.getShortName() : null);
if(siteId != null && !siteId.equals("")) if(siteId != null && !siteId.equals(""))
{ {
// post only for nodes within sites // post only for nodes within sites
String fileName = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); String fileName = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
if (!isFolder) if (!isFolder)
{ {
FileInfo fileInfo = fileFolderService.getFileInfo(nodeRef); FileInfo fileInfo = fileFolderService.getFileInfo(nodeRef);
postFileFolderActivity(ActivityType.FILE_UPDATED, null, null, nodeRef, siteId, fileName, fileInfo); poster.postFileFolderActivity(ActivityType.FILE_UPDATED, null, getCurrentTenantDomain(),
} siteId, null, nodeRef, fileName, APP_TOOL, Client.asType(ClientType.cmis), fileInfo);
} }
} }
}
} }
/** /**
@@ -244,167 +243,92 @@ public class ActivityPosterImpl implements ActivityPoster, InitializingBean
@Override @Override
public void postFileFolderDeleted(ActivityInfo activityInfo) public void postFileFolderDeleted(ActivityInfo activityInfo)
{ {
if(activitiesEnabled && activityInfo.getSiteId() != null) if(activitiesEnabled && activityInfo.getSiteId() != null)
{ {
// post only for nodes within sites poster.postFileFolderActivity((activityInfo.isFolder() ? ActivityType.FOLDER_DELETED : ActivityType.FILE_DELETED), activityInfo.getParentPath(), getCurrentTenantDomain(),
postFileFolderActivity((activityInfo.isFolder() ? ActivityType.FOLDER_DELETED : ActivityType.FILE_DELETED), activityInfo.getParentPath(), activityInfo.getParentNodeRef(), activityInfo.getNodeRef(), activityInfo.getSiteId(), activityInfo.getParentNodeRef(), activityInfo.getNodeRef(), activityInfo.getFileName(), APP_TOOL, Client.asType(ClientType.cmis), null);
activityInfo.getSiteId(), activityInfo.getFileName(), null); }
}
} }
public ActivityInfo getActivityInfo(NodeRef nodeRef) public ActivityInfo getActivityInfo(NodeRef nodeRef)
{ {
SiteInfo siteInfo = siteService.getSite(nodeRef); SiteInfo siteInfo = siteService.getSite(nodeRef);
String siteId = (siteInfo != null ? siteInfo.getShortName() : null); String siteId = (siteInfo != null ? siteInfo.getShortName() : null);
if(siteId != null && !siteId.equals("")) if(siteId != null && !siteId.equals(""))
{
NodeRef parentNodeRef = nodeService.getPrimaryParent(nodeRef).getParentRef();
FileInfo fileInfo = fileFolderService.getFileInfo(nodeRef);
String name = fileInfo.getName();
boolean isFolder = fileInfo.isFolder();
NodeRef documentLibrary = siteService.getContainer(siteId, SiteService.DOCUMENT_LIBRARY);
String parentPath = "/";
try
{
parentPath = getPathFromNode(documentLibrary, parentNodeRef);
}
catch (FileNotFoundException error)
{
if (logger.isDebugEnabled())
{
logger.debug("No " + SiteService.DOCUMENT_LIBRARY + " container found.");
}
}
return new ActivityInfo(nodeRef, parentPath, parentNodeRef, siteId, name, isFolder);
}
else
{
return null;
}
}
private void postFileFolderActivity(
String activityType,
String path,
NodeRef parentNodeRef,
NodeRef nodeRef,
String siteId,
String name,
FileInfo fileInfo)
{
JSONObject json = createActivityJSON(getCurrentTenantDomain(), path, parentNodeRef, nodeRef, name);
activityService.postActivity(
activityType,
siteId,
APP_TOOL,
json.toString(),
Client.asType(ClientType.cmis),
fileInfo);
}
/**
* Create JSON suitable for create, modify or delete activity posts. Returns a new JSONObject
* containing appropriate key/value pairs.
*
* @param tenantDomain
* @param nodeRef
* @param fileName
* @throws WebDAVServerException
* @return JSONObject
*/
private JSONObject createActivityJSON(
String tenantDomain,
String path,
NodeRef parentNodeRef,
NodeRef nodeRef,
String fileName)
{
JSONObject json = new JSONObject();
try
{ {
json.put("nodeRef", nodeRef); NodeRef parentNodeRef = nodeService.getPrimaryParent(nodeRef).getParentRef();
FileInfo fileInfo = fileFolderService.getFileInfo(nodeRef);
if (parentNodeRef != null) String name = fileInfo.getName();
boolean isFolder = fileInfo.isFolder();
NodeRef documentLibrary = siteService.getContainer(siteId, SiteService.DOCUMENT_LIBRARY);
String parentPath = "/";
try
{ {
// Used for deleted files. parentPath = getPathFromNode(documentLibrary, parentNodeRef);
json.put("parentNodeRef", parentNodeRef); }
catch (FileNotFoundException error)
{
if (logger.isDebugEnabled())
{
logger.debug("No " + SiteService.DOCUMENT_LIBRARY + " container found.");
}
} }
if (path != null) return new ActivityInfo(nodeRef, parentPath, parentNodeRef, siteId, name, isFolder);
{
// Used for deleted files and folders (added or deleted)
json.put("page", "documentlibrary?path=" + path);
}
else
{
// Used for added or modified files.
json.put("page", "document-details?nodeRef=" + nodeRef);
}
json.put("title", fileName);
if (!tenantDomain.equals(TenantService.DEFAULT_DOMAIN))
{
// Only used in multi-tenant setups.
json.put("tenantDomain", tenantDomain);
}
} }
catch (JSONException error) else
{ {
throw new AlfrescoRuntimeException("", error); return null;
} }
return json;
} }
public static class ActivityInfo public static class ActivityInfo
{ {
private NodeRef nodeRef; private NodeRef nodeRef;
private String parentPath; private String parentPath;
private NodeRef parentNodeRef; private NodeRef parentNodeRef;
private String siteId; private String siteId;
private String fileName; private String fileName;
private boolean isFolder; private boolean isFolder;
public ActivityInfo(NodeRef nodeRef, String parentPath, NodeRef parentNodeRef, public ActivityInfo(NodeRef nodeRef, String parentPath, NodeRef parentNodeRef,
String siteId, String fileName, boolean isFolder) String siteId, String fileName, boolean isFolder)
{ {
super(); super();
this.nodeRef = nodeRef; this.nodeRef = nodeRef;
this.parentPath = parentPath; this.parentPath = parentPath;
this.parentNodeRef = parentNodeRef; this.parentNodeRef = parentNodeRef;
this.siteId = siteId; this.siteId = siteId;
this.fileName = fileName; this.fileName = fileName;
this.isFolder = isFolder; this.isFolder = isFolder;
} }
public NodeRef getNodeRef() public NodeRef getNodeRef()
{ {
return nodeRef; return nodeRef;
} }
public String getParentPath() public String getParentPath()
{ {
return parentPath; return parentPath;
} }
public NodeRef getParentNodeRef() public NodeRef getParentNodeRef()
{ {
return parentNodeRef; return parentNodeRef;
} }
public String getSiteId() public String getSiteId()
{ {
return siteId; return siteId;
} }
public String getFileName() public String getFileName()
{ {
return fileName; return fileName;
} }
public boolean isFolder() public boolean isFolder()
{ {
return isFolder; return isFolder;

View File

@@ -321,7 +321,7 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
private ServiceRegistry serviceRegistry; private ServiceRegistry serviceRegistry;
private EventPublisher eventPublisher; private EventPublisher eventPublisher;
private ActivityPoster activityPoster; private CmisActivityPoster activityPoster;
private BehaviourFilter behaviourFilter; private BehaviourFilter behaviourFilter;
@@ -376,12 +376,12 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
this.siteService = siteService; this.siteService = siteService;
} }
public void setActivityPoster(ActivityPoster activityPoster) public void setActivityPoster(CmisActivityPoster activityPoster)
{ {
this.activityPoster = activityPoster; this.activityPoster = activityPoster;
} }
public ActivityPoster getActivityPoster() public CmisActivityPoster getActivityPoster()
{ {
return activityPoster; return activityPoster;
} }

View File

@@ -26,8 +26,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
* *
* @author sglover * @author sglover
*/ */
// TODO consolidate with ActivityPost for WebDAV public interface CmisActivityPoster
public interface ActivityPoster
{ {
void postFileFolderAdded(NodeRef nodeRef); void postFileFolderAdded(NodeRef nodeRef);

View File

@@ -0,0 +1,33 @@
package org.alfresco.service.cmr.activities;
import org.alfresco.repo.Client;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* A consolidated services for posting file folder activities.
*
* @author Gethin James
*/
public interface ActivityPoster
{
public static final String DOWNLOADED = "org.alfresco.documentlibrary.file-downloaded";
/**
* Posts file folder activity.
* @param activityType required
* @param path optional
* @param tenantDomain optional
* @param siteId required
* @param parentNodeRef optional
* @param nodeRef required
* @param fileName required
* @param appTool required
* @param client required
* @param fileInfo optional
*/
void postFileFolderActivity(String activityType, String path, String tenantDomain,
String siteId, NodeRef parentNodeRef, NodeRef nodeRef, String fileName,
String appTool, Client client, FileInfo fileInfo);
}

View File

@@ -0,0 +1,108 @@
package org.alfresco.service.cmr.activities;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.Client;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.NodeRef;
import org.json.JSONException;
import org.json.JSONObject;
/**
* A consolidated services for posting file folder activities.
* Some code was moved from webdav.ActivityPosterImpl and
* opencmis.ActivityPosterImpl.
*
* @author Gethin James
*/
public class FileFolderActivityPosterImpl implements ActivityPoster
{
private ActivityService activityService;
@Override
public void postFileFolderActivity(
String activityType,
String path,
String tenantDomain,
String siteId,
NodeRef parentNodeRef,
NodeRef nodeRef,
String fileName,
String appTool,
Client client,
FileInfo fileInfo)
{
JSONObject json;
try
{
json = createActivityJSON(tenantDomain, path, parentNodeRef, nodeRef, fileName);
}
catch (JSONException jsonError)
{
throw new AlfrescoRuntimeException("Unabled to create activities json", jsonError);
}
activityService.postActivity(
activityType,
siteId,
appTool,
json.toString(),
client,
fileInfo);
}
/**
* Create JSON suitable for create, modify or delete activity posts.
*
* @param tenantDomain
* @param path
* @param parentNodeRef
* @param nodeRef
* @param fileName
* @throws JSONException
* @return JSONObject
*/
protected JSONObject createActivityJSON(
String tenantDomain,
String path,
NodeRef parentNodeRef,
NodeRef nodeRef,
String fileName) throws JSONException
{
JSONObject json = new JSONObject();
json.put("nodeRef", nodeRef);
if (parentNodeRef != null)
{
// Used for deleted files.
json.put("parentNodeRef", parentNodeRef);
}
if (path != null)
{
// Used for deleted files and folders (added or deleted)
json.put("page", "documentlibrary?path=" + path);
}
else
{
// Used for added or modified files.
json.put("page", "document-details?nodeRef=" + nodeRef);
}
json.put("title", fileName);
if (tenantDomain!= null && !tenantDomain.equals(TenantService.DEFAULT_DOMAIN))
{
// Only used in multi-tenant setups.
json.put("tenantDomain", tenantDomain);
}
return json;
}
public void setActivityService(ActivityService activityService)
{
this.activityService = activityService;
}
}