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="feedControlDAO" ref="feedControlDAO"/>
|
||||||
<property name="authorityService" ref="AuthorityService"/>
|
<property name="authorityService" ref="AuthorityService"/>
|
||||||
<property name="tenantService" ref="tenantService"/>
|
<property name="tenantService" ref="tenantService"/>
|
||||||
|
<property name="siteService" ref="siteService"/>
|
||||||
<property name="userNamesAreCaseSensitive" value="${user.name.caseSensitive}"/>
|
<property name="userNamesAreCaseSensitive" value="${user.name.caseSensitive}"/>
|
||||||
<property name="feedGenerator" ref="feedGenerator"/>
|
<property name="feedGenerator" ref="feedGenerator"/>
|
||||||
<property name="maxFeedItems" value="${activities.feed.max.size}"/>
|
<property name="maxFeedItems" value="${activities.feed.max.size}"/>
|
||||||
@ -64,6 +65,21 @@
|
|||||||
<property name="postDAO" ref="postDAO"/>
|
<property name="postDAO" ref="postDAO"/>
|
||||||
<property name="feedDAO" ref="feedDAO"/>
|
<property name="feedDAO" ref="feedDAO"/>
|
||||||
<property name="feedControlDAO" ref="feedControlDAO"/>
|
<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>
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</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.FeedControlDAO;
|
||||||
import org.alfresco.repo.domain.activities.FeedControlEntity;
|
import org.alfresco.repo.domain.activities.FeedControlEntity;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||||
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.ActivityService;
|
||||||
import org.alfresco.service.cmr.activities.FeedControl;
|
import org.alfresco.service.cmr.activities.FeedControl;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.security.AuthorityService;
|
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.service.namespace.QName;
|
||||||
import org.alfresco.util.ParameterCheck;
|
import org.alfresco.util.ParameterCheck;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
@ -69,6 +72,7 @@ public class ActivityServiceImpl implements ActivityService
|
|||||||
private FeedControlDAO feedControlDAO;
|
private FeedControlDAO feedControlDAO;
|
||||||
private AuthorityService authorityService;
|
private AuthorityService authorityService;
|
||||||
private FeedGenerator feedGenerator;
|
private FeedGenerator feedGenerator;
|
||||||
|
private SiteService siteService;
|
||||||
|
|
||||||
private TenantService tenantService;
|
private TenantService tenantService;
|
||||||
|
|
||||||
@ -116,6 +120,11 @@ public class ActivityServiceImpl implements ActivityService
|
|||||||
this.tenantService = tenantService;
|
this.tenantService = tenantService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSiteService(SiteService siteService)
|
||||||
|
{
|
||||||
|
this.siteService = siteService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
|
* @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
|
||||||
@ -309,7 +318,16 @@ public class ActivityServiceImpl implements ActivityService
|
|||||||
{
|
{
|
||||||
feedUserId = feedUserId.toLowerCase();
|
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
|
try
|
||||||
{
|
{
|
||||||
List<ActivityFeedEntity> activityFeeds = null;
|
List<ActivityFeedEntity> activityFeeds = null;
|
||||||
@ -358,9 +376,18 @@ public class ActivityServiceImpl implements ActivityService
|
|||||||
ParameterCheck.mandatoryString("format", format);
|
ParameterCheck.mandatoryString("format", format);
|
||||||
|
|
||||||
List<String> activityFeedEntries = new ArrayList<String>();
|
List<String> activityFeedEntries = new ArrayList<String>();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (siteService != null)
|
||||||
|
{
|
||||||
|
SiteInfo siteInfo = siteService.getSite(siteId);
|
||||||
|
if (siteInfo == null)
|
||||||
|
{
|
||||||
|
throw new AccessDeniedException("No such site: " + siteId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
siteId = tenantService.getName(siteId);
|
siteId = tenantService.getName(siteId);
|
||||||
|
|
||||||
List<ActivityFeedEntity> activityFeeds = feedDAO.selectSiteFeedEntries(siteId, format);
|
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
|
public void process(int jobTaskNode, long minSeq, long maxSeq, RepoCtx ctx) throws Exception
|
||||||
{
|
{
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
logger.debug(">>> Process: jobTaskNode '" + jobTaskNode + "' from seq '" + minSeq + "' to seq '" + maxSeq + "' on this node from grid job.");
|
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);
|
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)
|
if (fmTemplates.size() == 0)
|
||||||
@ -232,9 +242,9 @@ public abstract class FeedTaskProcessor
|
|||||||
{
|
{
|
||||||
startTransaction();
|
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;
|
int excludedConnections = 0;
|
||||||
@ -335,7 +345,7 @@ public abstract class FeedTaskProcessor
|
|||||||
}
|
}
|
||||||
finally
|
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)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,7 +423,7 @@ public abstract class FeedTaskProcessor
|
|||||||
StringBuffer sbUrl = new StringBuffer();
|
StringBuffer sbUrl = new StringBuffer();
|
||||||
sbUrl.append(ctx.getRepoEndPoint()).
|
sbUrl.append(ctx.getRepoEndPoint()).
|
||||||
append(URL_SERVICE_SITES).append("/").append(siteId).append(URL_MEMBERSHIPS);
|
append(URL_SERVICE_SITES).append("/").append(siteId).append(URL_MEMBERSHIPS);
|
||||||
|
|
||||||
String jsonArrayResult = callWebScript(sbUrl.toString(), ctx.getTicket());
|
String jsonArrayResult = callWebScript(sbUrl.toString(), ctx.getTicket());
|
||||||
if ((jsonArrayResult != null) && (jsonArrayResult.length() != 0))
|
if ((jsonArrayResult != null) && (jsonArrayResult.length() != 0))
|
||||||
{
|
{
|
||||||
@ -428,7 +438,7 @@ public abstract class FeedTaskProcessor
|
|||||||
{
|
{
|
||||||
userName = userName.toLowerCase();
|
userName = userName.toLowerCase();
|
||||||
}
|
}
|
||||||
members.add(person.getString("userName"));
|
members.add(userName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -459,42 +469,47 @@ public abstract class FeedTaskProcessor
|
|||||||
for (int i = 0; i < ja.length(); i++)
|
for (int i = 0; i < ja.length(); i++)
|
||||||
{
|
{
|
||||||
String name = ja.getString(i);
|
String name = ja.getString(i);
|
||||||
if (! name.contains(" (Working Copy)."))
|
allTemplateNames.add(name);
|
||||||
{
|
|
||||||
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);
|
Map<String, List<String>> activityTemplates = new HashMap<String, List<String>>(10);
|
||||||
|
|
||||||
for (String template : allTemplateNames)
|
for (String template : allTemplateNames)
|
||||||
{
|
{
|
||||||
// assume template path = <path>/<base-activityType>.<format>.ftl
|
if (! template.contains(" (Working Copy)."))
|
||||||
// and base-activityType can contain "."
|
|
||||||
|
|
||||||
String baseActivityType = template;
|
|
||||||
int idx1 = baseActivityType.lastIndexOf("/");
|
|
||||||
if (idx1 != -1)
|
|
||||||
{
|
{
|
||||||
baseActivityType = baseActivityType.substring(idx1+1);
|
// assume template path = <path>/<base-activityType>.<format>.ftl
|
||||||
}
|
// and base-activityType can contain "."
|
||||||
|
|
||||||
int idx2 = baseActivityType.lastIndexOf(".");
|
String baseActivityType = template;
|
||||||
if (idx2 != -1)
|
int idx1 = baseActivityType.lastIndexOf("/");
|
||||||
{
|
if (idx1 != -1)
|
||||||
int idx3 = baseActivityType.substring(0, idx2).lastIndexOf(".");
|
|
||||||
if (idx3 != -1)
|
|
||||||
{
|
{
|
||||||
baseActivityType = baseActivityType.substring(0, idx3);
|
baseActivityType = baseActivityType.substring(idx1+1);
|
||||||
|
}
|
||||||
List<String> activityTypeTemplateList = activityTemplates.get(baseActivityType);
|
|
||||||
if (activityTypeTemplateList == null)
|
int idx2 = baseActivityType.lastIndexOf(".");
|
||||||
|
if (idx2 != -1)
|
||||||
|
{
|
||||||
|
int idx3 = baseActivityType.substring(0, idx2).lastIndexOf(".");
|
||||||
|
if (idx3 != -1)
|
||||||
{
|
{
|
||||||
activityTypeTemplateList = new ArrayList<String>(1);
|
baseActivityType = baseActivityType.substring(0, idx3);
|
||||||
activityTemplates.put(baseActivityType, activityTypeTemplateList);
|
|
||||||
|
List<String> activityTypeTemplateList = activityTemplates.get(baseActivityType);
|
||||||
|
if (activityTypeTemplateList == null)
|
||||||
|
{
|
||||||
|
activityTypeTemplateList = new ArrayList<String>(1);
|
||||||
|
activityTemplates.put(baseActivityType, activityTypeTemplateList);
|
||||||
|
}
|
||||||
|
activityTypeTemplateList.add(template);
|
||||||
}
|
}
|
||||||
activityTypeTemplateList.add(template);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -506,14 +521,14 @@ public abstract class FeedTaskProcessor
|
|||||||
{
|
{
|
||||||
Configuration cfg = new Configuration();
|
Configuration cfg = new Configuration();
|
||||||
cfg.setObjectWrapper(new DefaultObjectWrapper());
|
cfg.setObjectWrapper(new DefaultObjectWrapper());
|
||||||
|
|
||||||
// custom template loader
|
// custom template loader
|
||||||
cfg.setTemplateLoader(new TemplateWebScriptLoader(ctx.getRepoEndPoint(), ctx.getTicket()));
|
cfg.setTemplateLoader(new TemplateWebScriptLoader(ctx.getRepoEndPoint(), ctx.getTicket()));
|
||||||
|
|
||||||
// TODO review i18n
|
// TODO review i18n
|
||||||
cfg.setLocalizedLookup(false);
|
cfg.setLocalizedLookup(false);
|
||||||
|
|
||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String processFreemarker(Map<String, Template> templateCache, String fmTemplate, Configuration cfg, Map<String, Object> model) throws IOException, TemplateException, Exception
|
protected String processFreemarker(Map<String, Template> templateCache, String fmTemplate, Configuration cfg, Map<String, Object> model) throws IOException, TemplateException, Exception
|
||||||
@ -574,7 +589,7 @@ public abstract class FeedTaskProcessor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,36 +641,36 @@ public abstract class FeedTaskProcessor
|
|||||||
|
|
||||||
protected class TemplateWebScriptLoader extends URLTemplateLoader
|
protected class TemplateWebScriptLoader extends URLTemplateLoader
|
||||||
{
|
{
|
||||||
private String repoEndPoint;
|
private String repoEndPoint;
|
||||||
private String ticketId;
|
private String ticketId;
|
||||||
|
|
||||||
public TemplateWebScriptLoader(String repoEndPoint, String ticketId)
|
public TemplateWebScriptLoader(String repoEndPoint, String ticketId)
|
||||||
{
|
{
|
||||||
this.repoEndPoint = repoEndPoint;
|
this.repoEndPoint = repoEndPoint;
|
||||||
this.ticketId = ticketId;
|
this.ticketId = ticketId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public URL getURL(String templatePath)
|
public URL getURL(String templatePath)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
sb.append(this.repoEndPoint).
|
sb.append(this.repoEndPoint).
|
||||||
append(URL_SERVICE_TEMPLATE).append("/").append(templatePath).
|
append(URL_SERVICE_TEMPLATE).append("/").append(templatePath).
|
||||||
append("?format=text").
|
append("?format=text").
|
||||||
append("&alf_ticket=").append(ticketId);
|
append("&alf_ticket=").append(ticketId);
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
logger.debug(">>> getURL: " + sb.toString());
|
logger.debug(">>> getURL: " + sb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new URL(sb.toString());
|
return new URL(sb.toString());
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@ -25,7 +25,6 @@
|
|||||||
package org.alfresco.repo.activities.feed.local;
|
package org.alfresco.repo.activities.feed.local;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import org.alfresco.repo.activities.feed.AbstractFeedGenerator;
|
import org.alfresco.repo.activities.feed.AbstractFeedGenerator;
|
||||||
import org.alfresco.repo.activities.feed.FeedGridJob;
|
import org.alfresco.repo.activities.feed.FeedGridJob;
|
||||||
@ -73,17 +72,17 @@ public class LocalFeedGenerator extends AbstractFeedGenerator
|
|||||||
{
|
{
|
||||||
logger.debug(">>> Execute job cycle: " + gridName + " (maxSeq: " + maxSequence + ")");
|
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 ... ?
|
// TODO ... or push this upto to job scheduler ... ?
|
||||||
AuthenticationUtil.runAs(new RunAsWork<Object>()
|
AuthenticationUtil.runAs(new RunAsWork<Object>()
|
||||||
{
|
{
|
||||||
public Object doWork()
|
public Object doWork()
|
||||||
{
|
{
|
||||||
getWebScriptsCtx().setTicket(getAuthenticationService().getCurrentTicket());
|
getWebScriptsCtx().setTicket(getAuthenticationService().getCurrentTicket());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}, AuthenticationUtil.getSystemUserName()); // need web scripts to support System-level authentication ... see RepositoryContainer !
|
}, AuthenticationUtil.getSystemUserName()); // need web scripts to support System-level authentication ... see RepositoryContainer !
|
||||||
|
|
||||||
JobSettings js = new JobSettings();
|
JobSettings js = new JobSettings();
|
||||||
@ -102,11 +101,9 @@ public class LocalFeedGenerator extends AbstractFeedGenerator
|
|||||||
job.execute();
|
job.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
long endTime = new Date().getTime();
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -24,28 +24,57 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.activities.feed.local;
|
package org.alfresco.repo.activities.feed.local;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
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.FeedTaskProcessor;
|
||||||
|
import org.alfresco.repo.activities.feed.RepoCtx;
|
||||||
import org.alfresco.repo.domain.activities.ActivityFeedDAO;
|
import org.alfresco.repo.domain.activities.ActivityFeedDAO;
|
||||||
import org.alfresco.repo.domain.activities.ActivityFeedEntity;
|
import org.alfresco.repo.domain.activities.ActivityFeedEntity;
|
||||||
import org.alfresco.repo.domain.activities.ActivityPostDAO;
|
import org.alfresco.repo.domain.activities.ActivityPostDAO;
|
||||||
import org.alfresco.repo.domain.activities.ActivityPostEntity;
|
import org.alfresco.repo.domain.activities.ActivityPostEntity;
|
||||||
import org.alfresco.repo.domain.activities.FeedControlDAO;
|
import org.alfresco.repo.domain.activities.FeedControlDAO;
|
||||||
import org.alfresco.repo.domain.activities.FeedControlEntity;
|
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 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
|
* The local (ie. not grid) feed task processor is responsible for processing the individual feed job
|
||||||
*/
|
*/
|
||||||
public class LocalFeedTaskProcessor extends FeedTaskProcessor
|
public class LocalFeedTaskProcessor extends FeedTaskProcessor
|
||||||
{
|
{
|
||||||
|
private static final Log logger = LogFactory.getLog(LocalFeedTaskProcessor.class);
|
||||||
|
|
||||||
private ActivityPostDAO postDAO;
|
private ActivityPostDAO postDAO;
|
||||||
private ActivityFeedDAO feedDAO;
|
private ActivityFeedDAO feedDAO;
|
||||||
private FeedControlDAO feedControlDAO;
|
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
|
// used to start/end/commit transaction
|
||||||
// note: currently assumes that all dao services are configured with this mapper / data source
|
// note: currently assumes that all dao services are configured with this mapper / data source
|
||||||
private SqlMapClient sqlMapper;
|
private SqlMapClient sqlMapper;
|
||||||
@ -65,6 +94,36 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor
|
|||||||
this.feedControlDAO = feedControlDAO;
|
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)
|
public void setSqlMapClient(SqlMapClient sqlMapper)
|
||||||
{
|
{
|
||||||
this.sqlMapper = sqlMapper;
|
this.sqlMapper = sqlMapper;
|
||||||
@ -104,4 +163,169 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor
|
|||||||
{
|
{
|
||||||
return feedControlDAO.selectFeedControls(userId);
|
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