From 52c9a7e5cf975df9c5cc19496d5c5d52d2e0002a Mon Sep 17 00:00:00 2001 From: Jan Vonka Date: Tue, 5 May 2009 10:54:04 +0000 Subject: [PATCH] Activity Service - improve feed cleaner test and fix ALFCOM-2838 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@14183 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../activities/activities-feed-context.xml | 16 +- .../activities/ActivityPostServiceImpl.java | 251 ++++++++++++++++++ .../repo/activities/ActivityServiceImpl.java | 181 ++----------- .../feed/AbstractFeedGenerator.java | 14 +- .../feed/cleanup/FeedCleanerTest.java | 190 ++++++++----- .../feed/local/LocalFeedGenerator.java | 1 + .../cmr/activities/ActivityPostService.java | 86 ++++++ .../cmr/activities/ActivityService.java | 63 +---- 8 files changed, 500 insertions(+), 302 deletions(-) create mode 100644 source/java/org/alfresco/repo/activities/ActivityPostServiceImpl.java create mode 100644 source/java/org/alfresco/service/cmr/activities/ActivityPostService.java diff --git a/config/alfresco/activities/activities-feed-context.xml b/config/alfresco/activities/activities-feed-context.xml index d70208c742..f637a52e3b 100644 --- a/config/alfresco/activities/activities-feed-context.xml +++ b/config/alfresco/activities/activities-feed-context.xml @@ -2,19 +2,26 @@ - - + + + + + + + + + + - - + @@ -50,6 +57,7 @@ + diff --git a/source/java/org/alfresco/repo/activities/ActivityPostServiceImpl.java b/source/java/org/alfresco/repo/activities/ActivityPostServiceImpl.java new file mode 100644 index 0000000000..0d61ed6d23 --- /dev/null +++ b/source/java/org/alfresco/repo/activities/ActivityPostServiceImpl.java @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2005-2009 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.activities; + +import java.sql.SQLException; +import java.util.Date; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.domain.activities.ActivityPostDAO; +import org.alfresco.repo.domain.activities.ActivityPostEntity; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.service.cmr.activities.ActivityPostService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ParameterCheck; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Activity Post Service Implementation + * + * @author janv + */ +public class ActivityPostServiceImpl implements ActivityPostService +{ + private static final Log logger = LogFactory.getLog(ActivityServiceImpl.class); + + private static final int MAX_LEN_USER_ID = 255; // needs to match schema: feed_user_id, post_user_id + private static final int MAX_LEN_SITE_ID = 255; // needs to match schema: site_network + private static final int MAX_LEN_ACTIVITY_TYPE = 255; // needs to match schema: activity_type + private static final int MAX_LEN_ACTIVITY_DATA = 4000; // needs to match schema: activity_data + private static final int MAX_LEN_APP_TOOL_ID = 36; // needs to match schema: app_tool + + private ActivityPostDAO postDAO; + private TenantService tenantService; + private int estGridSize = 1; + + private boolean userNamesAreCaseSensitive = false; + + public void setUserNamesAreCaseSensitive(boolean userNamesAreCaseSensitive) + { + this.userNamesAreCaseSensitive = userNamesAreCaseSensitive; + } + + public void setPostDAO(ActivityPostDAO postDAO) + { + this.postDAO = postDAO; + } + + public void setTenantService(TenantService tenantService) + { + this.tenantService = tenantService; + } + + public void setEstimatedGridSize(int estGridSize) + { + this.estGridSize = estGridSize; + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, java.lang.String) + */ + public void postActivity(String activityType, String siteId, String appTool, String activityData) + { + postActivity(activityType, siteId, appTool, activityData, ActivityPostEntity.STATUS.PENDING); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.NodeRef) + */ + public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef) + { + ParameterCheck.mandatory("nodeRef", nodeRef); + + StringBuffer sb = new StringBuffer(); + sb.append("{").append("\"nodeRef\":\"").append(nodeRef.toString()).append("\"").append("}"); + + postActivity(activityType, siteId, appTool, sb.toString(), ActivityPostEntity.STATUS.PENDING); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.NodeRef, java.lang.String) + */ + public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef, String name) + { + ParameterCheck.mandatory("nodeRef", nodeRef); + + StringBuffer sb = new StringBuffer(); + sb.append("{").append("\"nodeRef\":\"").append(nodeRef.toString()).append("\"").append(",") + .append("\"name\":\"").append(name).append("\"") + .append("}"); + + postActivity(activityType, siteId, appTool, sb.toString(), ActivityPostEntity.STATUS.PENDING); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.NodeRef, java.lang.String, org.alfresco.service.namespace.QName, org.alfresco.service.cmr.repository.NodeRef) + */ + public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef, String name, QName typeQName, NodeRef parentNodeRef) + { + // primarily for delete node activities - eg. delete document, delete folder + + ParameterCheck.mandatory("nodeRef", nodeRef); + ParameterCheck.mandatory("typeQName", typeQName); + ParameterCheck.mandatory("parentNodeRef", parentNodeRef); + + StringBuffer sb = new StringBuffer(); + sb.append("{").append("\"nodeRef\":\"").append(nodeRef.toString()).append("\"").append(",") + .append("\"name\":\"").append(name).append("\"").append(",") + .append("\"typeQName\":\"").append(typeQName.toPrefixString()).append("\"").append(",") // TODO toPrefixString does not return prefix ??!! + .append("\"parentNodeRef\":\"").append(parentNodeRef.toString()).append("\"") + .append("}"); + + postActivity(activityType, siteId, appTool, sb.toString(), ActivityPostEntity.STATUS.PENDING); + } + + private void postActivity(String activityType, String siteId, String appTool, String activityData, ActivityPostEntity.STATUS status) + { + String currentUser = AuthenticationUtil.getFullyAuthenticatedUser(); + + try + { + // optional - default to empty string + if (siteId == null) + { + siteId = ""; + } + else if (siteId.length() > MAX_LEN_SITE_ID) + { + throw new AlfrescoRuntimeException("Invalid siteId - exceeds " + MAX_LEN_SITE_ID + " chars: " + siteId); + } + + // optional - default to empty string + if (appTool == null) + { + appTool = ""; + } + else if (appTool.length() > MAX_LEN_APP_TOOL_ID) + { + throw new AlfrescoRuntimeException("Invalid app tool - exceeds " + MAX_LEN_APP_TOOL_ID + " chars: " + appTool); + } + + // required + ParameterCheck.mandatoryString("activityType", activityType); + + if (activityType.length() > MAX_LEN_ACTIVITY_TYPE) + { + throw new AlfrescoRuntimeException("Invalid activity type - exceeds " + MAX_LEN_ACTIVITY_TYPE + " chars: " + activityType); + } + + // optional - default to empty string + if (activityData == null) + { + activityData = ""; + } + else if (activityType.length() > MAX_LEN_ACTIVITY_DATA) + { + throw new AlfrescoRuntimeException("Invalid activity data - exceeds " + MAX_LEN_ACTIVITY_DATA + " chars: " + activityData); + } + + // required + ParameterCheck.mandatoryString("currentUser", currentUser); + + if (currentUser.length() > MAX_LEN_USER_ID) + { + throw new AlfrescoRuntimeException("Invalid user - exceeds " + MAX_LEN_USER_ID + " chars: " + currentUser); + } + else if ((! currentUser.equals(AuthenticationUtil.SYSTEM_USER_NAME)) && (! userNamesAreCaseSensitive)) + { + // user names are not case-sensitive + currentUser = currentUser.toLowerCase(); + } + } + catch (AlfrescoRuntimeException e) + { + // log error and throw exception + logger.error(e); + throw e; + } + + try + { + Date postDate = new Date(); + ActivityPostEntity activityPost = new ActivityPostEntity(); + activityPost.setUserId(currentUser); + + activityPost.setSiteNetwork(tenantService.getName(siteId)); + + activityPost.setAppTool(appTool); + activityPost.setActivityData(activityData); + activityPost.setActivityType(activityType); + activityPost.setPostDate(postDate); + activityPost.setStatus(status.toString()); + activityPost.setLastModified(postDate); + + // hash the userid to generate a job task node + int nodeCount = estGridSize; + int userHashCode = currentUser.hashCode(); + int nodeHash = (userHashCode % nodeCount) + 1; + + activityPost.setJobTaskNode(nodeHash); + + try + { + long postId = postDAO.insertPost(activityPost); + + if (logger.isDebugEnabled()) + { + activityPost.setId(postId); + logger.debug("Posted: " + activityPost); + } + } + catch (SQLException e) + { + throw new AlfrescoRuntimeException("Failed to post activity: " + e, e); + } + catch (Throwable t) + { + throw new AlfrescoRuntimeException("Failed to post activity: " + t, t); + } + } + catch (AlfrescoRuntimeException e) + { + // log error, subsume exception (for post activity) + logger.error(e); + } + } +} diff --git a/source/java/org/alfresco/repo/activities/ActivityServiceImpl.java b/source/java/org/alfresco/repo/activities/ActivityServiceImpl.java index 1eedc6f9fb..ea95646c6e 100644 --- a/source/java/org/alfresco/repo/activities/ActivityServiceImpl.java +++ b/source/java/org/alfresco/repo/activities/ActivityServiceImpl.java @@ -26,20 +26,17 @@ package org.alfresco.repo.activities; import java.sql.SQLException; import java.util.ArrayList; -import java.util.Date; import java.util.List; import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.repo.activities.feed.FeedGenerator; import org.alfresco.repo.domain.activities.ActivityFeedDAO; import org.alfresco.repo.domain.activities.ActivityFeedEntity; -import org.alfresco.repo.domain.activities.ActivityPostDAO; -import org.alfresco.repo.domain.activities.ActivityPostEntity; import org.alfresco.repo.domain.activities.FeedControlDAO; import org.alfresco.repo.domain.activities.FeedControlEntity; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.tenant.TenantService; +import org.alfresco.service.cmr.activities.ActivityPostService; import org.alfresco.service.cmr.activities.ActivityService; import org.alfresco.service.cmr.activities.FeedControl; import org.alfresco.service.cmr.repository.NodeRef; @@ -61,20 +58,12 @@ public class ActivityServiceImpl implements ActivityService { private static final Log logger = LogFactory.getLog(ActivityServiceImpl.class); - private static final int MAX_LEN_USER_ID = 255; // needs to match schema: feed_user_id, post_user_id - private static final int MAX_LEN_SITE_ID = 255; // needs to match schema: site_network - private static final int MAX_LEN_ACTIVITY_TYPE = 255; // needs to match schema: activity_type - private static final int MAX_LEN_ACTIVITY_DATA = 4000; // needs to match schema: activity_data - private static final int MAX_LEN_APP_TOOL_ID = 36; // needs to match schema: app_tool - - private ActivityPostDAO postDAO; private ActivityFeedDAO feedDAO; private FeedControlDAO feedControlDAO; private AuthorityService authorityService; - private FeedGenerator feedGenerator; - private SiteService siteService; - private TenantService tenantService; + private SiteService siteService; + private ActivityPostService activityPostService; private int maxFeedItems = 100; @@ -90,11 +79,6 @@ public class ActivityServiceImpl implements ActivityService this.userNamesAreCaseSensitive = userNamesAreCaseSensitive; } - public void setPostDAO(ActivityPostDAO postDAO) - { - this.postDAO = postDAO; - } - public void setFeedDAO(ActivityFeedDAO feedDAO) { this.feedDAO = feedDAO; @@ -110,11 +94,6 @@ public class ActivityServiceImpl implements ActivityService this.authorityService = authorityService; } - public void setFeedGenerator(FeedGenerator feedGenerator) - { - this.feedGenerator = feedGenerator; - } - public void setTenantService(TenantService tenantService) { this.tenantService = tenantService; @@ -125,13 +104,19 @@ public class ActivityServiceImpl implements ActivityService this.siteService = siteService; } + public void setActivityPostService(ActivityPostService activityPostService) + { + this.activityPostService = activityPostService; + } + /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ public void postActivity(String activityType, String siteId, String appTool, String activityData) { - postActivity(activityType, siteId, appTool, activityData, ActivityPostEntity.STATUS.PENDING); + // delegate + activityPostService.postActivity(activityType, siteId, appTool, activityData); } /* (non-Javadoc) @@ -139,12 +124,8 @@ public class ActivityServiceImpl implements ActivityService */ public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef) { - ParameterCheck.mandatory("nodeRef", nodeRef); - - StringBuffer sb = new StringBuffer(); - sb.append("{").append("\"nodeRef\":\"").append(nodeRef.toString()).append("\"").append("}"); - - postActivity(activityType, siteId, appTool, sb.toString(), ActivityPostEntity.STATUS.PENDING); + // delegate + activityPostService.postActivity(activityType, siteId, appTool, nodeRef); } /* (non-Javadoc) @@ -152,14 +133,8 @@ public class ActivityServiceImpl implements ActivityService */ public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef, String name) { - ParameterCheck.mandatory("nodeRef", nodeRef); - - StringBuffer sb = new StringBuffer(); - sb.append("{").append("\"nodeRef\":\"").append(nodeRef.toString()).append("\"").append(",") - .append("\"name\":\"").append(name).append("\"") - .append("}"); - - postActivity(activityType, siteId, appTool, sb.toString(), ActivityPostEntity.STATUS.PENDING); + // delegate + activityPostService.postActivity(activityType, siteId, appTool, nodeRef, name); } /* (non-Javadoc) @@ -167,132 +142,8 @@ public class ActivityServiceImpl implements ActivityService */ public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef, String name, QName typeQName, NodeRef parentNodeRef) { - // primarily for delete node activities - eg. delete document, delete folder - - ParameterCheck.mandatory("nodeRef", nodeRef); - ParameterCheck.mandatory("typeQName", typeQName); - ParameterCheck.mandatory("parentNodeRef", parentNodeRef); - - StringBuffer sb = new StringBuffer(); - sb.append("{").append("\"nodeRef\":\"").append(nodeRef.toString()).append("\"").append(",") - .append("\"name\":\"").append(name).append("\"").append(",") - .append("\"typeQName\":\"").append(typeQName.toPrefixString()).append("\"").append(",") // TODO toPrefixString does not return prefix ??!! - .append("\"parentNodeRef\":\"").append(parentNodeRef.toString()).append("\"") - .append("}"); - - postActivity(activityType, siteId, appTool, sb.toString(), ActivityPostEntity.STATUS.PENDING); - } - - private void postActivity(String activityType, String siteId, String appTool, String activityData, ActivityPostEntity.STATUS status) - { - String currentUser = AuthenticationUtil.getFullyAuthenticatedUser(); - - try - { - // optional - default to empty string - if (siteId == null) - { - siteId = ""; - } - else if (siteId.length() > MAX_LEN_SITE_ID) - { - throw new AlfrescoRuntimeException("Invalid siteId - exceeds " + MAX_LEN_SITE_ID + " chars: " + siteId); - } - - // optional - default to empty string - if (appTool == null) - { - appTool = ""; - } - else if (appTool.length() > MAX_LEN_APP_TOOL_ID) - { - throw new AlfrescoRuntimeException("Invalid app tool - exceeds " + MAX_LEN_APP_TOOL_ID + " chars: " + appTool); - } - - // required - ParameterCheck.mandatoryString("activityType", activityType); - - if (activityType.length() > MAX_LEN_ACTIVITY_TYPE) - { - throw new AlfrescoRuntimeException("Invalid activity type - exceeds " + MAX_LEN_ACTIVITY_TYPE + " chars: " + activityType); - } - - // optional - default to empty string - if (activityData == null) - { - activityData = ""; - } - else if (activityType.length() > MAX_LEN_ACTIVITY_DATA) - { - throw new AlfrescoRuntimeException("Invalid activity data - exceeds " + MAX_LEN_ACTIVITY_DATA + " chars: " + activityData); - } - - // required - ParameterCheck.mandatoryString("currentUser", currentUser); - - if (currentUser.length() > MAX_LEN_USER_ID) - { - throw new AlfrescoRuntimeException("Invalid user - exceeds " + MAX_LEN_USER_ID + " chars: " + currentUser); - } - else if ((! currentUser.equals(AuthenticationUtil.SYSTEM_USER_NAME)) && (! userNamesAreCaseSensitive)) - { - // user names are not case-sensitive - currentUser = currentUser.toLowerCase(); - } - } - catch (AlfrescoRuntimeException e) - { - // log error and throw exception - logger.error(e); - throw e; - } - - try - { - Date postDate = new Date(); - ActivityPostEntity activityPost = new ActivityPostEntity(); - activityPost.setUserId(currentUser); - - activityPost.setSiteNetwork(tenantService.getName(siteId)); - - activityPost.setAppTool(appTool); - activityPost.setActivityData(activityData); - activityPost.setActivityType(activityType); - activityPost.setPostDate(postDate); - activityPost.setStatus(status.toString()); - activityPost.setLastModified(postDate); - - // hash the userid to generate a job task node - int nodeCount = feedGenerator.getEstimatedGridSize(); - int userHashCode = currentUser.hashCode(); - int nodeHash = (userHashCode % nodeCount) + 1; - - activityPost.setJobTaskNode(nodeHash); - - try - { - long postId = postDAO.insertPost(activityPost); - - if (logger.isDebugEnabled()) - { - activityPost.setId(postId); - logger.debug("Posted: " + activityPost); - } - } - catch (SQLException e) - { - throw new AlfrescoRuntimeException("Failed to post activity: " + e, e); - } - catch (Throwable t) - { - throw new AlfrescoRuntimeException("Failed to post activity: " + t, t); - } - } - catch (AlfrescoRuntimeException e) - { - // log error, subsume exception (for post activity) - logger.error(e); - } + // delegate + activityPostService.postActivity(activityType, siteId, appTool, nodeRef, name, typeQName, parentNodeRef); } /* (non-Javadoc) diff --git a/source/java/org/alfresco/repo/activities/feed/AbstractFeedGenerator.java b/source/java/org/alfresco/repo/activities/feed/AbstractFeedGenerator.java index 94b257ce16..18b25b0ffe 100644 --- a/source/java/org/alfresco/repo/activities/feed/AbstractFeedGenerator.java +++ b/source/java/org/alfresco/repo/activities/feed/AbstractFeedGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 Alfresco Software Limited. + * Copyright (C) 2005-2009 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -24,6 +24,7 @@ */ package org.alfresco.repo.activities.feed; +import org.alfresco.repo.activities.ActivityPostServiceImpl; import org.alfresco.repo.domain.activities.ActivityPostDAO; import org.alfresco.service.cmr.security.AuthenticationService; import org.alfresco.util.PropertyCheck; @@ -44,6 +45,7 @@ public abstract class AbstractFeedGenerator implements FeedGenerator private int maxItemsPerCycle = 100; private ActivityPostDAO postDAO; + private ActivityPostServiceImpl activityPostServiceImpl; private AuthenticationService authenticationService; private String repoEndPoint; // http://hostname:port/webapp (eg. http://localhost:8080/alfresco) @@ -54,6 +56,11 @@ public abstract class AbstractFeedGenerator implements FeedGenerator private volatile boolean busy; + public void setActivityPostServiceImpl(ActivityPostServiceImpl activityPostServiceImpl) + { + this.activityPostServiceImpl = activityPostServiceImpl; + } + public void setPostDAO(ActivityPostDAO postDAO) { this.postDAO = postDAO; @@ -112,9 +119,12 @@ public abstract class AbstractFeedGenerator implements FeedGenerator */ private void checkProperties() { - PropertyCheck.mandatory(this, "postDAO", postDAO); + PropertyCheck.mandatory(this, "postDAO", postDAO); + + activityPostServiceImpl.setEstimatedGridSize(getEstimatedGridSize()); } + abstract public int getEstimatedGridSize(); public void execute() throws JobExecutionException { diff --git a/source/java/org/alfresco/repo/activities/feed/cleanup/FeedCleanerTest.java b/source/java/org/alfresco/repo/activities/feed/cleanup/FeedCleanerTest.java index 585b9b1d0f..55f5f38247 100644 --- a/source/java/org/alfresco/repo/activities/feed/cleanup/FeedCleanerTest.java +++ b/source/java/org/alfresco/repo/activities/feed/cleanup/FeedCleanerTest.java @@ -24,8 +24,9 @@ */ package org.alfresco.repo.activities.feed.cleanup; +import java.io.PrintWriter; +import java.io.StringWriter; import java.util.Date; -import java.util.concurrent.CountDownLatch; import junit.framework.TestCase; @@ -33,6 +34,8 @@ import org.alfresco.repo.domain.activities.ActivityFeedDAO; import org.alfresco.repo.domain.activities.ActivityFeedEntity; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.service.cmr.activities.ActivityService; +import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.service.cmr.site.SiteVisibility; import org.alfresco.util.ApplicationContextHelper; import org.springframework.context.ConfigurableApplicationContext; @@ -48,16 +51,23 @@ public class FeedCleanerTest extends TestCase private ActivityFeedDAO feedDAO; private FeedCleaner cleaner; private ActivityService activityService; + private SiteService siteService; @Override public void setUp() throws Exception { + activityService = (ActivityService) ctx.getBean("activityService"); + siteService = (SiteService) ctx.getBean("SiteService"); + feedDAO = (ActivityFeedDAO) ctx.getBean("feedDAO"); + + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); + for (int i = 1; i <= 7; i++) + { + siteService.createSite("myPreset", "testSite"+i, null, null, SiteVisibility.PUBLIC); + } + AuthenticationUtil.setRunAsUserSystem(); - activityService = (ActivityService) ctx.getBean("activityService"); - - feedDAO = (ActivityFeedDAO) ctx.getBean("feedDAO"); - // construct the test cleaner cleaner = new FeedCleaner(); cleaner.setFeedDAO(feedDAO); @@ -66,7 +76,12 @@ public class FeedCleanerTest extends TestCase public void tearDown() throws Exception { // clean out any remaining feed entries (allows test to be re-runnable) - feedDAO.deleteFeedEntries(new Date(System.currentTimeMillis()+(120*1000L))); + feedDAO.deleteFeedEntries(new Date(System.currentTimeMillis()+(120*1000L))); + + for (int i = 1; i <= 7; i++) + { + siteService.deleteSite("testSite"+i); + } AuthenticationUtil.clearCurrentSecurityContext(); } @@ -244,72 +259,107 @@ public class FeedCleanerTest extends TestCase cleaner.setMaxAgeMins(1); cleaner.setMaxFeedSize(1); - final int typeCount = 3; - int threadCount = typeCount * 10; + int typeCount = 3; + int n = typeCount * 10; - final CountDownLatch endLatch = new CountDownLatch(threadCount); - // Kick off the threads - for (int i = 0; i < threadCount; i++) + Thread[] threads = new Thread[n]; + Tester[] testers = new Tester[n]; + + for (int i = 0; i < n; i++) { - Thread thread = new Thread(""+i) - { - @Override - public void run() - { - try - { - int type = new Integer(this.getName()) % typeCount; - - if (type == 0) - { - int insertCount = 10; - - // insert some entries - for (int i = 0; i < insertCount; i++) - { - ActivityFeedEntity feedEntry = new ActivityFeedEntity(); - - feedEntry.setPostDate(new Date(System.currentTimeMillis()-(i*60*1000L))); - feedEntry.setActivitySummaryFormat("json"); - feedEntry.setSiteNetwork("testSite4"); - feedEntry.setActivityType("testActivityType"); - feedEntry.setPostUserId("testUserC"); - feedEntry.setFeedUserId(""); - feedEntry.setFeedDate(new Date()); - - feedDAO.insertFeedEntry(feedEntry); - } - - System.out.println("["+this.getName()+"] Inserted "+insertCount+" entries"); - } - - if (type == 1) - { - // query some entries - int selectCount = activityService.getSiteFeedEntries("testSite4", "json").size(); - - System.out.println("["+this.getName()+"] Selected "+selectCount+" entries"); - } - - if (type == 2) - { - // clean some entries - int deleteCount = cleaner.execute(); - - System.out.println("["+this.getName()+"] Deleted "+deleteCount+" entries"); - } - } - catch (Exception e) - { - fail(e.getMessage()); - } - // Notify of completion - endLatch.countDown(); - } - }; - thread.start(); + Tester tester = new Tester(i, typeCount); + testers[i] = tester; + + threads[i] = new Thread(tester); + threads[i].start(); + } + for (int i = 0; i < n; i++) + { + threads[i].join(); + + if (testers[i].getErrorStackTrace() != null) + { + fail(testers[i].getErrorStackTrace()); + } + } + } + + private class Tester implements Runnable + { + private int i; + private int typeCount; + private String errorStackTrace = null; + + public Tester(int i, int typeCount) + { + this.i = i; + this.typeCount = typeCount; + } + + public String getErrorStackTrace() + { + return errorStackTrace; + } + + public void run() + { + try + { + int type = i % typeCount; + + if (type == 0) + { + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); + + int insertCount = 10; + + // insert some entries + for (int i = 0; i < insertCount; i++) + { + ActivityFeedEntity feedEntry = new ActivityFeedEntity(); + + feedEntry.setPostDate(new Date(System.currentTimeMillis()-(i*60*1000L))); + feedEntry.setActivitySummaryFormat("json"); + feedEntry.setSiteNetwork("testSite4"); + feedEntry.setActivityType("testActivityType"); + feedEntry.setPostUserId("testUserC"); + feedEntry.setFeedUserId(""); + feedEntry.setFeedDate(new Date()); + + feedDAO.insertFeedEntry(feedEntry); + } + + System.out.println("["+i+"] Inserted "+insertCount+" entries"); + } + + if (type == 1) + { + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); + + // query some entries + int selectCount = activityService.getSiteFeedEntries("testSite4", "json").size(); + + System.out.println("["+i+"] Selected "+selectCount+" entries"); + } + + if (type == 2) + { + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName()); + + // clean some entries + int deleteCount = cleaner.execute(); + + System.out.println("["+i+"] Deleted "+deleteCount+" entries"); + } + } + catch (Throwable t) + { + StringWriter sw = new StringWriter(); + t.printStackTrace(new PrintWriter(sw)); + errorStackTrace = sw.toString(); + + fail(t.getMessage()); + } } - // Wait for them all to be done - endLatch.await(); } } diff --git a/source/java/org/alfresco/repo/activities/feed/local/LocalFeedGenerator.java b/source/java/org/alfresco/repo/activities/feed/local/LocalFeedGenerator.java index 262a61fc9c..8afd53ea0c 100644 --- a/source/java/org/alfresco/repo/activities/feed/local/LocalFeedGenerator.java +++ b/source/java/org/alfresco/repo/activities/feed/local/LocalFeedGenerator.java @@ -49,6 +49,7 @@ public class LocalFeedGenerator extends AbstractFeedGenerator this.feedTaskProcessor = feedTaskProcessor; } + @Override public int getEstimatedGridSize() { return 1; diff --git a/source/java/org/alfresco/service/cmr/activities/ActivityPostService.java b/source/java/org/alfresco/service/cmr/activities/ActivityPostService.java new file mode 100644 index 0000000000..3d9894da77 --- /dev/null +++ b/source/java/org/alfresco/service/cmr/activities/ActivityPostService.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2005-2009 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.service.cmr.activities; + +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; + +public interface ActivityPostService +{ + + /* + * Post Activity + */ + + /** + * Post a custom activity type + * + * @param activityType - required + * @param siteId - optional, if null will be stored as empty string + * @param appTool - optional, if null will be stored as empty string + * @param jsonActivityData - required + */ + public void postActivity(String activityType, String siteId, String appTool, String jsonActivityData); + + /** + * Post a pre-defined activity type - certain activity data will be looked-up asynchronously, including: + * + * name (of nodeRef) + * displayPath + * typeQName + * firstName (of posting user) + * lastName (of posting user) + * + * @param activityType - required + * @param siteId - optional, if null will be stored as empty string + * @param appTool - optional, if null will be stored as empty string + * @param nodeRef - required - do not use for deleted (or about to be deleted) nodeRef + */ + public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef); + + /** + * Post a pre-defined activity type - eg. for checked-out nodeRef or renamed nodeRef + * + * @param activityType - required + * @param siteId - optional, if null will be stored as empty string + * @param appTool - optional, if null will be stored as empty string + * @param nodeRef - required - do not use deleted (or about to be deleted) nodeRef + * @param beforeName - optional - name of node (eg. prior to name change) + */ + public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef, String beforeName); + + /** + * Post a pre-defined activity type - eg. for deleted nodeRef + * + * @param activityType - required + * @param siteId - optional, if null will be stored as empty string + * @param appTool - optional, if null will be stored as empty string + * @param nodeRef - required - can be a deleted (or about to be deleted) nodeRef + * @param name - optional - name of name + * @param typeQName - optional - type of node + * @param parentNodeRef - required - used to lookup path/displayPath + */ + public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef, String name, QName typeQName, NodeRef parentNodeRef); +} diff --git a/source/java/org/alfresco/service/cmr/activities/ActivityService.java b/source/java/org/alfresco/service/cmr/activities/ActivityService.java index 0eb785665a..f0d44ca05e 100644 --- a/source/java/org/alfresco/service/cmr/activities/ActivityService.java +++ b/source/java/org/alfresco/service/cmr/activities/ActivityService.java @@ -26,67 +26,8 @@ package org.alfresco.service.cmr.activities; import java.util.List; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.namespace.QName; - -public interface ActivityService -{ - - /* - * Post Activity - */ - - /** - * Post a custom activity type - * - * @param activityType - required - * @param siteId - optional, if null will be stored as empty string - * @param appTool - optional, if null will be stored as empty string - * @param jsonActivityData - required - */ - public void postActivity(String activityType, String siteId, String appTool, String jsonActivityData); - - /** - * Post a pre-defined activity type - certain activity data will be looked-up asynchronously, including: - * - * name (of nodeRef) - * displayPath - * typeQName - * firstName (of posting user) - * lastName (of posting user) - * - * @param activityType - required - * @param siteId - optional, if null will be stored as empty string - * @param appTool - optional, if null will be stored as empty string - * @param nodeRef - required - do not use for deleted (or about to be deleted) nodeRef - */ - public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef); - - /** - * Post a pre-defined activity type - eg. for checked-out nodeRef or renamed nodeRef - * - * @param activityType - required - * @param siteId - optional, if null will be stored as empty string - * @param appTool - optional, if null will be stored as empty string - * @param nodeRef - required - do not use deleted (or about to be deleted) nodeRef - * @param beforeName - optional - name of node (eg. prior to name change) - */ - public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef, String beforeName); - - /** - * Post a pre-defined activity type - eg. for deleted nodeRef - * - * @param activityType - required - * @param siteId - optional, if null will be stored as empty string - * @param appTool - optional, if null will be stored as empty string - * @param nodeRef - required - can be a deleted (or about to be deleted) nodeRef - * @param name - optional - name of name - * @param typeQName - optional - type of node - * @param parentNodeRef - required - used to lookup path/displayPath - */ - public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef, String name, QName typeQName, NodeRef parentNodeRef); - - +public interface ActivityService extends ActivityPostService +{ /* * Retrieve Feed Entries */