mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-30 18:15:39 +00:00
MOB-822 - Activity feed generator - optimise to use embedded calls (as alternative to existing remote repo callbacks)
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@14163 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
parent
46a2ffcb82
commit
3aa7e15332
@ -9,6 +9,7 @@
|
||||
<property name="feedControlDAO" ref="feedControlDAO"/>
|
||||
<property name="authorityService" ref="AuthorityService"/>
|
||||
<property name="tenantService" ref="tenantService"/>
|
||||
<property name="siteService" ref="siteService"/>
|
||||
<property name="userNamesAreCaseSensitive" value="${user.name.caseSensitive}"/>
|
||||
<property name="feedGenerator" ref="feedGenerator"/>
|
||||
<property name="maxFeedItems" value="${activities.feed.max.size}"/>
|
||||
@ -64,6 +65,21 @@
|
||||
<property name="postDAO" ref="postDAO"/>
|
||||
<property name="feedDAO" ref="feedDAO"/>
|
||||
<property name="feedControlDAO" ref="feedControlDAO"/>
|
||||
|
||||
<property name="useRemoteCallbacks">
|
||||
<value>false</value>
|
||||
</property>
|
||||
|
||||
<property name="siteService" ref="SiteService"/>
|
||||
<property name="nodeService" ref="NodeService"/>
|
||||
<property name="contentService" ref="ContentService"/>
|
||||
<property name="templateSearchPaths">
|
||||
<list>
|
||||
<value>alfresco/extension/templates/activities</value>
|
||||
<value>alfresco/templates/activities</value>
|
||||
</list>
|
||||
</property>
|
||||
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
@ -38,11 +38,14 @@ 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.ActivityService;
|
||||
import org.alfresco.service.cmr.activities.FeedControl;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
import org.apache.commons.logging.Log;
|
||||
@ -69,6 +72,7 @@ public class ActivityServiceImpl implements ActivityService
|
||||
private FeedControlDAO feedControlDAO;
|
||||
private AuthorityService authorityService;
|
||||
private FeedGenerator feedGenerator;
|
||||
private SiteService siteService;
|
||||
|
||||
private TenantService tenantService;
|
||||
|
||||
@ -116,6 +120,11 @@ public class ActivityServiceImpl implements ActivityService
|
||||
this.tenantService = tenantService;
|
||||
}
|
||||
|
||||
public void setSiteService(SiteService siteService)
|
||||
{
|
||||
this.siteService = siteService;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
|
||||
@ -310,6 +319,15 @@ public class ActivityServiceImpl implements ActivityService
|
||||
feedUserId = feedUserId.toLowerCase();
|
||||
}
|
||||
|
||||
String currentUser = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
if (! ((currentUser == null) ||
|
||||
(currentUser.equals(AuthenticationUtil.getSystemUserName())) ||
|
||||
(authorityService.isAdminAuthority(currentUser)) ||
|
||||
(currentUser.equals(feedUserId))))
|
||||
{
|
||||
throw new AccessDeniedException("Unable to get user feed entries for '" + feedUserId + "' - currently logged in as '" + currentUser +"'");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
List<ActivityFeedEntity> activityFeeds = null;
|
||||
@ -361,6 +379,15 @@ public class ActivityServiceImpl implements ActivityService
|
||||
|
||||
try
|
||||
{
|
||||
if (siteService != null)
|
||||
{
|
||||
SiteInfo siteInfo = siteService.getSite(siteId);
|
||||
if (siteInfo == null)
|
||||
{
|
||||
throw new AccessDeniedException("No such site: " + siteId);
|
||||
}
|
||||
}
|
||||
|
||||
siteId = tenantService.getName(siteId);
|
||||
|
||||
List<ActivityFeedEntity> activityFeeds = feedDAO.selectSiteFeedEntries(siteId, format);
|
||||
|
545
source/java/org/alfresco/repo/activities/SiteActivityTest.java
Normal file
545
source/java/org/alfresco/repo/activities/SiteActivityTest.java
Normal file
@ -0,0 +1,545 @@
|
||||
/*
|
||||
* 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.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
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.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.repo.site.SiteModel;
|
||||
import org.alfresco.service.cmr.activities.ActivityService;
|
||||
import org.alfresco.service.cmr.activities.FeedControl;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.service.cmr.site.SiteVisibility;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.alfresco.util.PropertyMap;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
* Simple Activity Service unit test using site (membership) activities
|
||||
*
|
||||
* @author janv
|
||||
*/
|
||||
public class SiteActivityTest extends TestCase
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(SiteActivityTest.class);
|
||||
|
||||
private static ApplicationContext applicationContext = ApplicationContextHelper.getApplicationContext();
|
||||
|
||||
private SiteService siteService;
|
||||
private ActivityService activityService;
|
||||
private AuthenticationService authenticationService;
|
||||
private PersonService personService;
|
||||
private PostLookup postLookup;
|
||||
private FeedGenerator feedGenerator;
|
||||
|
||||
//
|
||||
// Test config & data
|
||||
//
|
||||
|
||||
// Location of activity type templates (for site activities)
|
||||
private static final String TEST_TEMPLATES_LOCATION = "activities"; // assumes test-resources is on classpath
|
||||
|
||||
// Test users
|
||||
private static final String ADMIN_USER = "admin";
|
||||
private static final String ADMIN_PW = "admin";
|
||||
|
||||
private static String user1 = null;
|
||||
private static String user2 = null;
|
||||
private static String user3 = null;
|
||||
private static String user4 = null;
|
||||
|
||||
private static final String USER_PW = "password";
|
||||
|
||||
// Test sites
|
||||
private static String site1 = null;
|
||||
private static String site2 = null;
|
||||
private static String site3 = null;
|
||||
|
||||
// AppToolId for site membership activities
|
||||
private static String appToolId = "siteService"; // refer to SiteService
|
||||
|
||||
private static boolean membersAddedUpdated = false;
|
||||
private static boolean membersRemoved = false;
|
||||
private static boolean controlsCreated = false;
|
||||
|
||||
public SiteActivityTest()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
String testid = ""+System.currentTimeMillis();
|
||||
|
||||
// Get the required services
|
||||
this.activityService = (ActivityService)applicationContext.getBean("activityService");
|
||||
this.siteService = (SiteService)applicationContext.getBean("SiteService");
|
||||
this.authenticationService = (AuthenticationService)applicationContext.getBean("AuthenticationService");
|
||||
this.personService = (PersonService)applicationContext.getBean("PersonService");
|
||||
|
||||
this.postLookup = (PostLookup)applicationContext.getBean("postLookup");
|
||||
this.feedGenerator = (FeedGenerator)applicationContext.getBean("feedGenerator");
|
||||
|
||||
LocalFeedTaskProcessor feedProcessor = (LocalFeedTaskProcessor)applicationContext.getBean("feedTaskProcessor");
|
||||
List<String> templateSearchPaths = new ArrayList<String>(1);
|
||||
templateSearchPaths.add(TEST_TEMPLATES_LOCATION);
|
||||
feedProcessor.setTemplateSearchPaths(templateSearchPaths);
|
||||
feedProcessor.setUseRemoteCallbacks(false);
|
||||
|
||||
site1 = "test_site1_" + testid;
|
||||
site2 = "test_site2_" + testid;
|
||||
site3 = "test_site3_" + testid;
|
||||
|
||||
user1 = "test_user1_" + testid;
|
||||
user2 = "test_user2_" + testid;
|
||||
user3 = "test_user3_" + testid;
|
||||
user4 = "test_user4_" + testid;
|
||||
|
||||
|
||||
// create users
|
||||
|
||||
login(ADMIN_USER, ADMIN_PW);
|
||||
|
||||
createUser(user1, USER_PW);
|
||||
createUser(user2, USER_PW);
|
||||
createUser(user3, USER_PW);
|
||||
createUser(user4, USER_PW);
|
||||
|
||||
// create sites
|
||||
|
||||
// create public site
|
||||
createSite(site1, true);
|
||||
|
||||
// create private sites
|
||||
createSite(site2, false);
|
||||
createSite(site3, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
login(ADMIN_USER, ADMIN_PW);
|
||||
|
||||
deleteUser(user1);
|
||||
deleteUser(user2);
|
||||
deleteUser(user3);
|
||||
deleteUser(user4);
|
||||
|
||||
membersAddedUpdated = false;
|
||||
membersRemoved = false;
|
||||
controlsCreated = false;
|
||||
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
protected void createSite(String siteId, boolean isPublic) throws Exception
|
||||
{
|
||||
siteService.createSite("myPreset", siteId, "myTitle", "myDescription", (isPublic ? SiteVisibility.PUBLIC : SiteVisibility.PRIVATE));
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("createdSite: " + siteId);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetSiteFeedsBefore() throws Exception
|
||||
{
|
||||
login(ADMIN_USER, ADMIN_PW);
|
||||
|
||||
getSiteFeed(site1, 0);
|
||||
getSiteFeed(site2, 0); // site 2 is private, but accessible to admins
|
||||
getSiteFeed(site3, 0); // site 3 is private, but accessible to admins
|
||||
|
||||
login(user4, USER_PW);
|
||||
|
||||
getSiteFeed(site1, 0); // site 1 is public, hence site feed is accessible to any user of the system
|
||||
|
||||
try
|
||||
{
|
||||
getSiteFeed(site2, 0); // site 2 is private, hence only accessible to members or admins
|
||||
|
||||
fail("Site feed for private site should not be accessible to non-admin / non-member");
|
||||
}
|
||||
catch (AccessDeniedException ade)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
getSiteFeed(site3, 0); // site 3 is private, hence only accessible to members or admins
|
||||
|
||||
fail("Site feed for private site should not be accessible to non-admin / non-member");
|
||||
}
|
||||
catch (AccessDeniedException ade)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
protected void getSiteFeed(String siteId, int expectedCount) throws Exception
|
||||
{
|
||||
assertEquals(expectedCount, activityService.getSiteFeedEntries(siteId, "json").size());
|
||||
}
|
||||
|
||||
public void testGetUserFeedsBefore() throws Exception
|
||||
{
|
||||
// as admin
|
||||
|
||||
login(ADMIN_USER, ADMIN_PW);
|
||||
|
||||
getUserFeed(user1, true, 0);
|
||||
getUserFeed(user2, true, 0);
|
||||
getUserFeed(user3, true, 0);
|
||||
getUserFeed(user4, true, 0);
|
||||
|
||||
// as user1
|
||||
|
||||
login(user1, USER_PW);
|
||||
|
||||
getUserFeed(user1, false, 0);
|
||||
|
||||
// as user2
|
||||
|
||||
login(user2, USER_PW);
|
||||
|
||||
try
|
||||
{
|
||||
getUserFeed(user1, true, 0);
|
||||
|
||||
fail("User feed should only be accessible to user or an admin");
|
||||
}
|
||||
catch (AccessDeniedException ade)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
|
||||
// as user1 - with filter args ...
|
||||
|
||||
login(user1, USER_PW);
|
||||
|
||||
getUserFeed(null, site1, false, false, false, 0);
|
||||
getUserFeed(null, site2, false, false, false, 0);
|
||||
getUserFeed(null, site3, false, false, false, 0);
|
||||
|
||||
getUserFeed(null, null, false, true, false, 0);
|
||||
getUserFeed(null, null, false, false, true, 0);
|
||||
getUserFeed(null, null, false, true, true, 0);
|
||||
}
|
||||
|
||||
protected void getUserFeed(String userId, boolean isAdmin, int expectedCount) throws Exception
|
||||
{
|
||||
getUserFeed(userId, null, isAdmin, false, false, expectedCount);
|
||||
}
|
||||
|
||||
protected void getUserFeed(String userId, String siteId, boolean isAdmin, boolean excludeThisUser, boolean excludeOtherUsers, int expectedCount) throws Exception
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
userId = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
}
|
||||
assertEquals(expectedCount, activityService.getUserFeedEntries(userId, "json", siteId, excludeThisUser, excludeOtherUsers).size());
|
||||
}
|
||||
|
||||
public void testUserFeedControls() throws Exception
|
||||
{
|
||||
if (! controlsCreated)
|
||||
{
|
||||
// user 1 opts out of all activities for site 1
|
||||
login(user1, USER_PW);
|
||||
addFeedControl(site1, null);
|
||||
|
||||
// user 2 opts out of site membership activities (across all sites)
|
||||
login(user2, USER_PW);
|
||||
addFeedControl(null, appToolId);
|
||||
|
||||
// user 3 opts out of site membership activities for site 1 only
|
||||
login(user3, USER_PW);
|
||||
addFeedControl(site1, appToolId);
|
||||
|
||||
// TODO add more here, once we have more appToolIds
|
||||
|
||||
controlsCreated = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void testAddAndUpdateMemberships() throws Exception
|
||||
{
|
||||
if (! membersAddedUpdated)
|
||||
{
|
||||
login(ADMIN_USER, ADMIN_PW);
|
||||
|
||||
addAndUpdateMemberships(site1, true); // public site, include all users
|
||||
addAndUpdateMemberships(site2, true); // private site, include all users
|
||||
addAndUpdateMemberships(site3, false); // private site, do not include user 4
|
||||
|
||||
generateFeed();
|
||||
|
||||
membersAddedUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetSiteFeedsAfterAddAndUpdateMemberships() throws Exception
|
||||
{
|
||||
testAddAndUpdateMemberships();
|
||||
|
||||
login(ADMIN_USER, ADMIN_PW);
|
||||
|
||||
getSiteFeed(site1, 8); // 8 = 4 users, each with 1 join, 1 role change
|
||||
getSiteFeed(site2, 8); // 8 = 4 users, each with 1 join, 1 role change
|
||||
getSiteFeed(site3, 6); // 6 = 3 users, each with 1 join, 1 role change (not user 4)
|
||||
|
||||
login(user4, USER_PW);
|
||||
|
||||
getSiteFeed(site1, 8);
|
||||
getSiteFeed(site2, 8); // site 2 is private, user 4 is a member
|
||||
|
||||
try
|
||||
{
|
||||
getSiteFeed(site3, 0); // site 3 is private, user 4 is not a member
|
||||
|
||||
fail("Site feed for private site should not be accessible to non-admin / non-member");
|
||||
}
|
||||
catch (AccessDeniedException ade)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
public void testRemoveMemberships() throws Exception
|
||||
{
|
||||
if (! membersRemoved)
|
||||
{
|
||||
testAddAndUpdateMemberships();
|
||||
|
||||
login(ADMIN_USER, ADMIN_PW);
|
||||
|
||||
removeMemberships(site1, true);
|
||||
removeMemberships(site2, true);
|
||||
removeMemberships(site3, false);
|
||||
|
||||
generateFeed();
|
||||
|
||||
membersRemoved = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected void addAndUpdateMemberships(String siteId, boolean includeUser4) throws Exception
|
||||
{
|
||||
// add member -> join site
|
||||
addMembership(siteId, user1, SiteModel.SITE_CONSUMER);
|
||||
addMembership(siteId, user2, SiteModel.SITE_MANAGER);
|
||||
addMembership(siteId, user3, SiteModel.SITE_COLLABORATOR);
|
||||
|
||||
if (includeUser4) { addMembership(siteId, user4, SiteModel.SITE_CONSUMER); }
|
||||
|
||||
// update member -> change role
|
||||
updateMembership(siteId, user1, SiteModel.SITE_MANAGER);
|
||||
updateMembership(siteId, user2, SiteModel.SITE_COLLABORATOR);
|
||||
updateMembership(siteId, user3, SiteModel.SITE_CONSUMER);
|
||||
|
||||
if (includeUser4) { updateMembership(siteId, user4, SiteModel.SITE_COLLABORATOR); }
|
||||
}
|
||||
|
||||
protected void removeMemberships(String siteId, boolean includeUser4) throws Exception
|
||||
{
|
||||
// remove member -> leave site
|
||||
removeMembership(siteId, user1);
|
||||
removeMembership(siteId, user2);
|
||||
removeMembership(siteId, user3);
|
||||
|
||||
if (includeUser4) { removeMembership(siteId, user4); }
|
||||
}
|
||||
|
||||
private void addFeedControl(String siteId, String appToolId) throws Exception
|
||||
{
|
||||
// set feed control for current user
|
||||
activityService.setFeedControl(new FeedControl(siteId, appToolId));
|
||||
}
|
||||
|
||||
public void testGetSiteFeedsAfterRemoveMemberships() throws Exception
|
||||
{
|
||||
testAddAndUpdateMemberships();
|
||||
testRemoveMemberships();
|
||||
|
||||
login(ADMIN_USER, ADMIN_PW);
|
||||
|
||||
getSiteFeed(site1, 12); // 12 = 4 users, each with 1 join, 1 role change, 1 leave
|
||||
getSiteFeed(site2, 12); // 12 = 4 users, each with 1 join, 1 role change, 1 leave
|
||||
getSiteFeed(site3, 9); // 9 = 3 users, each with 1 join, 1 role change, 1 leave (not user 4)
|
||||
|
||||
login(user4, USER_PW);
|
||||
|
||||
getSiteFeed(site1, 12);
|
||||
|
||||
try
|
||||
{
|
||||
getSiteFeed(site2, 0); // site 2 is private, user 4 is no longer a member
|
||||
|
||||
fail("Site feed for private site should not be accessible to non-admin / non-member");
|
||||
}
|
||||
catch (AccessDeniedException ade)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
getSiteFeed(site3, 0); // site 3 is private, user 4 was never a member
|
||||
|
||||
fail("Site feed for private site should not be accessible to non-admin / non-member");
|
||||
}
|
||||
catch (AccessDeniedException ade)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetUserFeedsAfter() throws Exception
|
||||
{
|
||||
testUserFeedControls();
|
||||
testAddAndUpdateMemberships();
|
||||
testRemoveMemberships();
|
||||
|
||||
// as admin
|
||||
|
||||
login(ADMIN_USER, ADMIN_PW);
|
||||
|
||||
// site 1, with 4 users, each with 1 join, 1 role change = 4x2 = 8
|
||||
// site 2, with 4 users, each with 1 join, 1 role change = 4x2 = 8
|
||||
// site 3, with 3 users, each with 1 join, 1 role change = 3x2 = 6
|
||||
|
||||
// user 1 belongs to 3 sites = (2x8)+(1x6) = 22
|
||||
// user 2 belongs to 3 sites = (2x8)+(1x6) = 22
|
||||
// user 3 belongs to 3 sites = (2x8)+(1x6) = 22
|
||||
// user 4 belongs to 2 sites = (2x8) = 16
|
||||
|
||||
getUserFeed(user1, true, 14); // 14 = (22 - 8) due to feed control - exclude site 1
|
||||
getUserFeed(user2, true, 0); // 0 = due to feed control - exclude site membership activities (across all sites)
|
||||
getUserFeed(user3, true, 14); // 14 = (22 - 8) due to feed control - exclude site membership activities for site 1
|
||||
getUserFeed(user4, true, 16); // 16 = no feed control
|
||||
|
||||
// as user1
|
||||
|
||||
login(user1, USER_PW);
|
||||
|
||||
getUserFeed(user1, false, 14);
|
||||
|
||||
// as user2
|
||||
|
||||
login(user2, USER_PW);
|
||||
|
||||
try
|
||||
{
|
||||
getUserFeed(user1, true, 14);
|
||||
|
||||
fail("User feed should only be accessible to user or an admin");
|
||||
}
|
||||
catch (AccessDeniedException ade)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
// as user1 - with filter args ...
|
||||
|
||||
login(user1, USER_PW);
|
||||
|
||||
getUserFeed(null, site1, false, false, false, 0);
|
||||
getUserFeed(null, site2, false, false, false, 8);
|
||||
getUserFeed(null, site3, false, false, false, 6);
|
||||
|
||||
getUserFeed(null, null, false, false, false, 14); // no filter
|
||||
getUserFeed(null, null, false, true, false, 14); // exclude any from user1
|
||||
getUserFeed(null, null, false, false, true, 0); // exclude all except user1
|
||||
getUserFeed(null, null, false, true, true, 0); // exclude all (NOOP)
|
||||
|
||||
// TODO - add more (eg. other non-admin user activities)
|
||||
}
|
||||
|
||||
private void addMembership(String siteId, String userName, String role) throws Exception
|
||||
{
|
||||
updateMembership(siteId, userName, role);
|
||||
}
|
||||
|
||||
private void updateMembership(String siteId, String userName, String role) throws Exception
|
||||
{
|
||||
siteService.setMembership(siteId, userName, role);
|
||||
}
|
||||
|
||||
private void removeMembership(String siteId, String userName) throws Exception
|
||||
{
|
||||
siteService.removeMembership(siteId, userName);
|
||||
}
|
||||
|
||||
protected void createUser(String userName, String password)
|
||||
{
|
||||
if (authenticationService.authenticationExists(userName) == false)
|
||||
{
|
||||
authenticationService.createAuthentication(userName, password.toCharArray());
|
||||
|
||||
PropertyMap ppOne = new PropertyMap(4);
|
||||
ppOne.put(ContentModel.PROP_USERNAME, userName);
|
||||
ppOne.put(ContentModel.PROP_FIRSTNAME, "firstName");
|
||||
ppOne.put(ContentModel.PROP_LASTNAME, "lastName");
|
||||
ppOne.put(ContentModel.PROP_EMAIL, "email@email.com");
|
||||
ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle");
|
||||
|
||||
personService.createPerson(ppOne);
|
||||
}
|
||||
}
|
||||
|
||||
protected void deleteUser(String userName)
|
||||
{
|
||||
if (authenticationService.authenticationExists(userName) == true)
|
||||
{
|
||||
personService.deletePerson(userName);
|
||||
authenticationService.deleteAuthentication(userName);
|
||||
}
|
||||
}
|
||||
|
||||
private void login(String username, String password)
|
||||
{
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(username);
|
||||
}
|
||||
|
||||
private void generateFeed() throws Exception
|
||||
{
|
||||
postLookup.execute();
|
||||
feedGenerator.execute();
|
||||
}
|
||||
}
|
@ -82,6 +82,8 @@ public abstract class FeedTaskProcessor
|
||||
|
||||
public void process(int jobTaskNode, long minSeq, long maxSeq, RepoCtx ctx) throws Exception
|
||||
{
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(">>> Process: jobTaskNode '" + jobTaskNode + "' from seq '" + minSeq + "' to seq '" + maxSeq + "' on this node from grid job.");
|
||||
@ -168,6 +170,14 @@ public abstract class FeedTaskProcessor
|
||||
}
|
||||
|
||||
activityTemplates.put(baseActivityType, fmTemplates);
|
||||
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
for (String fmTemplate : fmTemplates)
|
||||
{
|
||||
logger.trace("For activityType '"+activityType+"' found activity type template: "+fmTemplate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fmTemplates.size() == 0)
|
||||
@ -232,9 +242,9 @@ public abstract class FeedTaskProcessor
|
||||
{
|
||||
startTransaction();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.debug(">>> Process: " + connectedUsers.size() + " candidate connections for activity post " + activityPost.getId());
|
||||
logger.trace(">>> Process: " + connectedUsers.size() + " candidate connections for activity post " + activityPost.getId());
|
||||
}
|
||||
|
||||
int excludedConnections = 0;
|
||||
@ -335,7 +345,7 @@ public abstract class FeedTaskProcessor
|
||||
}
|
||||
finally
|
||||
{
|
||||
logger.info(">>> Generated " + totalGenerated + " activity feed entries for " + (activityPosts == null ? 0 : activityPosts.size()) + " activity posts");
|
||||
logger.info(">>> Generated " + totalGenerated + " activity feed entries for " + (activityPosts == null ? 0 : activityPosts.size()) + " activity posts (in " + (System.currentTimeMillis() - startTime) + " msecs)");
|
||||
}
|
||||
}
|
||||
|
||||
@ -428,7 +438,7 @@ public abstract class FeedTaskProcessor
|
||||
{
|
||||
userName = userName.toLowerCase();
|
||||
}
|
||||
members.add(person.getString("userName"));
|
||||
members.add(userName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -459,16 +469,20 @@ public abstract class FeedTaskProcessor
|
||||
for (int i = 0; i < ja.length(); i++)
|
||||
{
|
||||
String name = ja.getString(i);
|
||||
if (! name.contains(" (Working Copy)."))
|
||||
{
|
||||
allTemplateNames.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
return getActivityTemplates(allTemplateNames);
|
||||
}
|
||||
|
||||
protected Map<String, List<String>> getActivityTemplates(List<String> allTemplateNames)
|
||||
{
|
||||
Map<String, List<String>> activityTemplates = new HashMap<String, List<String>>(10);
|
||||
|
||||
for (String template : allTemplateNames)
|
||||
{
|
||||
if (! template.contains(" (Working Copy)."))
|
||||
{
|
||||
// assume template path = <path>/<base-activityType>.<format>.ftl
|
||||
// and base-activityType can contain "."
|
||||
@ -498,6 +512,7 @@ public abstract class FeedTaskProcessor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return activityTemplates;
|
||||
}
|
||||
|
@ -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
|
||||
@ -25,7 +25,6 @@
|
||||
package org.alfresco.repo.activities.feed.local;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
|
||||
import org.alfresco.repo.activities.feed.AbstractFeedGenerator;
|
||||
import org.alfresco.repo.activities.feed.FeedGridJob;
|
||||
@ -74,7 +73,7 @@ public class LocalFeedGenerator extends AbstractFeedGenerator
|
||||
logger.debug(">>> Execute job cycle: " + gridName + " (maxSeq: " + maxSequence + ")");
|
||||
}
|
||||
|
||||
long startTime = new Date().getTime();
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// TODO ... or push this upto to job scheduler ... ?
|
||||
AuthenticationUtil.runAs(new RunAsWork<Object>()
|
||||
@ -102,11 +101,9 @@ public class LocalFeedGenerator extends AbstractFeedGenerator
|
||||
job.execute();
|
||||
}
|
||||
|
||||
long endTime = new Date().getTime();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(">>> Finish job cycle: " + gridName + " (time taken (secs) = " + ((endTime - startTime) / 1000) + ")");
|
||||
logger.debug(">>> Finish job cycle: " + gridName + " (in " + (System.currentTimeMillis() - startTime) + " msecs)");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -24,28 +24,57 @@
|
||||
*/
|
||||
package org.alfresco.repo.activities.feed.local;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.activities.feed.FeedTaskProcessor;
|
||||
import org.alfresco.repo.activities.feed.RepoCtx;
|
||||
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.template.ClassPathRepoTemplateLoader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
|
||||
import com.ibatis.sqlmap.client.SqlMapClient;
|
||||
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.DefaultObjectWrapper;
|
||||
|
||||
/**
|
||||
* The local (ie. not grid) feed task processor is responsible for processing the individual feed job
|
||||
*/
|
||||
public class LocalFeedTaskProcessor extends FeedTaskProcessor
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(LocalFeedTaskProcessor.class);
|
||||
|
||||
private ActivityPostDAO postDAO;
|
||||
private ActivityFeedDAO feedDAO;
|
||||
private FeedControlDAO feedControlDAO;
|
||||
|
||||
// can call locally (instead of remote repo callback)
|
||||
private SiteService siteService;
|
||||
private NodeService nodeService;
|
||||
private ContentService contentService;
|
||||
private String defaultEncoding;
|
||||
private List<String> templateSearchPaths;
|
||||
private boolean useRemoteCallbacks;
|
||||
|
||||
// used to start/end/commit transaction
|
||||
// note: currently assumes that all dao services are configured with this mapper / data source
|
||||
private SqlMapClient sqlMapper;
|
||||
@ -65,6 +94,36 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor
|
||||
this.feedControlDAO = feedControlDAO;
|
||||
}
|
||||
|
||||
public void setSiteService(SiteService siteService)
|
||||
{
|
||||
this.siteService = siteService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setContentService(ContentService contentService)
|
||||
{
|
||||
this.contentService = contentService;
|
||||
}
|
||||
|
||||
public void setDefaultEncoding(String defaultEncoding)
|
||||
{
|
||||
this.defaultEncoding = defaultEncoding;
|
||||
}
|
||||
|
||||
public void setTemplateSearchPaths(List<String> templateSearchPaths)
|
||||
{
|
||||
this.templateSearchPaths = templateSearchPaths;
|
||||
}
|
||||
|
||||
public void setUseRemoteCallbacks(boolean useRemoteCallbacks)
|
||||
{
|
||||
this.useRemoteCallbacks = useRemoteCallbacks;
|
||||
}
|
||||
|
||||
public void setSqlMapClient(SqlMapClient sqlMapper)
|
||||
{
|
||||
this.sqlMapper = sqlMapper;
|
||||
@ -104,4 +163,169 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor
|
||||
{
|
||||
return feedControlDAO.selectFeedControls(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<String> getSiteMembers(final RepoCtx ctx, final String siteId) throws Exception
|
||||
{
|
||||
if (useRemoteCallbacks)
|
||||
{
|
||||
// as per 3.0, 3.1
|
||||
return super.getSiteMembers(ctx, siteId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// optimise for non-remote implementation - override remote repo callback (to "List Site Memberships" web script) with embedded call
|
||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Set<String>>()
|
||||
{
|
||||
public Set<String> doWork() throws Exception
|
||||
{
|
||||
Set<String> members = new HashSet<String>();
|
||||
if ((siteId != null) && (siteId.length() != 0))
|
||||
{
|
||||
Map<String, String> mapResult = siteService.listMembers(siteId, null, null, 0, true);
|
||||
|
||||
if ((mapResult != null) && (mapResult.size() != 0))
|
||||
{
|
||||
for (String userName : mapResult.keySet())
|
||||
{
|
||||
if (! ctx.isUserNamesAreCaseSensitive())
|
||||
{
|
||||
userName = userName.toLowerCase();
|
||||
}
|
||||
members.add(userName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return members;
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, List<String>> getActivityTypeTemplates(String repoEndPoint, String ticket, String subPath) throws Exception
|
||||
{
|
||||
if (useRemoteCallbacks)
|
||||
{
|
||||
// as per 3.0, 3.1
|
||||
return super.getActivityTypeTemplates(repoEndPoint, ticket, subPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// optimisation - override remote repo callback (to "Activities Templates" web script) with local/embedded call
|
||||
|
||||
String path = "/";
|
||||
String templatePattern = "*.ftl";
|
||||
|
||||
if ((subPath != null) && (subPath.length() > 0))
|
||||
{
|
||||
subPath = subPath + "*";
|
||||
|
||||
int idx = subPath.lastIndexOf("/");
|
||||
if (idx != -1)
|
||||
{
|
||||
path = subPath.substring(0, idx);
|
||||
templatePattern = subPath.substring(idx+1) + ".ftl";
|
||||
}
|
||||
}
|
||||
|
||||
List<String> allTemplateNames = getDocumentPaths(path, false, templatePattern);
|
||||
|
||||
return getActivityTemplates(allTemplateNames);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Configuration getFreemarkerConfiguration(RepoCtx ctx)
|
||||
{
|
||||
if (useRemoteCallbacks)
|
||||
{
|
||||
// as per 3.0, 3.1
|
||||
return super.getFreemarkerConfiguration(ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
Configuration cfg = new Configuration();
|
||||
cfg.setObjectWrapper(new DefaultObjectWrapper());
|
||||
|
||||
cfg.setTemplateLoader(new ClassPathRepoTemplateLoader(nodeService, contentService, defaultEncoding));
|
||||
|
||||
// TODO review i18n
|
||||
cfg.setLocalizedLookup(false);
|
||||
|
||||
return cfg;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to get template document paths
|
||||
private List<String> getDocumentPaths(String path, boolean includeSubPaths, String documentPattern)
|
||||
{
|
||||
if ((path == null) || (path.length() == 0))
|
||||
{
|
||||
path = "/";
|
||||
}
|
||||
|
||||
if (! path.startsWith("/"))
|
||||
{
|
||||
path = "/" + path;
|
||||
}
|
||||
|
||||
if (! path.endsWith("/"))
|
||||
{
|
||||
path = path + "/";
|
||||
}
|
||||
|
||||
if ((documentPattern == null) || (documentPattern.length() == 0))
|
||||
{
|
||||
documentPattern = "*";
|
||||
}
|
||||
|
||||
List<String> documentPaths = new ArrayList<String>(0);
|
||||
|
||||
for (String classPath : templateSearchPaths)
|
||||
{
|
||||
final StringBuilder pattern = new StringBuilder(128);
|
||||
pattern.append("classpath*:").append(classPath)
|
||||
.append(path)
|
||||
.append((includeSubPaths ? "**/" : ""))
|
||||
.append(documentPattern);
|
||||
|
||||
try
|
||||
{
|
||||
documentPaths.addAll(getPaths(pattern.toString(), classPath));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// Note: Ignore: no documents found
|
||||
}
|
||||
}
|
||||
|
||||
return documentPaths;
|
||||
}
|
||||
|
||||
// Helper to return a list of resource document paths based on a search pattern.
|
||||
private List<String> getPaths(String pattern, String classPath) throws IOException
|
||||
{
|
||||
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
|
||||
Resource[] resources = resolver.getResources(pattern);
|
||||
List<String> documentPaths = new ArrayList<String>(resources.length);
|
||||
for (Resource resource : resources)
|
||||
{
|
||||
String resourcePath = resource.getURL().toExternalForm();
|
||||
|
||||
int idx = resourcePath.lastIndexOf(classPath);
|
||||
if (idx != -1)
|
||||
{
|
||||
String documentPath = resourcePath.substring(idx);
|
||||
documentPath = documentPath.replace('\\', '/');
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("Item resource path: " + resourcePath + " , item path: " + documentPath);
|
||||
}
|
||||
documentPaths.add(documentPath);
|
||||
}
|
||||
}
|
||||
return documentPaths;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
<entry xmlns='http://www.w3.org/2005/Atom'>
|
||||
<title>${name!""}</title>
|
||||
<link rel="alternate" type="text/html"
|
||||
<#if nodeRef?? && nodeRef != "">
|
||||
href="${repoEndPoint}/d/d/${nodeRef?replace("://","/")}/${name!""}"
|
||||
<#else>
|
||||
href="${repoEndPoint}"
|
||||
</#if>
|
||||
/>
|
||||
<icon></icon>
|
||||
<id>${id}</id>
|
||||
<updated>${xmldate(date)}</updated>
|
||||
<summary>${userId!""} ${activityType!""} ${displayPath!""} <#if siteNetwork?? && siteNetwork != "">(${siteNetwork} site)</#if></summary>
|
||||
<author>
|
||||
<name>${userId!""}</name>
|
||||
</author>
|
||||
</entry>
|
@ -0,0 +1,2 @@
|
||||
<#-- default JSON rendering is to pass-through - assumes activityData is posted in JSON format -->
|
||||
${activityData!""}
|
@ -0,0 +1,11 @@
|
||||
<entry xmlns='http://www.w3.org/2005/Atom'>
|
||||
<title>${memberFirstName?xml}<#if memberLastName??> ${memberLastName?xml}</#if> joined ${siteNetwork?xml} site</title>
|
||||
<link rel="alternate" type="text/html"/>
|
||||
<icon></icon>
|
||||
<id>${id}</id>
|
||||
<updated>${xmldate(date)}</updated>
|
||||
<summary>${memberFirstName?xml}<#if memberLastName??> ${memberLastName?xml}</#if> joined ${siteNetwork?xml} site (with role ${role})</summary>
|
||||
<author>
|
||||
<name>${userId}</name>
|
||||
</author>
|
||||
</entry>
|
@ -0,0 +1,11 @@
|
||||
<entry xmlns='http://www.w3.org/2005/Atom'>
|
||||
<title>${memberFirstName?xml}<#if memberLastName??> ${memberLastName?xml}</#if> left ${siteNetwork?xml} site</title>
|
||||
<link rel="alternate" type="text/html"/>
|
||||
<icon></icon>
|
||||
<id>${id}</id>
|
||||
<updated>${xmldate(date)}</updated>
|
||||
<summary>${memberFirstName?xml}<#if memberLastName??> ${memberLastName?xml}</#if> left ${siteNetwork?xml} site</summary>
|
||||
<author>
|
||||
<name>${userId}</name>
|
||||
</author>
|
||||
</entry>
|
@ -0,0 +1,11 @@
|
||||
<entry xmlns='http://www.w3.org/2005/Atom'>
|
||||
<title>${memberFirstName?xml}<#if memberLastName??> ${memberLastName?xml}</#if> role changed for ${siteNetwork?xml} site</title>
|
||||
<link rel="alternate" type="text/html"/>
|
||||
<icon></icon>
|
||||
<id>${id}</id>
|
||||
<updated>${xmldate(date)}</updated>
|
||||
<summary>${memberFirstName?xml}<#if memberLastName??> ${memberLastName?xml}</#if> role changed to ${role} for ${siteNetwork?xml} site</summary>
|
||||
<author>
|
||||
<name>${userId}</name>
|
||||
</author>
|
||||
</entry>
|
Loading…
x
Reference in New Issue
Block a user