mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
First-cut Activity Service (SLNG-20)
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@9128 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
19
config/alfresco/activities/activities-SqlMapConfig.xml
Normal file
19
config/alfresco/activities/activities-SqlMapConfig.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<!DOCTYPE sqlMapConfig
|
||||
PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
|
||||
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
|
||||
|
||||
<sqlMapConfig>
|
||||
|
||||
<!-- NOTE: although we use iBatis here rather than Hibernate, for consistency we make use of single SQL dialect property (hibernate.dialect) for consistency -->
|
||||
<properties resource="alfresco/domain/hibernate-cfg.properties" />
|
||||
|
||||
<!-- SQL Map XML files loaded from the classpath -->
|
||||
|
||||
<!-- note: dialect property is set in properties resource above -->
|
||||
<sqlMap resource="alfresco/activities/${hibernate.dialect}/ActivityPost.xml"/>
|
||||
<sqlMap resource="alfresco/activities/${hibernate.dialect}/ActivityFeed.xml"/>
|
||||
<sqlMap resource="alfresco/activities/${hibernate.dialect}/ActivityFeedControl.xml"/>
|
||||
|
||||
</sqlMapConfig>
|
86
config/alfresco/activities/activities-feed-context.xml
Normal file
86
config/alfresco/activities/activities-feed-context.xml
Normal file
@@ -0,0 +1,86 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||
|
||||
<beans>
|
||||
|
||||
<bean id="activityService" class="org.alfresco.repo.activities.ActivityServiceImpl">
|
||||
<property name="postDaoService" ref="postDaoService"/>
|
||||
<property name="feedDaoService" ref="feedDaoService"/>
|
||||
<property name="feedControlDaoService" ref="feedControlDaoService"/>
|
||||
<property name="authorityService" ref="AuthorityService"/>
|
||||
<property name="userNamesAreCaseSensitive" value="${user.name.caseSensitive}"/>
|
||||
<property name="feedGenerator" ref="feedGenerator"/>
|
||||
<property name="maxFeedItems" value="100"/>
|
||||
</bean>
|
||||
|
||||
<bean id="iBatisDataSource" parent="dataSource">
|
||||
<property name="defaultAutoCommit" >
|
||||
<value>true</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean" singleton="true">
|
||||
<property name="configLocation"><value>classpath:alfresco/activities/activities-SqlMapConfig.xml</value></property>
|
||||
<property name="dataSource" ref="iBatisDataSource"/>
|
||||
</bean>
|
||||
|
||||
<bean id="postDaoService" class="org.alfresco.repo.activities.ibatis.IBatisActivityPostDaoServiceImpl">
|
||||
<property name="sqlMapClient" ref="sqlMapClient"/>
|
||||
</bean>
|
||||
|
||||
<bean id="feedDaoService" class="org.alfresco.repo.activities.ibatis.IBatisActivityFeedDaoServiceImpl">
|
||||
<property name="sqlMapClient" ref="sqlMapClient"/>
|
||||
</bean>
|
||||
|
||||
<bean id="feedControlDaoService" class="org.alfresco.repo.activities.ibatis.IBatisFeedControlDaoServiceImpl">
|
||||
<property name="sqlMapClient" ref="sqlMapClient"/>
|
||||
</bean>
|
||||
|
||||
<!-- cleans out-of-date feed entries -->
|
||||
<bean id="feedCleaner" class="org.alfresco.repo.activities.feed.cleanup.FeedCleaner">
|
||||
<property name="feedDaoService" ref="feedDaoService"/>
|
||||
<property name="maxAgeMins">
|
||||
<value>20160</value> <!-- 20160 mins = 2 weeks -->
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- cleans processed posts - max age can be small, unless required to be kept longer (for debugging) -->
|
||||
<bean id="postCleaner" class="org.alfresco.repo.activities.post.cleanup.PostCleaner">
|
||||
<property name="postDaoService" ref="postDaoService"/>
|
||||
<property name="maxAgeMins">
|
||||
<value>30</value> <!-- 30 minutes -->
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- secondary lookup for pending posts -->
|
||||
<bean id="postLookup" class="org.alfresco.repo.activities.post.lookup.PostLookup">
|
||||
<property name="postDaoService" ref="postDaoService"/>
|
||||
<property name="nodeService" ref="NodeService"/>
|
||||
<property name="permissionService" ref="PermissionService"/>
|
||||
<property name="transactionService" ref="transactionService"/>
|
||||
<property name="personService" ref="personService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="baseFeedGenerator" class="org.alfresco.repo.activities.feed.AbstractFeedGenerator" abstract="true" init-method="init">
|
||||
<property name="postDaoService" ref="postDaoService"/>
|
||||
<property name="authenticationService" ref="AuthenticationService"/>
|
||||
<property name="repoEndPoint" value="${repo.remote.endpoint.url}"/>
|
||||
<property name="maxItemsPerCycle" value="100"/>
|
||||
</bean>
|
||||
|
||||
|
||||
<!-- Local (non-grid-based) Feed Generator -->
|
||||
|
||||
<bean id="feedGenerator" class="org.alfresco.repo.activities.feed.local.LocalFeedGenerator" parent="baseFeedGenerator">
|
||||
<property name="feedTaskProcessor" ref="feedTaskProcessor"/>
|
||||
</bean>
|
||||
|
||||
<bean id="feedTaskProcessor" class="org.alfresco.repo.activities.feed.local.LocalFeedTaskProcessor">
|
||||
<!-- NOTE: assumes same sqlMapClient is also configured for postDaoService and feedDaoService -->
|
||||
<property name="sqlMapClient" ref="sqlMapClient"/>
|
||||
<property name="postDaoService" ref="postDaoService"/>
|
||||
<property name="feedDaoService" ref="feedDaoService"/>
|
||||
<property name="feedControlDaoService" ref="feedControlDaoService"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
@@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<!DOCTYPE sqlMap
|
||||
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
|
||||
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
|
||||
|
||||
<sqlMap namespace="ActivityFeed">
|
||||
|
||||
<typeAlias alias="ActivityFeed" type="org.alfresco.repo.activities.feed.ActivityFeedDAO"/>
|
||||
|
||||
<resultMap id="ActivityFeedResult" class="ActivityFeed">
|
||||
<result property="id" column="ID"/>
|
||||
<result property="feedUserId" column="FEED_USER_ID"/>
|
||||
<result property="postUserId" column="POST_USER_ID"/>
|
||||
<result property="postDate" column="POST_DATE"/>
|
||||
<result property="postId" column="POST_ID"/> <!-- not an explicit FK constraint, can dangle if and when activity post is deleted -->
|
||||
<result property="siteNetwork" column="SITE_NETWORK"/>
|
||||
<result property="activityType" column="ACTIVITY_TYPE"/>
|
||||
<result property="activitySummary" column="ACTIVITY_SUMMARY"/>
|
||||
<result property="activitySummaryFormat" column="ACTIVITY_FORMAT"/>
|
||||
<result property="feedDate" column="FEED_DATE"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="select.activity.feed.for.feeduser" parameterClass="ActivityFeed" resultClass="ActivityFeed">
|
||||
<![CDATA[
|
||||
select id as id, activity_format as activitySummaryFormat, activity_summary as activitySummary, feed_user_id as feedUserId, post_user_id as postUserId, site_network as siteNetwork, post_date postDate
|
||||
from alf_activity_feed
|
||||
where feed_user_id = #feedUserId#
|
||||
and post_user_id != #feedUserId#
|
||||
and activity_format = #activitySummaryFormat#
|
||||
order by post_date desc
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<select id="select.activity.feedcontrol" parameterClass="FeedControl" resultClass="long">
|
||||
<![CDATA[
|
||||
select id as id
|
||||
from alf_activity_feed_control
|
||||
where feed_user_id = #feedUserId#
|
||||
and site_network = #siteNetwork#
|
||||
and app_tool = #appTool#
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<select id="select.activity.feed.for.feeduser.and.site" parameterClass="ActivityFeed" resultClass="ActivityFeed">
|
||||
<![CDATA[
|
||||
select id as id, activity_format as activitySummaryFormat, activity_summary as activitySummary, feed_user_id as feedUserId, post_user_id as postUserId, site_network as siteNetwork, post_date postDate
|
||||
from alf_activity_feed
|
||||
where feed_user_id = #feedUserId#
|
||||
and post_user_id != #feedUserId#
|
||||
and site_network = #siteNetwork#
|
||||
and activity_format = #activitySummaryFormat#
|
||||
order by post_date desc
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<select id="select.activity.feed.for.site" parameterClass="ActivityFeed" resultClass="ActivityFeed">
|
||||
<![CDATA[
|
||||
select id as id, activity_format as activitySummaryFormat, activity_summary as activitySummary, feed_user_id as feedUserId, post_user_id as postUserId, site_network as siteNetwork, post_date postDate
|
||||
from alf_activity_feed
|
||||
where feed_user_id = ''
|
||||
and site_network = #siteNetwork#
|
||||
and activity_format = #activitySummaryFormat#
|
||||
order by post_date desc
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<insert id="insert.activity.feed" parameterClass="ActivityFeed">
|
||||
insert into alf_activity_feed (activity_type, activity_summary, activity_format, feed_user_id, post_user_id, post_date, post_id, site_network, app_tool, feed_date)
|
||||
values (#activityType#, #activitySummary#, #activitySummaryFormat#, #feedUserId#, #postUserId#, #postDate#, #postId#, #siteNetwork#, #appTool#, #feedDate#)
|
||||
|
||||
<!-- optionally return auto-generated primary key - only required for debug (can be commented out) -->
|
||||
<selectKey resultClass="long" keyProperty="id" type="post">
|
||||
CALL IDENTITY()
|
||||
</selectKey>
|
||||
</insert>
|
||||
|
||||
<delete id="delete.activity.feed.entries.older.than.date" parameterClass="Date">
|
||||
<![CDATA[
|
||||
delete from alf_activity_feed where post_date < #keepdate#
|
||||
]]>
|
||||
</delete>
|
||||
|
||||
</sqlMap>
|
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<!DOCTYPE sqlMap
|
||||
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
|
||||
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
|
||||
|
||||
<sqlMap namespace="ActivityFeedControl">
|
||||
|
||||
<typeAlias alias="FeedControl" type="org.alfresco.repo.activities.feed.control.FeedControlDAO"/>
|
||||
|
||||
<resultMap id="FeedControlResult" class="FeedControl">
|
||||
<result property="id" column="ID"/>
|
||||
<result property="feedUserId" column="FEED_USER_ID"/>
|
||||
<result property="siteNetwork" column="SITE_NETWORK"/>
|
||||
<result property="appTool" column="APP_TOOL"/>
|
||||
<result property="lastModified" column="LAST_MODIFIED"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="select.activity.feedcontrols.for.user" parameterClass="FeedControl" resultClass="FeedControl">
|
||||
<![CDATA[
|
||||
select id as id, feed_user_id as feedUserId, site_network as siteNetwork, app_tool as appTool
|
||||
from alf_activity_feed_control
|
||||
where feed_user_id = #feedUserId#
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<insert id="insert.activity.feedcontrol" parameterClass="FeedControl">
|
||||
insert into alf_activity_feed_control (feed_user_id, site_network, app_tool, last_modified)
|
||||
values (#feedUserId#, #siteNetwork#, #appTool#, #lastModified#)
|
||||
|
||||
<!-- optionally return auto-generated primary key - only required for debug (can be commented out) -->
|
||||
<selectKey resultClass="long" keyProperty="id" type="post">
|
||||
CALL IDENTITY()
|
||||
</selectKey>
|
||||
</insert>
|
||||
|
||||
<delete id="delete.activity.feedcontrol" parameterClass="FeedControl">
|
||||
<![CDATA[
|
||||
delete from alf_activity_feed_control
|
||||
where feed_user_id = #feedUserId#
|
||||
and site_network = #siteNetwork#
|
||||
and app_tool = #appTool#
|
||||
]]>
|
||||
</delete>
|
||||
|
||||
</sqlMap>
|
114
config/alfresco/activities/org.hibernate.dialect.HSQLDialect/ActivityPost.xml
Executable file
114
config/alfresco/activities/org.hibernate.dialect.HSQLDialect/ActivityPost.xml
Executable file
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<!DOCTYPE sqlMap
|
||||
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
|
||||
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
|
||||
|
||||
<sqlMap namespace="ActivityPost">
|
||||
|
||||
<typeAlias alias="ActivityPost" type="org.alfresco.repo.activities.post.ActivityPostDAO"/>
|
||||
|
||||
<resultMap id="ActivityPostResult" class="ActivityPost">
|
||||
<result property="id" column="SEQUENCE_ID"/>
|
||||
<result property="activityData" column="ACTIVITY_DATA"/>
|
||||
<result property="activityType" column="ACTIVITY_TYPE"/>
|
||||
<result property="userId" column="POST_USER_ID"/>
|
||||
<result property="postDate" column="POST_DATE"/>
|
||||
<result property="jobTaskNode" column="JOB_TASK_NODE"/>
|
||||
<result property="siteNetwork" column="SITE_NETWORK"/>
|
||||
<result property="appTool" column="APP_TOOL"/>
|
||||
<result property="status" column="STATUS"/>
|
||||
<result property="lastModified" column="LAST_MODIFIED"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="select.activity.posts" parameterClass="ActivityPost" resultClass="ActivityPost">
|
||||
<![CDATA[
|
||||
select
|
||||
sequence_id as id,
|
||||
activity_data as activityData,
|
||||
activity_type as activityType,
|
||||
post_user_id as userId,
|
||||
post_date as postDate,
|
||||
job_task_node as jobTaskNode,
|
||||
site_network as siteNetwork,
|
||||
app_tool as appTool,
|
||||
status as status
|
||||
from
|
||||
alf_activity_post
|
||||
where
|
||||
job_task_node = #jobTaskNode# and
|
||||
sequence_id >= #minId# and
|
||||
sequence_id <= #maxId# and
|
||||
status = #status#
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<select id="select.activity.posts.by.status.only" parameterClass="ActivityPost" resultClass="ActivityPost">
|
||||
<![CDATA[
|
||||
select
|
||||
sequence_id as id,
|
||||
activity_data as activityData,
|
||||
activity_type as activityType,
|
||||
post_user_id as userId,
|
||||
post_date as postDate,
|
||||
job_task_node as jobTaskNode,
|
||||
site_network as siteNetwork,
|
||||
app_tool as appTool,
|
||||
status as status
|
||||
from
|
||||
alf_activity_post
|
||||
where
|
||||
status = #status#
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<select id="select.activity.post.max.seq" resultClass="long">
|
||||
select max(sequence_id) as maxId
|
||||
from alf_activity_post
|
||||
where status = 'POSTED'
|
||||
</select>
|
||||
|
||||
<select id="select.activity.post.min.seq" resultClass="long">
|
||||
select min(sequence_id) as minId
|
||||
from alf_activity_post
|
||||
where status = 'POSTED'
|
||||
</select>
|
||||
|
||||
<select id="select.activity.post.max.jobtasknode" resultClass="int">
|
||||
select max(job_task_node) as maxJobTaskNode
|
||||
from alf_activity_post
|
||||
where status = 'POSTED'
|
||||
</select>
|
||||
|
||||
<insert id="insert.activity.post" parameterClass="ActivityPost">
|
||||
insert into alf_activity_post (status, activity_data, post_user_id, post_date, activity_type, site_network, app_tool, job_task_node, last_modified)
|
||||
values (#status#, #activityData#, #userId#, #postDate#, #activityType#, #siteNetwork#, #appTool#, #jobTaskNode#, #lastModified#)
|
||||
|
||||
<!-- optionally return auto-generated primary key - only required for debug (can be commented out) -->
|
||||
<selectKey resultClass="long" keyProperty="id" type="post">
|
||||
CALL IDENTITY()
|
||||
</selectKey>
|
||||
|
||||
</insert>
|
||||
|
||||
<delete id="delete.activity.posts.older.than.date" parameterClass="ActivityPost">
|
||||
<![CDATA[
|
||||
delete from alf_activity_post
|
||||
where post_date < #postDate#
|
||||
and status = #status#
|
||||
]]>
|
||||
</delete>
|
||||
|
||||
<update id="update.activity.post.data" parameterClass="ActivityPost">
|
||||
update alf_activity_post set status = #status#, activity_data=#activityData#, site_network=#siteNetwork#, last_modified=#lastModified#
|
||||
where sequence_id = #id#
|
||||
and status != #status#
|
||||
</update>
|
||||
|
||||
<update id="update.activity.post.status" parameterClass="ActivityPost">
|
||||
update alf_activity_post set status = #status#, last_modified=#lastModified#
|
||||
where sequence_id = #id#
|
||||
and status != #status#
|
||||
</update>
|
||||
|
||||
</sqlMap>
|
@@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<!DOCTYPE sqlMap
|
||||
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
|
||||
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
|
||||
|
||||
<sqlMap namespace="ActivityFeed">
|
||||
|
||||
<typeAlias alias="ActivityFeed" type="org.alfresco.repo.activities.feed.ActivityFeedDAO"/>
|
||||
|
||||
<resultMap id="ActivityFeedResult" class="ActivityFeed">
|
||||
<result property="id" column="ID"/>
|
||||
<result property="feedUserId" column="FEED_USER_ID"/>
|
||||
<result property="postUserId" column="POST_USER_ID"/>
|
||||
<result property="postDate" column="POST_DATE"/>
|
||||
<result property="postId" column="POST_ID"/> <!-- not an explicit FK constraint, can dangle if and when activity post is deleted -->
|
||||
<result property="siteNetwork" column="SITE_NETWORK"/>
|
||||
<result property="activityType" column="ACTIVITY_TYPE"/>
|
||||
<result property="activitySummary" column="ACTIVITY_SUMMARY"/>
|
||||
<result property="activitySummaryFormat" column="ACTIVITY_FORMAT"/>
|
||||
<result property="feedDate" column="FEED_DATE"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="select.activity.feed.for.feeduser" parameterClass="ActivityFeed" resultClass="ActivityFeed">
|
||||
<![CDATA[
|
||||
select id as id, activity_format as activitySummaryFormat, activity_summary as activitySummary, feed_user_id as feedUserId, post_user_id as postUserId, site_network as siteNetwork, post_date postDate
|
||||
from alf_activity_feed
|
||||
where feed_user_id = #feedUserId#
|
||||
and post_user_id != #feedUserId#
|
||||
and activity_format = #activitySummaryFormat#
|
||||
order by post_date desc
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<select id="select.activity.feed.for.feeduser.and.site" parameterClass="ActivityFeed" resultClass="ActivityFeed">
|
||||
<![CDATA[
|
||||
select id as id, activity_format as activitySummaryFormat, activity_summary as activitySummary, feed_user_id as feedUserId, post_user_id as postUserId, site_network as siteNetwork, post_date postDate
|
||||
from alf_activity_feed
|
||||
where feed_user_id = #feedUserId#
|
||||
and post_user_id != #feedUserId#
|
||||
and site_network = #siteNetwork#
|
||||
and activity_format = #activitySummaryFormat#
|
||||
order by post_date desc
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<select id="select.activity.feed.for.site" parameterClass="ActivityFeed" resultClass="ActivityFeed">
|
||||
<![CDATA[
|
||||
select id as id, activity_format as activitySummaryFormat, activity_summary as activitySummary, feed_user_id as feedUserId, post_user_id as postUserId, site_network as siteNetwork, post_date postDate
|
||||
from alf_activity_feed
|
||||
where feed_user_id = ''
|
||||
and site_network = #siteNetwork#
|
||||
and activity_format = #activitySummaryFormat#
|
||||
order by post_date desc
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<insert id="insert.activity.feed" parameterClass="ActivityFeed">
|
||||
insert into alf_activity_feed (activity_type, activity_summary, activity_format, feed_user_id, post_user_id, post_date, post_id, site_network, app_tool, feed_date)
|
||||
values (#activityType#, #activitySummary#, #activitySummaryFormat#, #feedUserId#, #postUserId#, #postDate#, #postId#, #siteNetwork#, #appTool#, #feedDate#)
|
||||
|
||||
<!-- optionally return auto-generated primary key - only required for debug (can be commented out) -->
|
||||
<selectKey resultClass="long" keyProperty="id" type="post">
|
||||
SELECT LAST_INSERT_ID() AS value
|
||||
</selectKey>
|
||||
</insert>
|
||||
|
||||
<delete id="delete.activity.feed.entries.older.than.date" parameterClass="Date">
|
||||
<![CDATA[
|
||||
delete from alf_activity_feed where post_date < #keepdate#
|
||||
]]>
|
||||
</delete>
|
||||
|
||||
</sqlMap>
|
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<!DOCTYPE sqlMap
|
||||
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
|
||||
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
|
||||
|
||||
<sqlMap namespace="ActivityFeedControl">
|
||||
|
||||
<typeAlias alias="FeedControl" type="org.alfresco.repo.activities.feed.control.FeedControlDAO"/>
|
||||
|
||||
<resultMap id="FeedControlResult" class="FeedControl">
|
||||
<result property="id" column="ID"/>
|
||||
<result property="feedUserId" column="FEED_USER_ID"/>
|
||||
<result property="siteNetwork" column="SITE_NETWORK"/>
|
||||
<result property="appTool" column="APP_TOOL"/>
|
||||
<result property="lastModified" column="LAST_MODIFIED"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="select.activity.feedcontrols.for.user" parameterClass="FeedControl" resultClass="FeedControl">
|
||||
<![CDATA[
|
||||
select id as id, feed_user_id as feedUserId, site_network as siteNetwork, app_tool as appTool
|
||||
from alf_activity_feed_control
|
||||
where feed_user_id = #feedUserId#
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<select id="select.activity.feedcontrol" parameterClass="FeedControl" resultClass="long">
|
||||
<![CDATA[
|
||||
select id as id
|
||||
from alf_activity_feed_control
|
||||
where feed_user_id = #feedUserId#
|
||||
and site_network = #siteNetwork#
|
||||
and app_tool = #appTool#
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<insert id="insert.activity.feedcontrol" parameterClass="FeedControl">
|
||||
insert into alf_activity_feed_control (feed_user_id, site_network, app_tool, last_modified)
|
||||
values (#feedUserId#, #siteNetwork#, #appTool#, #lastModified#)
|
||||
|
||||
<!-- optionally return auto-generated primary key - only required for debug (can be commented out) -->
|
||||
<selectKey resultClass="long" keyProperty="id" type="post">
|
||||
SELECT LAST_INSERT_ID() AS value
|
||||
</selectKey>
|
||||
</insert>
|
||||
|
||||
<delete id="delete.activity.feedcontrol" parameterClass="FeedControl">
|
||||
<![CDATA[
|
||||
delete from alf_activity_feed_control
|
||||
where feed_user_id = #feedUserId#
|
||||
and site_network = #siteNetwork#
|
||||
and app_tool = #appTool#
|
||||
]]>
|
||||
</delete>
|
||||
|
||||
</sqlMap>
|
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<!DOCTYPE sqlMap
|
||||
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
|
||||
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
|
||||
|
||||
<sqlMap namespace="ActivityPost">
|
||||
|
||||
<typeAlias alias="ActivityPost" type="org.alfresco.repo.activities.post.ActivityPostDAO"/>
|
||||
|
||||
<resultMap id="ActivityPostResult" class="ActivityPost">
|
||||
<result property="id" column="SEQUENCE_ID"/>
|
||||
<result property="activityData" column="ACTIVITY_DATA"/>
|
||||
<result property="activityType" column="ACTIVITY_TYPE"/>
|
||||
<result property="userId" column="POST_USER_ID"/>
|
||||
<result property="postDate" column="POST_DATE"/>
|
||||
<result property="jobTaskNode" column="JOB_TASK_NODE"/>
|
||||
<result property="siteNetwork" column="SITE_NETWORK"/>
|
||||
<result property="appTool" column="APP_TOOL"/>
|
||||
<result property="status" column="STATUS"/>
|
||||
<result property="lastModified" column="LAST_MODIFIED"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="select.activity.posts" parameterClass="ActivityPost" resultClass="ActivityPost">
|
||||
<![CDATA[
|
||||
select
|
||||
sequence_id as id,
|
||||
activity_data as activityData,
|
||||
activity_type as activityType,
|
||||
post_user_id as userId,
|
||||
post_date as postDate,
|
||||
job_task_node as jobTaskNode,
|
||||
site_network as siteNetwork,
|
||||
app_tool as appTool,
|
||||
status as status
|
||||
from
|
||||
alf_activity_post
|
||||
where
|
||||
job_task_node = #jobTaskNode# and
|
||||
sequence_id >= #minId# and
|
||||
sequence_id <= #maxId# and
|
||||
status = #status#
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<select id="select.activity.posts.by.status.only" parameterClass="ActivityPost" resultClass="ActivityPost">
|
||||
<![CDATA[
|
||||
select
|
||||
sequence_id as id,
|
||||
activity_data as activityData,
|
||||
activity_type as activityType,
|
||||
post_user_id as userId,
|
||||
post_date as postDate,
|
||||
job_task_node as jobTaskNode,
|
||||
site_network as siteNetwork,
|
||||
app_tool as appTool,
|
||||
status as status
|
||||
from
|
||||
alf_activity_post
|
||||
where
|
||||
status = #status#
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<select id="select.activity.post.max.seq" resultClass="long">
|
||||
select max(sequence_id) as maxId
|
||||
from alf_activity_post
|
||||
where status = 'POSTED'
|
||||
</select>
|
||||
|
||||
<select id="select.activity.post.min.seq" resultClass="long">
|
||||
select min(sequence_id) as minId
|
||||
from alf_activity_post
|
||||
where status = 'POSTED'
|
||||
</select>
|
||||
|
||||
<select id="select.activity.post.max.jobtasknode" resultClass="int">
|
||||
select max(job_task_node) as maxJobTaskNode
|
||||
from alf_activity_post
|
||||
where status = 'POSTED'
|
||||
</select>
|
||||
|
||||
<insert id="insert.activity.post" parameterClass="ActivityPost">
|
||||
insert into alf_activity_post (status, activity_data, post_user_id, post_date, activity_type, site_network, app_tool, job_task_node, last_modified)
|
||||
values (#status#, #activityData#, #userId#, #postDate#, #activityType#, #siteNetwork#, #appTool#, #jobTaskNode#, #lastModified#)
|
||||
|
||||
<!-- optionally return auto-generated primary key - only required for debug (can be commented out) -->
|
||||
<selectKey resultClass="long" keyProperty="id" type="post">
|
||||
SELECT LAST_INSERT_ID() AS value
|
||||
</selectKey>
|
||||
|
||||
</insert>
|
||||
|
||||
<delete id="delete.activity.posts.older.than.date" parameterClass="ActivityPost">
|
||||
<![CDATA[
|
||||
delete from alf_activity_post
|
||||
where post_date < #postDate#
|
||||
and status = #status#
|
||||
]]>
|
||||
</delete>
|
||||
|
||||
<update id="update.activity.post.data" parameterClass="ActivityPost">
|
||||
update alf_activity_post set status = #status#, activity_data=#activityData#, site_network=#siteNetwork#, last_modified=#lastModified#
|
||||
where sequence_id = #id#
|
||||
and status != #status#
|
||||
</update>
|
||||
|
||||
<update id="update.activity.post.status" parameterClass="ActivityPost">
|
||||
update alf_activity_post set status = #status#, last_modified=#lastModified#
|
||||
where sequence_id = #id#
|
||||
and status != #status#
|
||||
</update>
|
||||
|
||||
</sqlMap>
|
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<!DOCTYPE sqlMap
|
||||
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
|
||||
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
|
||||
|
||||
<sqlMap namespace="ActivityFeed">
|
||||
|
||||
<typeAlias alias="ActivityFeed" type="org.alfresco.repo.activities.feed.ActivityFeedDAO"/>
|
||||
|
||||
<resultMap id="ActivityFeedResult" class="ActivityFeed">
|
||||
<result property="id" column="ID"/>
|
||||
<result property="feedUserId" column="FEED_USER_ID"/>
|
||||
<result property="postUserId" column="POST_USER_ID"/>
|
||||
<result property="postDate" column="POST_DATE"/>
|
||||
<result property="postId" column="POST_ID"/> <!-- not an explicit FK constraint, can dangle if and when activity post is deleted -->
|
||||
<result property="siteNetwork" column="SITE_NETWORK"/>
|
||||
<result property="activityType" column="ACTIVITY_TYPE"/>
|
||||
<result property="activitySummary" column="ACTIVITY_SUMMARY"/>
|
||||
<result property="activitySummaryFormat" column="ACTIVITY_FORMAT"/>
|
||||
<result property="feedDate" column="FEED_DATE"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="select.activity.feed.for.feeduser" parameterClass="ActivityFeed" resultClass="ActivityFeed">
|
||||
<![CDATA[
|
||||
select id as id, activity_format as activitySummaryFormat, activity_summary as activitySummary, feed_user_id as feedUserId, post_user_id as postUserId, site_network as siteNetwork, post_date postDate
|
||||
from alf_activity_feed
|
||||
where feed_user_id = #feedUserId#
|
||||
and post_user_id != #feedUserId#
|
||||
and activity_format = #activitySummaryFormat#
|
||||
order by post_date desc
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<select id="select.activity.feed.for.feeduser.and.site" parameterClass="ActivityFeed" resultClass="ActivityFeed">
|
||||
<![CDATA[
|
||||
select id as id, activity_format as activitySummaryFormat, activity_summary as activitySummary, feed_user_id as feedUserId, post_user_id as postUserId, site_network as siteNetwork, post_date postDate
|
||||
from alf_activity_feed
|
||||
where feed_user_id = #feedUserId#
|
||||
and post_user_id != #feedUserId#
|
||||
and site_network = #siteNetwork#
|
||||
and activity_format = #activitySummaryFormat#
|
||||
order by post_date desc
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<select id="select.activity.feed.for.site" parameterClass="ActivityFeed" resultClass="ActivityFeed">
|
||||
<![CDATA[
|
||||
select id as id, activity_format as activitySummaryFormat, activity_summary as activitySummary, feed_user_id as feedUserId, post_user_id as postUserId, site_network as siteNetwork, post_date postDate
|
||||
from alf_activity_feed
|
||||
where feed_user_id = ''
|
||||
and site_network = #siteNetwork#
|
||||
and activity_format = #activitySummaryFormat#
|
||||
order by post_date desc
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<insert id="insert.activity.feed" parameterClass="ActivityFeed">
|
||||
|
||||
<selectKey resultClass="long" keyProperty="id" type="pre">
|
||||
select alf_activity_feed_seq.nextval as value from dual
|
||||
</selectKey>
|
||||
|
||||
insert into alf_activity_feed (id, activity_type, activity_summary, activity_format, feed_user_id, post_user_id, post_date, post_id, site_network, app_tool, feed_date)
|
||||
values (#id#, #activityType#, #activitySummary#, #activitySummaryFormat#, #feedUserId#, #postUserId#, #postDate#, #postId#, #siteNetwork#, #appTool#, #feedDate#)
|
||||
|
||||
</insert>
|
||||
|
||||
<delete id="delete.activity.feed.entries.older.than.date" parameterClass="Date">
|
||||
<![CDATA[
|
||||
delete from alf_activity_feed where post_date < #keepdate#
|
||||
]]>
|
||||
</delete>
|
||||
|
||||
</sqlMap>
|
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<!DOCTYPE sqlMap
|
||||
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
|
||||
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
|
||||
|
||||
<sqlMap namespace="ActivityFeedControl">
|
||||
|
||||
<typeAlias alias="FeedControl" type="org.alfresco.repo.activities.feed.control.FeedControlDAO"/>
|
||||
|
||||
<resultMap id="FeedControlResult" class="FeedControl">
|
||||
<result property="id" column="ID"/>
|
||||
<result property="feedUserId" column="FEED_USER_ID"/>
|
||||
<result property="siteNetwork" column="SITE_NETWORK"/>
|
||||
<result property="appTool" column="APP_TOOL"/>
|
||||
<result property="lastModified" column="LAST_MODIFIED"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="select.activity.feedcontrols.for.user" parameterClass="FeedControl" resultClass="FeedControl">
|
||||
<![CDATA[
|
||||
select id as id, feed_user_id as feedUserId, site_network as siteNetwork, app_tool as appTool
|
||||
from alf_activity_feed_control
|
||||
where feed_user_id = #feedUserId#
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<select id="select.activity.feedcontrol" parameterClass="FeedControl" resultClass="long">
|
||||
<![CDATA[
|
||||
select id as id
|
||||
from alf_activity_feed_control
|
||||
where feed_user_id = #feedUserId#
|
||||
and site_network = #siteNetwork#
|
||||
and app_tool = #appTool#
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<insert id="insert.activity.feedcontrol" parameterClass="FeedControl">
|
||||
|
||||
<selectKey resultClass="long" keyProperty="id" type="pre">
|
||||
select alf_activity_feed_control_seq.nextval as value from dual
|
||||
</selectKey>
|
||||
|
||||
insert into alf_activity_feed_control (id, feed_user_id, site_network, app_tool, last_modified)
|
||||
values (#id#, #feedUserId#, #siteNetwork#, #appTool#, #lastModified#)
|
||||
|
||||
</insert>
|
||||
|
||||
<delete id="delete.activity.feedcontrol" parameterClass="FeedControl">
|
||||
<![CDATA[
|
||||
delete from alf_activity_feed_control
|
||||
where feed_user_id = #feedUserId#
|
||||
and site_network = #siteNetwork#
|
||||
and app_tool = #appTool#
|
||||
]]>
|
||||
</delete>
|
||||
|
||||
</sqlMap>
|
114
config/alfresco/activities/org.hibernate.dialect.Oracle9Dialect/ActivityPost.xml
Executable file
114
config/alfresco/activities/org.hibernate.dialect.Oracle9Dialect/ActivityPost.xml
Executable file
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<!DOCTYPE sqlMap
|
||||
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
|
||||
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
|
||||
|
||||
<sqlMap namespace="ActivityPost">
|
||||
|
||||
<typeAlias alias="ActivityPost" type="org.alfresco.repo.activities.post.ActivityPostDAO"/>
|
||||
|
||||
<resultMap id="ActivityPostResult" class="ActivityPost">
|
||||
<result property="id" column="SEQUENCE_ID"/>
|
||||
<result property="activityData" column="ACTIVITY_DATA"/>
|
||||
<result property="activityType" column="ACTIVITY_TYPE"/>
|
||||
<result property="userId" column="POST_USER_ID"/>
|
||||
<result property="postDate" column="POST_DATE"/>
|
||||
<result property="jobTaskNode" column="JOB_TASK_NODE"/>
|
||||
<result property="siteNetwork" column="SITE_NETWORK"/>
|
||||
<result property="appTool" column="APP_TOOL"/>
|
||||
<result property="status" column="STATUS"/>
|
||||
<result property="lastModified" column="LAST_MODIFIED"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="select.activity.posts" parameterClass="ActivityPost" resultClass="ActivityPost">
|
||||
<![CDATA[
|
||||
select
|
||||
sequence_id as id,
|
||||
activity_data as activityData,
|
||||
activity_type as activityType,
|
||||
post_user_id as userId,
|
||||
post_date as postDate,
|
||||
job_task_node as jobTaskNode,
|
||||
site_network as siteNetwork,
|
||||
app_tool as appTool,
|
||||
status as status
|
||||
from
|
||||
alf_activity_post
|
||||
where
|
||||
job_task_node = #jobTaskNode# and
|
||||
sequence_id >= #minId# and
|
||||
sequence_id <= #maxId# and
|
||||
status = #status#
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<select id="select.activity.posts.by.status.only" parameterClass="ActivityPost" resultClass="ActivityPost">
|
||||
<![CDATA[
|
||||
select
|
||||
sequence_id as id,
|
||||
activity_data as activityData,
|
||||
activity_type as activityType,
|
||||
post_user_id as userId,
|
||||
post_date as postDate,
|
||||
job_task_node as jobTaskNode,
|
||||
site_network as siteNetwork,
|
||||
app_tool as appTool,
|
||||
status as status
|
||||
from
|
||||
alf_activity_post
|
||||
where
|
||||
status = #status#
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<select id="select.activity.post.max.seq" resultClass="long">
|
||||
select max(sequence_id) as maxId
|
||||
from alf_activity_post
|
||||
where status = 'POSTED'
|
||||
</select>
|
||||
|
||||
<select id="select.activity.post.min.seq" resultClass="long">
|
||||
select min(sequence_id) as minId
|
||||
from alf_activity_post
|
||||
where status = 'POSTED'
|
||||
</select>
|
||||
|
||||
<select id="select.activity.post.max.jobtasknode" resultClass="int">
|
||||
select max(job_task_node) as maxJobTaskNode
|
||||
from alf_activity_post
|
||||
where status = 'POSTED'
|
||||
</select>
|
||||
|
||||
<insert id="insert.activity.post" parameterClass="ActivityPost">
|
||||
|
||||
<selectKey resultClass="long" keyProperty="id" type="pre">
|
||||
select alf_activity_post_seq.nextval as value from dual
|
||||
</selectKey>
|
||||
|
||||
insert into alf_activity_post (sequence_id, status, activity_data, post_user_id, post_date, activity_type, site_network, app_tool, job_task_node, last_modified)
|
||||
values (#id#, #status#, #activityData#, #userId#, #postDate#, #activityType#, #siteNetwork#, #appTool#, #jobTaskNode#, #lastModified#)
|
||||
|
||||
</insert>
|
||||
|
||||
<delete id="delete.activity.posts.older.than.date" parameterClass="ActivityPost">
|
||||
<![CDATA[
|
||||
delete from alf_activity_post
|
||||
where post_date < #postDate#
|
||||
and status = #status#
|
||||
]]>
|
||||
</delete>
|
||||
|
||||
<update id="update.activity.post.data" parameterClass="ActivityPost">
|
||||
update alf_activity_post set status = #status#, activity_data=#activityData#, site_network=#siteNetwork#, last_modified=#lastModified#
|
||||
where sequence_id = #id#
|
||||
and status != #status#
|
||||
</update>
|
||||
|
||||
<update id="update.activity.post.status" parameterClass="ActivityPost">
|
||||
update alf_activity_post set status = #status#, last_modified=#lastModified#
|
||||
where sequence_id = #id#
|
||||
and status != #status#
|
||||
</update>
|
||||
|
||||
</sqlMap>
|
@@ -13,6 +13,7 @@
|
||||
<import resource="classpath:alfresco/action-services-context.xml" />
|
||||
<import resource="classpath:alfresco/rule-services-context.xml" />
|
||||
<import resource="classpath:alfresco/node-services-context.xml" />
|
||||
<import resource="classpath:alfresco/activities/activities-feed-context.xml" />
|
||||
<import resource="classpath:alfresco/scheduled-jobs-context.xml" />
|
||||
<import resource="classpath:alfresco/network-protocol-context.xml" />
|
||||
<import resource="classpath:alfresco/emailserver/email-service-context.xml" />
|
||||
|
@@ -43,6 +43,7 @@
|
||||
<list>
|
||||
<value>classpath:alfresco/dbscripts/create/2.2/${db.script.dialect}/AlfrescoPostCreate-2.2-MappedFKIndexes.sql</value>
|
||||
<value>classpath:alfresco/dbscripts/create/2.2/${db.script.dialect}/AlfrescoPostCreate-2.2-Extra.sql</value>
|
||||
<value>classpath:alfresco/dbscripts/create/3.0/${db.script.dialect}/create-activities-tables.sql</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="validateUpdateScriptPatches">
|
||||
@@ -59,6 +60,7 @@
|
||||
<ref bean="patch.db-V2.2-1-DropIndexesAndConstraints" />
|
||||
<ref bean="patch.db-V2.2-2-MoveQNames" />
|
||||
<ref bean="patch.db-V2.2-3-PropTypes" />
|
||||
<ref bean="patch.db-V3.0-0-CreateActivitiesTables" />
|
||||
</list>
|
||||
</property>
|
||||
<property name="postUpdateScriptPatches">
|
||||
|
@@ -0,0 +1,59 @@
|
||||
--
|
||||
-- Title: Activities Schema
|
||||
-- Database: HSQL
|
||||
-- Since: V3.0.0 Schema
|
||||
--
|
||||
-- Note: The Activities schema is NOT managed by Hibernate
|
||||
--
|
||||
|
||||
|
||||
CREATE TABLE alf_activity_post (
|
||||
sequence_id bigint generated by default as identity (start with 1),
|
||||
post_date timestamp NOT NULL,
|
||||
status varchar(10) NOT NULL,
|
||||
activity_data varchar(4000) NOT NULL,
|
||||
post_user_id varchar(255) NOT NULL,
|
||||
job_task_node integer NOT NULL,
|
||||
site_network varchar(255) default NULL,
|
||||
app_tool varchar(36) default NULL,
|
||||
activity_type varchar(255) NOT NULL,
|
||||
last_modified timestamp NOT NULL,
|
||||
primary key (sequence_id)
|
||||
);
|
||||
|
||||
CREATE INDEX jobtasknode_idx on alf_activity_post(job_task_node);
|
||||
CREATE INDEX status_idx on alf_activity_post(status);
|
||||
|
||||
|
||||
CREATE TABLE alf_activity_feed (
|
||||
id bigint generated by default as identity (start with 1),
|
||||
post_id bigint default NULL,
|
||||
post_date timestamp NOT NULL,
|
||||
activity_summary varchar(4000) default NULL,
|
||||
feed_user_id varchar(255) NOT NULL,
|
||||
activity_type varchar(255) NOT NULL,
|
||||
activity_format varchar(10) default NULL,
|
||||
site_network varchar(255) default NULL,
|
||||
app_tool varchar(36) default NULL,
|
||||
post_user_id varchar(255) NOT NULL,
|
||||
feed_date timestamp NOT NULL,
|
||||
primary key (id)
|
||||
);
|
||||
|
||||
CREATE INDEX postdate_idx ON alf_activity_feed(post_date);
|
||||
CREATE INDEX feeduserid_idx ON alf_activity_feed(feed_user_id);
|
||||
CREATE INDEX postuserid_idx ON alf_activity_feed(post_user_id);
|
||||
CREATE INDEX sitenetwork_idx ON alf_activity_feed(site_network);
|
||||
CREATE INDEX activityformat_idx ON alf_activity_feed(activity_format);
|
||||
|
||||
|
||||
CREATE TABLE alf_activity_feed_control (
|
||||
id bigint generated by default as identity (start with 1),
|
||||
feed_user_id varchar(255) NOT NULL,
|
||||
site_network varchar(255) NOT NULL,
|
||||
app_tool varchar(36) default NULL,
|
||||
last_modified timestamp NOT NULL,
|
||||
primary key (id)
|
||||
);
|
||||
|
||||
CREATE INDEX feedcontroluserid_idx ON alf_activity_feed_control(feed_user_id);
|
@@ -0,0 +1,56 @@
|
||||
--
|
||||
-- Title: Activities Schema
|
||||
-- Database: MySQL
|
||||
-- Since: V3.0.0 Schema
|
||||
--
|
||||
-- Note: The Activities schema is NOT managed by Hibernate
|
||||
--
|
||||
|
||||
|
||||
CREATE TABLE alf_activity_post (
|
||||
sequence_id bigint NOT NULL auto_increment,
|
||||
post_date timestamp NOT NULL,
|
||||
status varchar(10) NOT NULL,
|
||||
activity_data varchar(4000) NOT NULL,
|
||||
post_user_id varchar(255) NOT NULL,
|
||||
job_task_node int(11) NOT NULL,
|
||||
site_network varchar(255) default NULL,
|
||||
app_tool varchar(36) default NULL,
|
||||
activity_type varchar(255) NOT NULL,
|
||||
last_modified timestamp NOT NULL,
|
||||
PRIMARY KEY (sequence_id),
|
||||
KEY jobtasknode_idx (job_task_node),
|
||||
KEY status_idx (status)
|
||||
) type=InnoDB;
|
||||
|
||||
|
||||
CREATE TABLE alf_activity_feed (
|
||||
id bigint NOT NULL auto_increment,
|
||||
post_id bigint default NULL,
|
||||
post_date timestamp NOT NULL,
|
||||
activity_summary varchar(4000) default NULL,
|
||||
feed_user_id varchar(255) NOT NULL,
|
||||
activity_type varchar(255) NOT NULL,
|
||||
activity_format varchar(10) default NULL,
|
||||
site_network varchar(255) default NULL,
|
||||
app_tool varchar(36) default NULL,
|
||||
post_user_id varchar(255) NOT NULL,
|
||||
feed_date timestamp NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
KEY postdate_idx (post_date),
|
||||
KEY feeduserid_idx (feed_user_id),
|
||||
KEY postuserid_idx (post_user_id),
|
||||
KEY sitenetwork_idx (site_network),
|
||||
KEY activityformat_idx (activity_format)
|
||||
) type=InnoDB;
|
||||
|
||||
|
||||
CREATE TABLE alf_activity_feed_control (
|
||||
id bigint NOT NULL auto_increment,
|
||||
feed_user_id varchar(255) NOT NULL,
|
||||
site_network varchar(255) NOT NULL,
|
||||
app_tool varchar(36) NOT NULL,
|
||||
last_modified timestamp NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
KEY feedcontroluserid_idx (feed_user_id)
|
||||
) type=InnoDB;
|
@@ -0,0 +1,65 @@
|
||||
--
|
||||
-- Title: Activities Schema
|
||||
-- Database: Oracle
|
||||
-- Since: V3.0.0 Schema
|
||||
--
|
||||
-- Note: The Activities schema is NOT managed by Hibernate
|
||||
--
|
||||
|
||||
|
||||
CREATE TABLE alf_activity_post (
|
||||
sequence_id number(19,0) NOT NULL,
|
||||
post_date timestamp NOT NULL,
|
||||
status varchar2(10) NOT NULL,
|
||||
activity_data varchar2(4000) NOT NULL,
|
||||
post_user_id varchar2(255) NOT NULL,
|
||||
job_task_node number(19,0) NOT NULL,
|
||||
site_network varchar2(255) default NULL,
|
||||
app_tool varchar2(36) default NULL,
|
||||
activity_type varchar2(255) NOT NULL,
|
||||
last_modified timestamp NOT NULL,
|
||||
primary key (sequence_id)
|
||||
);
|
||||
|
||||
CREATE SEQUENCE alf_activity_post_seq START WITH 1 INCREMENT BY 1;
|
||||
|
||||
CREATE INDEX jobtasknode_idx on alf_activity_post(job_task_node);
|
||||
CREATE INDEX status_idx on alf_activity_post(status);
|
||||
|
||||
|
||||
CREATE TABLE alf_activity_feed (
|
||||
id number(19,0) NOT NULL,
|
||||
post_id number(19,0) default NULL,
|
||||
post_date timestamp NOT NULL,
|
||||
activity_summary varchar2(4000) default NULL,
|
||||
feed_user_id varchar2(255) default NULL,
|
||||
activity_type varchar2(255) NOT NULL,
|
||||
activity_format varchar2(10) default NULL,
|
||||
site_network varchar2(255) default NULL,
|
||||
app_tool varchar2(36) default NULL,
|
||||
post_user_id varchar2(255) NOT NULL,
|
||||
feed_date timestamp NOT NULL,
|
||||
primary key (id)
|
||||
);
|
||||
|
||||
CREATE SEQUENCE alf_activity_feed_seq START WITH 1 INCREMENT BY 1;
|
||||
|
||||
CREATE INDEX postdate_idx ON alf_activity_feed(post_date);
|
||||
CREATE INDEX feeduserid_idx ON alf_activity_feed(feed_user_id);
|
||||
CREATE INDEX postuserid_idx ON alf_activity_feed(post_user_id);
|
||||
CREATE INDEX sitenetwork_idx ON alf_activity_feed(site_network);
|
||||
CREATE INDEX activityformat_idx ON alf_activity_feed(activity_format);
|
||||
|
||||
|
||||
CREATE TABLE alf_activity_feed_control (
|
||||
id number(19,0) NOT NULL,
|
||||
feed_user_id varchar2(255) NOT NULL,
|
||||
site_network varchar2(255) NOT NULL,
|
||||
app_tool varchar2(36) NOT NULL,
|
||||
last_modified timestamp NOT NULL,
|
||||
primary key (id)
|
||||
);
|
||||
|
||||
CREATE SEQUENCE alf_activity_feed_control_seq START WITH 1 INCREMENT BY 1;
|
||||
|
||||
CREATE INDEX feedcontroluserid_idx ON alf_activity_feed_control(feed_user_id);
|
@@ -1468,4 +1468,15 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="patch.db-V3.0-0-CreateActivitiesTables" class="org.alfresco.repo.admin.patch.impl.SchemaUpgradeScriptPatch" parent="basePatch">
|
||||
<property name="id"><value>patch.db-V3.0-0-CreateActivitiesTables</value></property>
|
||||
<property name="description"><value>patch.schemaUpgradeScript.description</value></property>
|
||||
<property name="fixesFromSchema"><value>0</value></property>
|
||||
<property name="fixesToSchema"><value>125</value></property>
|
||||
<property name="targetSchema"><value>126</value></property>
|
||||
<property name="scriptUrl">
|
||||
<value>classpath:alfresco/dbscripts/create/3.0/${db.script.dialect}/create-activities-tables.sql</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
@@ -205,3 +205,6 @@ avm.remote.idlestream.timeout=30000
|
||||
|
||||
# ECM content usages/quotas
|
||||
system.usages.enabled=true
|
||||
|
||||
# Repository endpoint - used by Activity Service
|
||||
repo.remote.endpoint.url=http://localhost:8080/alfresco/service
|
@@ -354,4 +354,120 @@
|
||||
<!-- See the wiki (http://wiki.alfresco.com/wikiDeployment) for details -->
|
||||
<!-- and the deployment-attempt-cleaner-context.xml.sample file. -->
|
||||
|
||||
|
||||
<!-- Activities Feed Cleaner -->
|
||||
|
||||
<bean id="feedCleanerJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
|
||||
<property name="jobClass">
|
||||
<value>org.alfresco.repo.activities.feed.cleanup.FeedCleanupJob</value>
|
||||
</property>
|
||||
<property name="jobDataAsMap">
|
||||
<map>
|
||||
<entry key="feedCleaner">
|
||||
<ref bean="feedCleaner" />
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
<bean id="feedCleanerTrigger" class="org.alfresco.util.TriggerBean">
|
||||
<property name="jobDetail">
|
||||
<ref bean="feedCleanerJobDetail" />
|
||||
</property>
|
||||
<property name="scheduler">
|
||||
<ref bean="schedulerFactory" />
|
||||
</property>
|
||||
<property name="startDelayMinutes">
|
||||
<value>5</value>
|
||||
</property>
|
||||
<property name="repeatIntervalMinutes">
|
||||
<value>10</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="feedGeneratorJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
|
||||
<property name="jobClass">
|
||||
<value>org.alfresco.repo.activities.feed.FeedGeneratorJob</value>
|
||||
</property>
|
||||
<property name="jobDataAsMap">
|
||||
<map>
|
||||
<entry key="feedGenerator">
|
||||
<ref bean="feedGenerator" />
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="feedGeneratorTrigger" class="org.alfresco.util.TriggerBean">
|
||||
<property name="jobDetail">
|
||||
<ref bean="feedGeneratorJobDetail" />
|
||||
</property>
|
||||
<property name="scheduler">
|
||||
<ref bean="schedulerFactory" />
|
||||
</property>
|
||||
<property name="startDelayMinutes">
|
||||
<value>0</value>
|
||||
</property>
|
||||
<property name="repeatInterval">
|
||||
<value>30000</value> <!-- 30000 msecs = 30 seconds -->
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Activities Post Lookup (for secondary lookup) -->
|
||||
|
||||
<bean id="postLookupJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
|
||||
<property name="jobClass">
|
||||
<value>org.alfresco.repo.activities.post.lookup.PostLookupJob</value>
|
||||
</property>
|
||||
<property name="jobDataAsMap">
|
||||
<map>
|
||||
<entry key="postLookup">
|
||||
<ref bean="postLookup" />
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
<bean id="postLookupTrigger" class="org.alfresco.util.TriggerBean">
|
||||
<property name="jobDetail">
|
||||
<ref bean="postLookupJobDetail" />
|
||||
</property>
|
||||
<property name="scheduler">
|
||||
<ref bean="schedulerFactory" />
|
||||
</property>
|
||||
<property name="startDelayMinutes">
|
||||
<value>1</value>
|
||||
</property>
|
||||
<property name="repeatInterval">
|
||||
<value>15000</value> <!-- 15000 msecs = 15 seconds -->
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Activities Post Cleaner -->
|
||||
|
||||
<bean id="postCleanerJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
|
||||
<property name="jobClass">
|
||||
<value>org.alfresco.repo.activities.post.cleanup.PostCleanupJob</value>
|
||||
</property>
|
||||
<property name="jobDataAsMap">
|
||||
<map>
|
||||
<entry key="postCleaner">
|
||||
<ref bean="postCleaner" />
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
<bean id="postCleanerTrigger" class="org.alfresco.util.TriggerBean">
|
||||
<property name="jobDetail">
|
||||
<ref bean="postCleanerJobDetail" />
|
||||
</property>
|
||||
<property name="scheduler">
|
||||
<ref bean="schedulerFactory" />
|
||||
</property>
|
||||
<property name="startDelayMinutes">
|
||||
<value>10</value>
|
||||
</property>
|
||||
<property name="repeatIntervalMinutes">
|
||||
<value>10</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
@@ -167,4 +167,13 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="activitiesScript" parent="baseJavaScriptExtension" class="org.alfresco.repo.activities.script.Activity">
|
||||
<property name="extensionName">
|
||||
<value>activities</value>
|
||||
</property>
|
||||
<property name="activityService">
|
||||
<ref bean="activityService"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
@@ -19,4 +19,4 @@ version.build=@build-number@
|
||||
|
||||
# Schema number
|
||||
|
||||
version.schema=125
|
||||
version.schema=126
|
||||
|
@@ -0,0 +1,511 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.activities;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.activities.feed.ActivityFeedDAO;
|
||||
import org.alfresco.repo.activities.feed.ActivityFeedDaoService;
|
||||
import org.alfresco.repo.activities.feed.FeedGenerator;
|
||||
import org.alfresco.repo.activities.feed.control.FeedControlDAO;
|
||||
import org.alfresco.repo.activities.feed.control.FeedControlDaoService;
|
||||
import org.alfresco.repo.activities.post.ActivityPostDAO;
|
||||
import org.alfresco.repo.activities.post.ActivityPostDaoService;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
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.namespace.QName;
|
||||
import org.alfresco.util.JSONtoFmModel;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.json.JSONException;
|
||||
|
||||
/**
|
||||
* Activity Service Implementation
|
||||
*
|
||||
* @author janv
|
||||
*/
|
||||
public class ActivityServiceImpl implements ActivityService
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(ActivityServiceImpl.class);
|
||||
|
||||
private static final int MAX_LEN_USER_ID = 255; // needs to match schema: feed_user_id, post_user_id
|
||||
private static final int MAX_LEN_SITE_ID = 255; // needs to match schema: site_network
|
||||
private static final int MAX_LEN_ACTIVITY_TYPE = 255; // needs to match schema: activity_type
|
||||
private static final int MAX_LEN_ACTIVITY_DATA = 4000; // needs to match schema: activity_data
|
||||
private static final int MAX_LEN_APP_TOOL_ID = 36; // needs to match schema: app_tool
|
||||
|
||||
private ActivityPostDaoService postDaoService;
|
||||
private ActivityFeedDaoService feedDaoService;
|
||||
private FeedControlDaoService feedControlDaoService;
|
||||
private AuthorityService authorityService;
|
||||
private FeedGenerator feedGenerator;
|
||||
|
||||
private int maxFeedItems = 100;
|
||||
|
||||
private boolean userNamesAreCaseSensitive = false;
|
||||
|
||||
public void setMaxFeedItems(int maxFeedItems)
|
||||
{
|
||||
this.maxFeedItems = maxFeedItems;
|
||||
}
|
||||
|
||||
public void setUserNamesAreCaseSensitive(boolean userNamesAreCaseSensitive)
|
||||
{
|
||||
this.userNamesAreCaseSensitive = userNamesAreCaseSensitive;
|
||||
}
|
||||
|
||||
public void setPostDaoService(ActivityPostDaoService postDaoService)
|
||||
{
|
||||
this.postDaoService = postDaoService;
|
||||
}
|
||||
|
||||
public void setFeedDaoService(ActivityFeedDaoService feedDaoService)
|
||||
{
|
||||
this.feedDaoService = feedDaoService;
|
||||
}
|
||||
|
||||
public void setFeedControlDaoService(FeedControlDaoService feedControlDaoService)
|
||||
{
|
||||
this.feedControlDaoService = feedControlDaoService;
|
||||
}
|
||||
|
||||
public void setAuthorityService(AuthorityService authorityService)
|
||||
{
|
||||
this.authorityService = authorityService;
|
||||
}
|
||||
|
||||
public void setFeedGenerator(FeedGenerator feedGenerator)
|
||||
{
|
||||
this.feedGenerator = feedGenerator;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void postActivity(String activityType, String network, String appTool, String activityData)
|
||||
{
|
||||
postActivity(activityType, network, appTool, activityData, ActivityPostDAO.STATUS.POSTED);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
public void postActivity(String activityType, String network, String appTool, NodeRef nodeRef)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("{").append("\"nodeRef\":\"").append(nodeRef.toString()).append("\"").append("}");
|
||||
|
||||
postActivity(activityType, network, appTool, sb.toString(), ActivityPostDAO.STATUS.PENDING);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
|
||||
*/
|
||||
public void postActivity(String activityType, String network, String appTool, NodeRef nodeRef, String name)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("{").append("\"nodeRef\":\"").append(nodeRef.toString()).append("\"").append(",")
|
||||
.append("\"name\":\"").append(name).append("\"")
|
||||
.append("}");
|
||||
|
||||
postActivity(activityType, network, appTool, sb.toString(), ActivityPostDAO.STATUS.PENDING);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.NodeRef, java.lang.String, org.alfresco.service.namespace.QName, org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
public void postActivity(String activityType, String network, String appTool, NodeRef nodeRef, String name, QName typeQName, NodeRef parentNodeRef)
|
||||
{
|
||||
// primarily for delete node activities - eg. delete document, delete folder
|
||||
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
ParameterCheck.mandatory("typeQName", typeQName);
|
||||
ParameterCheck.mandatory("parentNodeRef", parentNodeRef);
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("{").append("\"nodeRef\":\"").append(nodeRef.toString()).append("\"").append(",")
|
||||
.append("\"name\":\"").append(name).append("\"").append(",")
|
||||
.append("\"typeQName\":\"").append(typeQName.toPrefixString()).append("\"").append(",") // TODO toPrefixString does not return prefix ??!!
|
||||
.append("\"parentNodeRef\":\"").append(parentNodeRef.toString()).append("\"")
|
||||
.append("}");
|
||||
|
||||
postActivity(activityType, network, appTool, sb.toString(), ActivityPostDAO.STATUS.PENDING);
|
||||
}
|
||||
|
||||
private void postActivity(String activityType, String siteNetwork, String appTool, String activityData, ActivityPostDAO.STATUS status)
|
||||
{
|
||||
String currentUser = AuthenticationUtil.getCurrentUserName();
|
||||
|
||||
try
|
||||
{
|
||||
// optional - default to empty string
|
||||
if (siteNetwork == null)
|
||||
{
|
||||
siteNetwork = "";
|
||||
}
|
||||
else if (siteNetwork.length() > MAX_LEN_SITE_ID)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Invalid site network - exceeds " + MAX_LEN_SITE_ID + " chars: " + siteNetwork);
|
||||
}
|
||||
|
||||
// optional - default to empty string
|
||||
if (appTool == null)
|
||||
{
|
||||
appTool = "";
|
||||
}
|
||||
else if (appTool.length() > MAX_LEN_APP_TOOL_ID)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Invalid app tool - exceeds " + MAX_LEN_APP_TOOL_ID + " chars: " + appTool);
|
||||
}
|
||||
|
||||
// required
|
||||
ParameterCheck.mandatoryString("activityType", activityType);
|
||||
|
||||
if (activityType.length() > MAX_LEN_ACTIVITY_TYPE)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Invalid activity type - exceeds " + MAX_LEN_ACTIVITY_TYPE + " chars: " + activityType);
|
||||
}
|
||||
|
||||
// optional - default to empty string
|
||||
if (activityData == null)
|
||||
{
|
||||
activityData = "";
|
||||
}
|
||||
else if (activityType.length() > MAX_LEN_ACTIVITY_DATA)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Invalid activity data - exceeds " + MAX_LEN_ACTIVITY_DATA + " chars: " + activityData);
|
||||
}
|
||||
|
||||
// required
|
||||
ParameterCheck.mandatoryString("currentUser", currentUser);
|
||||
|
||||
if (currentUser.length() > MAX_LEN_USER_ID)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Invalid user - exceeds " + MAX_LEN_USER_ID + " chars: " + currentUser);
|
||||
}
|
||||
else if ((! currentUser.equals(AuthenticationUtil.SYSTEM_USER_NAME)) && (! userNamesAreCaseSensitive))
|
||||
{
|
||||
// user names are case-insensitive
|
||||
currentUser = currentUser.toLowerCase();
|
||||
}
|
||||
}
|
||||
catch (AlfrescoRuntimeException e)
|
||||
{
|
||||
// log error and throw exception
|
||||
logger.error(e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Date postDate = new Date();
|
||||
ActivityPostDAO activityPost = new ActivityPostDAO();
|
||||
activityPost.setUserId(currentUser);
|
||||
activityPost.setSiteNetwork(siteNetwork);
|
||||
activityPost.setAppTool(appTool);
|
||||
activityPost.setActivityData(activityData);
|
||||
activityPost.setActivityType(activityType);
|
||||
activityPost.setPostDate(postDate);
|
||||
activityPost.setStatus(status.toString());
|
||||
activityPost.setLastModified(postDate);
|
||||
|
||||
// hash the userid to generate a job task node
|
||||
int nodeCount = feedGenerator.getEstimatedGridSize();
|
||||
int userHashCode = currentUser.hashCode();
|
||||
int nodeHash = (userHashCode % nodeCount) + 1;
|
||||
|
||||
activityPost.setJobTaskNode(nodeHash);
|
||||
|
||||
try
|
||||
{
|
||||
long postId = postDaoService.insertPost(activityPost);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
activityPost.setId(postId);
|
||||
logger.debug("Posted: " + activityPost);
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to post activity: " + e, e);
|
||||
}
|
||||
}
|
||||
catch (AlfrescoRuntimeException e)
|
||||
{
|
||||
// log error, subsume exception
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.activities.ActivityService#getUserFeedEntries(java.lang.String, java.lang.String, java.lang.String)
|
||||
*/
|
||||
public List<Map<String, Object>> getUserFeedEntries(String feedUserId, String format, String siteId)
|
||||
{
|
||||
// NOTE: siteId is optional
|
||||
ParameterCheck.mandatoryString("feedUserId", feedUserId);
|
||||
ParameterCheck.mandatoryString("format", format);
|
||||
|
||||
List<Map<String, Object>> activityFeedModels = new ArrayList<Map<String, Object>>();
|
||||
|
||||
if (! userNamesAreCaseSensitive)
|
||||
{
|
||||
feedUserId = feedUserId.toLowerCase();
|
||||
}
|
||||
|
||||
String currentUser = AuthenticationUtil.getCurrentUserName();
|
||||
if (currentUser != null)
|
||||
{
|
||||
if ((! authorityService.isAdminAuthority(currentUser)) && (! currentUser.equals(feedUserId)))
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unable to get feed entries for '" + feedUserId + "' - currently logged in as '" + currentUser +"'");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
List<ActivityFeedDAO> activityFeeds = null;
|
||||
if (siteId != null)
|
||||
{
|
||||
activityFeeds = feedDaoService.selectUserFeedEntries(feedUserId, format, siteId);
|
||||
}
|
||||
else
|
||||
{
|
||||
activityFeeds = feedDaoService.selectUserFeedEntries(feedUserId, format);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (ActivityFeedDAO activityFeed : activityFeeds)
|
||||
{
|
||||
count++;
|
||||
if (count > maxFeedItems)
|
||||
{
|
||||
break;
|
||||
}
|
||||
activityFeedModels.add(JSONtoFmModel.convertJSONObjectToMap(activityFeed.getJSONString()));
|
||||
}
|
||||
}
|
||||
catch (SQLException se)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unable to get user feed entries: " + se.getMessage());
|
||||
}
|
||||
catch (JSONException je)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unable to get user feed entries: " + je.getMessage());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unable to get user feed entries - current user is null");
|
||||
}
|
||||
|
||||
return activityFeedModels;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.activities.ActivityService#getSiteFeedEntries(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public List<Map<String, Object>> getSiteFeedEntries(String siteId, String format)
|
||||
{
|
||||
ParameterCheck.mandatoryString("siteId", siteId);
|
||||
ParameterCheck.mandatoryString("format", format);
|
||||
|
||||
List<Map<String, Object>> activityFeedModels = new ArrayList<Map<String, Object>>();
|
||||
|
||||
String currentUser = AuthenticationUtil.getCurrentUserName();
|
||||
if (currentUser != null)
|
||||
{
|
||||
// TODO - check whether site is public or private, if private, check whether user is member or admin - authorityService.isAdminAuthority(currentUser))
|
||||
try
|
||||
{
|
||||
List<ActivityFeedDAO> activityFeeds = feedDaoService.selectSiteFeedEntries(siteId, format);
|
||||
|
||||
int count = 0;
|
||||
for (ActivityFeedDAO activityFeed : activityFeeds)
|
||||
{
|
||||
count++;
|
||||
if (count > maxFeedItems)
|
||||
{
|
||||
break;
|
||||
}
|
||||
activityFeedModels.add(JSONtoFmModel.convertJSONObjectToMap(activityFeed.getJSONString()));
|
||||
}
|
||||
}
|
||||
catch (SQLException se)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unable to get site feed entries: " + se.getMessage());
|
||||
}
|
||||
catch (JSONException je)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unable to get site feed entries: " + je.getMessage());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unable to get site feed entries - current user is null");
|
||||
}
|
||||
|
||||
return activityFeedModels;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.activities.ActivityService#setFeedControl(org.alfresco.service.cmr.activities.FeedControl)
|
||||
*/
|
||||
public void setFeedControl(FeedControl feedControl)
|
||||
{
|
||||
ParameterCheck.mandatory("feedControl", feedControl);
|
||||
|
||||
String userId = AuthenticationUtil.getCurrentUserName();
|
||||
if (! userNamesAreCaseSensitive)
|
||||
{
|
||||
userId = userId.toLowerCase();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (! existsFeedControl(feedControl))
|
||||
{
|
||||
feedControlDaoService.insertFeedControl(new FeedControlDAO(userId, feedControl));
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to set feed control: " + e, e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.activities.ActivityService#getFeedControls()
|
||||
*/
|
||||
public List<FeedControl> getFeedControls()
|
||||
{
|
||||
String userId = AuthenticationUtil.getCurrentUserName();
|
||||
return getFeedControlsImpl(userId);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.activities.ActivityService#getFeedControls(java.lang.String)
|
||||
*/
|
||||
public List<FeedControl> getFeedControls(String userId)
|
||||
{
|
||||
ParameterCheck.mandatoryString("userId", userId);
|
||||
String currentUser = AuthenticationUtil.getCurrentUserName();
|
||||
|
||||
if ((currentUser == null) || ((! currentUser.equals(AuthenticationUtil.getSystemUserName())) && (! currentUser.equals(userId)) && (! authorityService.isAdminAuthority(currentUser))))
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Current user " + currentUser + " is not permitted to get feed controls for " + userId);
|
||||
}
|
||||
|
||||
return getFeedControlsImpl(userId);
|
||||
}
|
||||
|
||||
private List<FeedControl> getFeedControlsImpl(String userId)
|
||||
{
|
||||
ParameterCheck.mandatoryString("userId", userId);
|
||||
|
||||
if (! userNamesAreCaseSensitive)
|
||||
{
|
||||
userId = userId.toLowerCase();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
List<FeedControlDAO> feedControlDaos = feedControlDaoService.selectFeedControls(userId);
|
||||
List<FeedControl> feedControls = new ArrayList<FeedControl>(feedControlDaos.size());
|
||||
for (FeedControlDAO feedControlDao : feedControlDaos)
|
||||
{
|
||||
feedControls.add(feedControlDao.getFeedControl());
|
||||
}
|
||||
|
||||
return feedControls;
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to set feed control: " + e, e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.activities.ActivityService#deleteFeedControl(org.alfresco.service.cmr.activities.FeedControl)
|
||||
*/
|
||||
public void unsetFeedControl(FeedControl feedControl)
|
||||
{
|
||||
ParameterCheck.mandatory("feedControl", feedControl);
|
||||
|
||||
String userId = AuthenticationUtil.getCurrentUserName();
|
||||
if (! userNamesAreCaseSensitive)
|
||||
{
|
||||
userId = userId.toLowerCase();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
feedControlDaoService.deleteFeedControl(new FeedControlDAO(userId, feedControl));
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to set feed control: " + e, e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.activities.ActivityService#existsFeedControl(java.lang.String, org.alfresco.service.cmr.activities.FeedControl)
|
||||
*/
|
||||
public boolean existsFeedControl(FeedControl feedControl)
|
||||
{
|
||||
ParameterCheck.mandatory("feedControl", feedControl);
|
||||
|
||||
String userId = AuthenticationUtil.getCurrentUserName();
|
||||
|
||||
if (! userNamesAreCaseSensitive)
|
||||
{
|
||||
userId = userId.toLowerCase();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
long id = feedControlDaoService.selectFeedControl(new FeedControlDAO(userId, feedControl));
|
||||
return (id != -1);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to query feed control: " + e, e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.jscript.ClasspathScriptLocation;
|
||||
import org.alfresco.service.cmr.activities.ActivityService;
|
||||
import org.alfresco.service.cmr.activities.FeedControl;
|
||||
import org.alfresco.service.cmr.repository.ScriptLocation;
|
||||
import org.alfresco.service.cmr.repository.ScriptService;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
|
||||
/**
|
||||
* Activity Service Implementation unit test
|
||||
*
|
||||
* @author janv
|
||||
*/
|
||||
public class ActivityServiceImplTest extends BaseSpringTest
|
||||
{
|
||||
private ActivityService activityService;
|
||||
private ScriptService scriptService;
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
private static final String ADMIN_UN = "admin";
|
||||
private static final String ADMIN_PW = "admin";
|
||||
|
||||
private static final String USER_UN = "bob";
|
||||
private static final String USER_PW = "bob";
|
||||
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
{
|
||||
super.onSetUpInTransaction();
|
||||
|
||||
// Get the required services
|
||||
this.activityService = (ActivityService)this.applicationContext.getBean("ActivityService");
|
||||
this.scriptService = (ScriptService)this.applicationContext.getBean("ScriptService");
|
||||
|
||||
this.authenticationService = (AuthenticationService)applicationContext.getBean("authenticationService");
|
||||
|
||||
authenticationService.authenticate(ADMIN_UN, ADMIN_PW.toCharArray());
|
||||
}
|
||||
|
||||
protected void onTearDownInTransaction() throws Exception
|
||||
{
|
||||
authenticationService.clearCurrentSecurityContext();
|
||||
}
|
||||
|
||||
public void testPostValidActivities() throws Exception
|
||||
{
|
||||
this.activityService.postActivity("org.alfresco.testActivityType1", null, null, "");
|
||||
|
||||
this.activityService.postActivity("org.alfresco.testActivityType2", "", "", "");
|
||||
|
||||
this.activityService.postActivity("org.alfresco.testActivityType3", "site1", "appToolA", "{ \"var1\" : \"val1\" }");
|
||||
}
|
||||
|
||||
public void testPostInvalidActivities() throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
this.activityService.postActivity("", "", "", null, "");
|
||||
fail("invalid post activity");
|
||||
}
|
||||
catch (IllegalArgumentException iae)
|
||||
{
|
||||
assertTrue(iae.getMessage().contains("nodeRef is a mandatory parameter"));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.activityService.postActivity("", "", "", "");
|
||||
fail("invalid post activity");
|
||||
}
|
||||
catch (IllegalArgumentException iae)
|
||||
{
|
||||
assertTrue(iae.getMessage().contains("activityType is a mandatory parameter"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetEmptySiteFeed() throws Exception
|
||||
{
|
||||
authenticationService.clearCurrentSecurityContext();
|
||||
|
||||
if(! authenticationService.authenticationExists(USER_UN))
|
||||
{
|
||||
authenticationService.createAuthentication(USER_UN, USER_PW.toCharArray());
|
||||
}
|
||||
authenticationService.authenticate(USER_UN, USER_PW.toCharArray());
|
||||
|
||||
List<Map<String, Object>> siteFeedEntries = this.activityService.getSiteFeedEntries("unknown site", "some format");
|
||||
|
||||
assertNotNull(siteFeedEntries);
|
||||
assertTrue(siteFeedEntries.isEmpty());
|
||||
}
|
||||
|
||||
public void testGetEmptyUserFeed() throws Exception
|
||||
{
|
||||
|
||||
List<Map<String, Object>> userFeedEntries = this.activityService.getUserFeedEntries("unknown user", "some format", null);
|
||||
|
||||
assertNotNull(userFeedEntries);
|
||||
assertTrue(userFeedEntries.isEmpty());
|
||||
}
|
||||
|
||||
public void testJSAPI() throws Exception
|
||||
{
|
||||
ScriptLocation location = new ClasspathScriptLocation("org/alfresco/repo/activities/script/test_activityService.js");
|
||||
String result = (String)this.scriptService.executeScript(location, new HashMap<String, Object>(0));
|
||||
|
||||
// Check the result and fail if message returned
|
||||
if (result != null && result.length() != 0)
|
||||
{
|
||||
fail("The activity service test JS script failed: " + result);
|
||||
}
|
||||
}
|
||||
|
||||
public void testFeedControls() throws Exception
|
||||
{
|
||||
List<FeedControl> feedControls = this.activityService.getFeedControls(USER_UN);
|
||||
assertNotNull(feedControls);
|
||||
assertTrue(feedControls.isEmpty());
|
||||
|
||||
authenticationService.clearCurrentSecurityContext();
|
||||
|
||||
if(! authenticationService.authenticationExists(USER_UN))
|
||||
{
|
||||
authenticationService.createAuthentication(USER_UN, USER_PW.toCharArray());
|
||||
}
|
||||
authenticationService.authenticate(USER_UN, USER_PW.toCharArray());
|
||||
|
||||
feedControls = this.activityService.getFeedControls();
|
||||
assertNotNull(feedControls);
|
||||
assertTrue(feedControls.isEmpty());
|
||||
|
||||
assertFalse(this.activityService.existsFeedControl(new FeedControl("mySite1", "appTool1")));
|
||||
|
||||
this.activityService.setFeedControl(new FeedControl("mySite1", null));
|
||||
this.activityService.setFeedControl(new FeedControl("mySite1", "appTool1"));
|
||||
this.activityService.setFeedControl(new FeedControl(null, "appTool2"));
|
||||
|
||||
feedControls = this.activityService.getFeedControls();
|
||||
assertEquals(3, feedControls.size());
|
||||
|
||||
feedControls = this.activityService.getFeedControls(USER_UN);
|
||||
assertEquals(3, feedControls.size());
|
||||
|
||||
assertTrue(this.activityService.existsFeedControl(new FeedControl("mySite1", "appTool1")));
|
||||
|
||||
this.activityService.unsetFeedControl(new FeedControl("mySite1", "appTool1"));
|
||||
|
||||
assertFalse(this.activityService.existsFeedControl(new FeedControl("mySite1", "appTool1")));
|
||||
|
||||
feedControls = this.activityService.getFeedControls();
|
||||
assertEquals(2, feedControls.size());
|
||||
|
||||
this.activityService.unsetFeedControl(new FeedControl("mySite1", null));
|
||||
this.activityService.unsetFeedControl(new FeedControl(null, "appTool2"));
|
||||
|
||||
feedControls = this.activityService.getFeedControls();
|
||||
assertEquals(0, feedControls.size());
|
||||
}
|
||||
}
|
33
source/java/org/alfresco/repo/activities/ActivityType.java
Normal file
33
source/java/org/alfresco/repo/activities/ActivityType.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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;
|
||||
|
||||
public interface ActivityType
|
||||
{
|
||||
// pre-defined alfresco activity types
|
||||
|
||||
// generic fallback (if specific template is missing)
|
||||
public final String GENERIC_FALLBACK = "org.alfresco.generic";
|
||||
}
|
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed;
|
||||
|
||||
import org.alfresco.repo.activities.post.ActivityPostDaoService;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.alfresco.util.VmShutdownListener;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
/**
|
||||
* Implementations of the abstract feed generator component are responsible for generating activity feed entries
|
||||
*/
|
||||
public abstract class AbstractFeedGenerator implements FeedGenerator
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(AbstractFeedGenerator.class);
|
||||
|
||||
private static VmShutdownListener vmShutdownListener = new VmShutdownListener(AbstractFeedGenerator.class.getName());
|
||||
|
||||
private int maxItemsPerCycle = 100;
|
||||
|
||||
private ActivityPostDaoService postDaoService;
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
private String repoEndPoint; // http://hostname:port/webapp (eg. http://localhost:8080/alfresco)
|
||||
|
||||
private RepoCtx ctx = null;
|
||||
|
||||
private boolean busy;
|
||||
|
||||
public void setPostDaoService(ActivityPostDaoService postDaoService)
|
||||
{
|
||||
this.postDaoService = postDaoService;
|
||||
}
|
||||
|
||||
public void setAuthenticationService(AuthenticationService authenticationService)
|
||||
{
|
||||
this.authenticationService = authenticationService;
|
||||
}
|
||||
|
||||
public void setRepoEndPoint(String repoEndPoint)
|
||||
{
|
||||
this.repoEndPoint = repoEndPoint;
|
||||
}
|
||||
|
||||
public void setMaxItemsPerCycle(int maxItemsPerCycle)
|
||||
{
|
||||
this.maxItemsPerCycle = maxItemsPerCycle;
|
||||
}
|
||||
|
||||
public int getMaxItemsPerCycle()
|
||||
{
|
||||
return this.maxItemsPerCycle;
|
||||
}
|
||||
|
||||
public ActivityPostDaoService getPostDaoService()
|
||||
{
|
||||
return this.postDaoService;
|
||||
}
|
||||
|
||||
public AuthenticationService getAuthenticationService()
|
||||
{
|
||||
return this.authenticationService;
|
||||
}
|
||||
|
||||
public RepoCtx getWebScriptsCtx()
|
||||
{
|
||||
return this.ctx;
|
||||
}
|
||||
|
||||
public void init() throws Exception
|
||||
{
|
||||
ctx = new RepoCtx(repoEndPoint);
|
||||
|
||||
busy = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform basic checks to ensure that the necessary dependencies were injected.
|
||||
*/
|
||||
private void checkProperties()
|
||||
{
|
||||
PropertyCheck.mandatory(this, "postDaoService", postDaoService);
|
||||
}
|
||||
|
||||
|
||||
public void execute() throws JobExecutionException
|
||||
{
|
||||
if (busy)
|
||||
{
|
||||
logger.warn("Still busy ...");
|
||||
return;
|
||||
}
|
||||
|
||||
checkProperties();
|
||||
try
|
||||
{
|
||||
// run at least one job cycle
|
||||
boolean moreWork = true;
|
||||
while (moreWork)
|
||||
{
|
||||
moreWork = generate();
|
||||
}
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// If the VM is shutting down, then ignore
|
||||
if (vmShutdownListener.isVmShuttingDown())
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.error("Exception during generation of feeds", e);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
busy = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract boolean generate() throws Exception;
|
||||
}
|
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONStringer;
|
||||
|
||||
/**
|
||||
* Activity Feed DAO
|
||||
*/
|
||||
public class ActivityFeedDAO
|
||||
{
|
||||
private long id; // internal DB-generated id
|
||||
private String activityType;
|
||||
private String activitySummary;
|
||||
private String activitySummaryFormat;
|
||||
private String feedUserId;
|
||||
private String postUserId;
|
||||
private String siteNetwork;
|
||||
private String appTool;
|
||||
private Date postDate;
|
||||
private Date feedDate; // for debug
|
||||
private long postId; // for debug - not an explicit FK constraint, could be used to implement re-generate
|
||||
|
||||
|
||||
public long getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getActivitySummary()
|
||||
{
|
||||
return activitySummary;
|
||||
}
|
||||
|
||||
public void setActivitySummary(String summary)
|
||||
{
|
||||
this.activitySummary = summary;
|
||||
}
|
||||
|
||||
public String getFeedUserId()
|
||||
{
|
||||
return feedUserId;
|
||||
}
|
||||
|
||||
public void setFeedUserId(String userid)
|
||||
{
|
||||
this.feedUserId = userid;
|
||||
}
|
||||
|
||||
public String getPostUserId()
|
||||
{
|
||||
return postUserId;
|
||||
}
|
||||
|
||||
public void setPostUserId(String userid)
|
||||
{
|
||||
this.postUserId = userid;
|
||||
}
|
||||
|
||||
public String getActivitySummaryFormat()
|
||||
{
|
||||
return activitySummaryFormat;
|
||||
}
|
||||
|
||||
public void setActivitySummaryFormat(String format)
|
||||
{
|
||||
this.activitySummaryFormat = format;
|
||||
}
|
||||
|
||||
public String getSiteNetwork()
|
||||
{
|
||||
return siteNetwork;
|
||||
}
|
||||
|
||||
public void setSiteNetwork(String siteNetwork)
|
||||
{
|
||||
this.siteNetwork = siteNetwork;
|
||||
}
|
||||
|
||||
public String getActivityType()
|
||||
{
|
||||
return activityType;
|
||||
}
|
||||
public void setActivityType(String activityType)
|
||||
{
|
||||
this.activityType = activityType;
|
||||
}
|
||||
|
||||
public Date getPostDate()
|
||||
{
|
||||
return postDate;
|
||||
}
|
||||
|
||||
public void setPostDate(Date postDate)
|
||||
{
|
||||
this.postDate = postDate;
|
||||
}
|
||||
|
||||
public long getPostId()
|
||||
{
|
||||
return postId;
|
||||
}
|
||||
|
||||
public void setPostId(long postId)
|
||||
{
|
||||
this.postId = postId;
|
||||
}
|
||||
|
||||
public Date getFeedDate()
|
||||
{
|
||||
return feedDate;
|
||||
}
|
||||
|
||||
public void setFeedDate(Date feedDate)
|
||||
{
|
||||
this.feedDate = feedDate;
|
||||
}
|
||||
|
||||
public String getAppTool()
|
||||
{
|
||||
return appTool;
|
||||
}
|
||||
|
||||
public void setAppTool(String appTool)
|
||||
{
|
||||
this.appTool = appTool;
|
||||
}
|
||||
|
||||
public String getJSONString() throws JSONException
|
||||
{
|
||||
return new JSONStringer()
|
||||
.object()
|
||||
.key("postUserId")
|
||||
.value(postUserId)
|
||||
.key("postDate")
|
||||
.value(postDate)
|
||||
.key("feedUserId")
|
||||
.value(feedUserId)
|
||||
.key("siteNetwork")
|
||||
.value(siteNetwork)
|
||||
.key("activityType")
|
||||
.value(activityType)
|
||||
.key("activitySummary")
|
||||
.value(activitySummary)
|
||||
.key("activitySummaryFormat")
|
||||
.value(activitySummaryFormat)
|
||||
.endObject().toString();
|
||||
}
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.activities.ibatis.ActivityDaoService;
|
||||
|
||||
/**
|
||||
* Interface for activity feed DAO service
|
||||
*/
|
||||
public interface ActivityFeedDaoService extends ActivityDaoService
|
||||
{
|
||||
public long insertFeedEntry(ActivityFeedDAO activityFeed) throws SQLException;
|
||||
|
||||
public int deleteFeedEntries(Date keepDate) throws SQLException;
|
||||
|
||||
public List<ActivityFeedDAO> selectUserFeedEntries(String feedUserId, String format) throws SQLException;
|
||||
|
||||
public List<ActivityFeedDAO> selectUserFeedEntries(String feedUserId, String format, String siteId) throws SQLException;
|
||||
|
||||
public List<ActivityFeedDAO> selectSiteFeedEntries(String siteUserId, String format) throws SQLException;
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed;
|
||||
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
/**
|
||||
* Interface for feed generator
|
||||
*/
|
||||
public interface FeedGenerator
|
||||
{
|
||||
public void execute() throws JobExecutionException;
|
||||
|
||||
public int getEstimatedGridSize();
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobDataMap;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
/**
|
||||
* Executes scheduled feed generator quartz-job - refer to scheduled-jobs-context.xml
|
||||
*/
|
||||
public class FeedGeneratorJob implements Job
|
||||
{
|
||||
public FeedGeneratorJob()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the feed generator to do its work
|
||||
*/
|
||||
public void execute(JobExecutionContext context) throws JobExecutionException
|
||||
{
|
||||
JobDataMap jobData = context.getJobDetail().getJobDataMap();
|
||||
// extract the feed cleaner to use
|
||||
Object feedGeneratorObj = jobData.get("feedGenerator");
|
||||
if (feedGeneratorObj == null || !(feedGeneratorObj instanceof FeedGenerator))
|
||||
{
|
||||
throw new AlfrescoRuntimeException(
|
||||
"FeedGeneratorObj data must contain valid 'feedGenerator' reference");
|
||||
}
|
||||
FeedGenerator feedGenerator = (FeedGenerator)feedGeneratorObj;
|
||||
feedGenerator.execute();
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Interface for feed grid job
|
||||
*/
|
||||
public interface FeedGridJob
|
||||
{
|
||||
public void setArgument(JobSettings arg);
|
||||
|
||||
public JobSettings getArgument();
|
||||
|
||||
public Serializable execute() throws Exception;
|
||||
}
|
@@ -0,0 +1,636 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.activities.feed.control.FeedControlDAO;
|
||||
import org.alfresco.repo.activities.post.ActivityPostDAO;
|
||||
import org.alfresco.repo.template.ISO8601DateFormatMethod;
|
||||
import org.alfresco.util.Base64;
|
||||
import org.alfresco.util.JSONtoFmModel;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import freemarker.cache.URLTemplateLoader;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.DefaultObjectWrapper;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateException;
|
||||
|
||||
/**
|
||||
* Responsible for processing the individual task
|
||||
*/
|
||||
public abstract class FeedTaskProcessor
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(FeedTaskProcessor.class);
|
||||
|
||||
private static final String defaultFormat = "text";
|
||||
private static final String[] formats = {"atomentry", "rss", "json", "html", "xml", defaultFormat};
|
||||
|
||||
private static final String URL_SERVICE_SITES = "/api/sites";
|
||||
private static final String URL_MEMBERSHIPS = "/memberships";
|
||||
|
||||
private static final String URL_SERVICE_TEMPLATES = "/api/activities/templates";
|
||||
private static final String URL_SERVICE_TEMPLATE = "/api/activities/template";
|
||||
|
||||
|
||||
public void process(int jobTaskNode, long minSeq, long maxSeq, RepoCtx ctx) throws Exception
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(">>> Process: jobTaskNode '" + jobTaskNode + "' from seq '" + minSeq + "' to seq '" + maxSeq + "' on this node from grid job.");
|
||||
}
|
||||
|
||||
ActivityPostDAO selector = new ActivityPostDAO();
|
||||
selector.setJobTaskNode(jobTaskNode);
|
||||
selector.setMinId(minSeq);
|
||||
selector.setMaxId(maxSeq);
|
||||
selector.setStatus(ActivityPostDAO.STATUS.POSTED.toString());
|
||||
|
||||
String ticket = ctx.getTicket();
|
||||
|
||||
List<ActivityPostDAO> activityPosts = null;
|
||||
int totalGenerated = 0;
|
||||
|
||||
try
|
||||
{
|
||||
activityPosts = selectPosts(selector);
|
||||
|
||||
if (logger.isDebugEnabled()) { logger.debug(">>> Process: " + activityPosts.size() + " activity posts"); }
|
||||
|
||||
Configuration cfg = getFreemarkerConfiguration(ctx);
|
||||
|
||||
Map<String, List<String>> activityTemplates = new HashMap<String, List<String>>(10);
|
||||
|
||||
// for each activity post ...
|
||||
for (ActivityPostDAO activityPost : activityPosts)
|
||||
{
|
||||
String postingUserId = activityPost.getUserId();
|
||||
String activityType = activityPost.getActivityType();
|
||||
|
||||
// eg. org.alfresco.folder.added -> added
|
||||
String baseActivityType = getBaseActivityType(activityType);
|
||||
|
||||
List<String> fmTemplates = activityTemplates.get(baseActivityType);
|
||||
|
||||
if (fmTemplates == null)
|
||||
{
|
||||
// eg. org.alfresco.folder.added -> /org/alfresco/folder/added (note: the leading slash)
|
||||
String templateSubPath = getTemplateSubPath(activityType);
|
||||
|
||||
fmTemplates = new ArrayList<String>(0);
|
||||
while (true)
|
||||
{
|
||||
int idx = templateSubPath.lastIndexOf("/");
|
||||
if (idx != -1)
|
||||
{
|
||||
templateSubPath = templateSubPath.substring(0, idx);
|
||||
Map<String, List<String>> templates = null;
|
||||
try
|
||||
{
|
||||
// Repository callback to get list of FreeMarker templates for given activity type
|
||||
templates = getActivityTypeTemplates(ctx.getRepoEndPoint(), ticket, templateSubPath+"/");
|
||||
}
|
||||
catch (FileNotFoundException fnfe)
|
||||
{
|
||||
// ignore - path does not exist
|
||||
}
|
||||
if (templates != null)
|
||||
{
|
||||
if (templates.get(baseActivityType) != null)
|
||||
{
|
||||
// add templates, if format not already included
|
||||
addMissingFormats(activityType, fmTemplates, templates.get(baseActivityType));
|
||||
}
|
||||
|
||||
// special fallback case
|
||||
if (templates.get("generic") != null)
|
||||
{
|
||||
// add templates, if format not already included
|
||||
addMissingFormats(activityType, fmTemplates, templates.get("generic"));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
activityTemplates.put(baseActivityType, fmTemplates);
|
||||
}
|
||||
|
||||
if (fmTemplates.size() == 0)
|
||||
{
|
||||
logger.error(">>> Skipping activity post " + activityPost.getId() + " since no specific/generic templates for activityType: " + activityType );
|
||||
updatePostStatus(activityPost.getId(), ActivityPostDAO.STATUS.ERROR);
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<String, Object> model = null;
|
||||
try
|
||||
{
|
||||
model = JSONtoFmModel.convertJSONObjectToMap(activityPost.getActivityData());
|
||||
}
|
||||
catch(JSONException je)
|
||||
{
|
||||
logger.error(">>> Skipping activity post " + activityPost.getId() + " due to invalid activity data: " + je);
|
||||
updatePostStatus(activityPost.getId(), ActivityPostDAO.STATUS.ERROR);
|
||||
continue;
|
||||
}
|
||||
|
||||
model.put("activityType", activityPost.getActivityType());
|
||||
model.put("siteNetwork", activityPost.getSiteNetwork());
|
||||
model.put("userId", activityPost.getUserId());
|
||||
model.put("id", activityPost.getId());
|
||||
model.put("date", activityPost.getPostDate()); // post date rather than time that feed is generated
|
||||
model.put("xmldate", new ISO8601DateFormatMethod());
|
||||
model.put("repoEndPoint", ctx.getRepoEndPoint());
|
||||
|
||||
Set<String> connectedUsers = null;
|
||||
if ((activityPost.getSiteNetwork() == null) || (activityPost.getSiteNetwork().length() == 0))
|
||||
{
|
||||
connectedUsers = new HashSet<String>(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
// Repository callback to get site members
|
||||
connectedUsers = getSiteMembers(ctx, activityPost.getSiteNetwork());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
logger.error(">>> Skipping activity post " + activityPost.getId() + " since failed to get site members: " + e);
|
||||
updatePostStatus(activityPost.getId(), ActivityPostDAO.STATUS.ERROR);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
connectedUsers.add(""); // add empty posting userid - to represent site feed !
|
||||
|
||||
try
|
||||
{
|
||||
startTransaction();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(">>> Process: " + connectedUsers.size() + " candidate connections for activity post " + activityPost.getId());
|
||||
}
|
||||
|
||||
int excludedConnections = 0;
|
||||
|
||||
for (String connectedUser : connectedUsers)
|
||||
{
|
||||
List<FeedControlDAO> feedControls = null;
|
||||
if (! connectedUser.equals(""))
|
||||
{
|
||||
feedControls = getFeedControls(connectedUser);
|
||||
}
|
||||
|
||||
// filter based on opt-out feed controls (if any)
|
||||
if (! acceptActivity(activityPost, feedControls))
|
||||
{
|
||||
excludedConnections++;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (String fmTemplate : fmTemplates)
|
||||
{
|
||||
// determine format - based on template naming convention
|
||||
String formatFound = null;
|
||||
for (String format : formats)
|
||||
{
|
||||
if (fmTemplate.contains("."+format+"."))
|
||||
{
|
||||
formatFound = format;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (formatFound == null)
|
||||
{
|
||||
formatFound = defaultFormat;
|
||||
logger.warn("Unknown format for: " + fmTemplate + " default to '"+formatFound+"'");
|
||||
}
|
||||
|
||||
ActivityFeedDAO feed = new ActivityFeedDAO();
|
||||
|
||||
// Generate activity feed summary
|
||||
feed.setFeedUserId(connectedUser);
|
||||
feed.setPostUserId(postingUserId);
|
||||
feed.setActivityType(activityType);
|
||||
|
||||
if (formatFound.equals("json"))
|
||||
{
|
||||
// allows generic JSON template to simply pass straight through
|
||||
model.put("activityData", activityPost.getActivityData());
|
||||
}
|
||||
|
||||
String activitySummary = processFreemarker(fmTemplate, cfg, model);
|
||||
if (! activitySummary.equals(""))
|
||||
{
|
||||
feed.setActivitySummary(activitySummary);
|
||||
feed.setActivitySummaryFormat(formatFound);
|
||||
feed.setSiteNetwork(activityPost.getSiteNetwork());
|
||||
feed.setAppTool(activityPost.getAppTool());
|
||||
feed.setPostDate(activityPost.getPostDate());
|
||||
feed.setPostId(activityPost.getId());
|
||||
feed.setFeedDate(new Date());
|
||||
|
||||
// Insert activity feed
|
||||
insertFeedEntry(feed); // ignore returned feedId
|
||||
|
||||
totalGenerated++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Empty template result for activityType '" + activityType + "' using format '" + formatFound + "' hence skip feed entry (activity post " + activityPost.getId() + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updatePostStatus(activityPost.getId(), ActivityPostDAO.STATUS.PROCESSED);
|
||||
|
||||
commitTransaction();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(">>> Processed: " + (connectedUsers.size() - excludedConnections) + " connections for activity post " + activityPost.getId() + " (excluded " + excludedConnections + ")");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
endTransaction();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(SQLException se)
|
||||
{
|
||||
logger.error(se);
|
||||
throw se;
|
||||
}
|
||||
finally
|
||||
{
|
||||
logger.info(">>> Generated " + totalGenerated + " activity feed entries for " + (activityPosts == null ? 0 : activityPosts.size()) + " activity posts");
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void startTransaction() throws SQLException;
|
||||
|
||||
public abstract void commitTransaction() throws SQLException;
|
||||
|
||||
public abstract void endTransaction() throws SQLException;
|
||||
|
||||
public abstract List<ActivityPostDAO> selectPosts(ActivityPostDAO selector) throws SQLException;
|
||||
|
||||
public abstract List<FeedControlDAO> selectUserFeedControls(String userId) throws SQLException;
|
||||
|
||||
public abstract long insertFeedEntry(ActivityFeedDAO feed) throws SQLException;
|
||||
|
||||
public abstract int updatePostStatus(long id, ActivityPostDAO.STATUS status) throws SQLException;
|
||||
|
||||
|
||||
protected String callWebScript(String urlString, String ticket) throws MalformedURLException, URISyntaxException, IOException
|
||||
{
|
||||
URL url = new URL(urlString);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(">>> Request URI: " + url.toURI());
|
||||
}
|
||||
|
||||
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
|
||||
if (ticket != null)
|
||||
{
|
||||
// add Base64 encoded authorization header
|
||||
// refer to: http://wiki.alfresco.com/wiki/Web_Scripts_Framework#HTTP_Basic_Authentication
|
||||
conn.addRequestProperty("Authorization", "Basic " + Base64.encodeBytes(ticket.getBytes()));
|
||||
}
|
||||
|
||||
String result = null;
|
||||
InputStream is = null;
|
||||
BufferedReader br = null;
|
||||
|
||||
try
|
||||
{
|
||||
is = conn.getInputStream();
|
||||
br = new BufferedReader(new InputStreamReader(is));
|
||||
|
||||
String line = null;
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while(((line = br.readLine()) !=null)) {
|
||||
sb.append(line);
|
||||
}
|
||||
|
||||
result = sb.toString();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
int responseCode = conn.getResponseCode();
|
||||
logger.debug(">>> Response code: " + responseCode);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (br != null) { br.close(); };
|
||||
if (is != null) { is.close(); };
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Set<String> getSiteMembers(RepoCtx ctx, String siteId) throws Exception
|
||||
{
|
||||
Set<String> members = new HashSet<String>();
|
||||
if ((siteId != null) && (siteId.length() != 0))
|
||||
{
|
||||
StringBuffer sbUrl = new StringBuffer();
|
||||
sbUrl.append(ctx.getRepoEndPoint()).
|
||||
append(URL_SERVICE_SITES).append("/").append(siteId).append(URL_MEMBERSHIPS);
|
||||
|
||||
String jsonArrayResult = callWebScript(sbUrl.toString(), ctx.getTicket());
|
||||
if ((jsonArrayResult != null) && (jsonArrayResult.length() != 0))
|
||||
{
|
||||
JSONArray ja = new JSONArray(jsonArrayResult);
|
||||
for (int i = 0; i < ja.length(); i++)
|
||||
{
|
||||
JSONObject member = (JSONObject)ja.get(i);
|
||||
JSONObject person = (JSONObject)member.getJSONObject("person");
|
||||
members.add(person.getString("userName"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return members;
|
||||
}
|
||||
|
||||
protected Map<String, List<String>> getActivityTypeTemplates(String repoEndPoint, String ticket, String subPath) throws Exception
|
||||
{
|
||||
StringBuffer sbUrl = new StringBuffer();
|
||||
sbUrl.append(repoEndPoint).append(URL_SERVICE_TEMPLATES).append("?p=").append(subPath).append("*").append("&format=json");
|
||||
|
||||
String jsonArrayResult = null;
|
||||
try
|
||||
{
|
||||
jsonArrayResult = callWebScript(sbUrl.toString(), ticket);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
List<String> allTemplateNames = new ArrayList<String>(10);
|
||||
|
||||
if ((jsonArrayResult != null) && (jsonArrayResult.length() != 0))
|
||||
{
|
||||
JSONArray ja = new JSONArray(jsonArrayResult);
|
||||
for (int i = 0; i < ja.length(); i++)
|
||||
{
|
||||
String name = ja.getString(i);
|
||||
if (! name.contains(" (Working Copy)."))
|
||||
{
|
||||
allTemplateNames.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, List<String>> activityTemplates = new HashMap<String, List<String>>(10);
|
||||
|
||||
for (String template : allTemplateNames)
|
||||
{
|
||||
// assume template path = <path>/<base-activityType>.<format>.ftl
|
||||
// and base-activityType can contain "."
|
||||
|
||||
String baseActivityType = template;
|
||||
int idx1 = baseActivityType.lastIndexOf("/");
|
||||
if (idx1 != -1)
|
||||
{
|
||||
baseActivityType = baseActivityType.substring(idx1+1);
|
||||
}
|
||||
|
||||
int idx2 = baseActivityType.lastIndexOf(".");
|
||||
if (idx2 != -1)
|
||||
{
|
||||
int idx3 = baseActivityType.substring(0, idx2).lastIndexOf(".");
|
||||
if (idx3 != -1)
|
||||
{
|
||||
baseActivityType = baseActivityType.substring(0, idx3);
|
||||
|
||||
List<String> activityTypeTemplateList = activityTemplates.get(baseActivityType);
|
||||
if (activityTypeTemplateList == null)
|
||||
{
|
||||
activityTypeTemplateList = new ArrayList<String>(1);
|
||||
activityTemplates.put(baseActivityType, activityTypeTemplateList);
|
||||
}
|
||||
activityTypeTemplateList.add(template);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return activityTemplates;
|
||||
}
|
||||
|
||||
protected Configuration getFreemarkerConfiguration(RepoCtx ctx)
|
||||
{
|
||||
Configuration cfg = new Configuration();
|
||||
cfg.setObjectWrapper(new DefaultObjectWrapper());
|
||||
|
||||
// custom template loader
|
||||
cfg.setTemplateLoader(new TemplateWebScriptLoader(ctx.getRepoEndPoint(), ctx.getTicket()));
|
||||
|
||||
// TODO review i18n
|
||||
cfg.setLocalizedLookup(false);
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
protected String processFreemarker(String fmTemplate, Configuration cfg, Map<String, Object> model) throws IOException, TemplateException, Exception
|
||||
{
|
||||
Template myTemplate = cfg.getTemplate(fmTemplate);
|
||||
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
Writer out = new OutputStreamWriter(bos);
|
||||
myTemplate.process(model, out);
|
||||
out.flush();
|
||||
|
||||
return new String(bos.toByteArray());
|
||||
}
|
||||
|
||||
protected List<FeedControlDAO> getFeedControls(String connectedUser) throws SQLException
|
||||
{
|
||||
// TODO cache for this run
|
||||
return selectUserFeedControls(connectedUser);
|
||||
}
|
||||
|
||||
protected boolean acceptActivity(ActivityPostDAO activityPost, List<FeedControlDAO> feedControls)
|
||||
{
|
||||
if (feedControls == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for (FeedControlDAO feedControl : feedControls)
|
||||
{
|
||||
if ((feedControl.getSiteNetwork() == null) && (feedControl.getAppTool() != null))
|
||||
{
|
||||
if (feedControl.getAppTool().equals(activityPost.getAppTool()))
|
||||
{
|
||||
// exclude this appTool (across sites)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ((feedControl.getAppTool() == null) && (feedControl.getSiteNetwork() != null))
|
||||
{
|
||||
if (feedControl.getSiteNetwork().equals(activityPost.getSiteNetwork()))
|
||||
{
|
||||
// exclude this site (across appTools)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ((feedControl.getSiteNetwork() != null) && (feedControl.getAppTool() != null))
|
||||
{
|
||||
if ((feedControl.getSiteNetwork().equals(activityPost.getSiteNetwork())) &&
|
||||
(feedControl.getAppTool().equals(activityPost.getAppTool())))
|
||||
{
|
||||
// exclude this appTool for this site
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void addMissingFormats(String activityType, List<String> fmTemplates, List<String> templatesToAdd)
|
||||
{
|
||||
for (String templateToAdd : templatesToAdd)
|
||||
{
|
||||
int idx1 = templateToAdd.lastIndexOf(".");
|
||||
if (idx1 != -1)
|
||||
{
|
||||
int idx2 = templateToAdd.substring(0, idx1).lastIndexOf(".");
|
||||
if (idx2 != -1)
|
||||
{
|
||||
String templateFormat = templateToAdd.substring(idx2+1, idx1);
|
||||
|
||||
boolean found = false;
|
||||
for (String fmTemplate : fmTemplates)
|
||||
{
|
||||
if (fmTemplate.contains("."+templateFormat+"."))
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! found)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(">>> Add template '" + templateToAdd + "' for type '" + activityType + "'");
|
||||
}
|
||||
fmTemplates.add(templateToAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected String getTemplateSubPath(String activityType)
|
||||
{
|
||||
return (! activityType.startsWith("/") ? "/" : "") + activityType.replace(".", "/");
|
||||
}
|
||||
|
||||
protected String getBaseActivityType(String activityType)
|
||||
{
|
||||
String[] parts = activityType.split("\\.");
|
||||
|
||||
return (parts.length != 0 ? parts[parts.length-1] : "");
|
||||
}
|
||||
|
||||
protected class TemplateWebScriptLoader extends URLTemplateLoader
|
||||
{
|
||||
private String repoEndPoint;
|
||||
private String ticketId;
|
||||
|
||||
public TemplateWebScriptLoader(String repoEndPoint, String ticketId)
|
||||
{
|
||||
this.repoEndPoint = repoEndPoint;
|
||||
this.ticketId = ticketId;
|
||||
}
|
||||
|
||||
public URL getURL(String templatePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(this.repoEndPoint).
|
||||
append(URL_SERVICE_TEMPLATE).append("?p=").append(templatePath).
|
||||
append("&format=text").
|
||||
append("&alf_ticket=").append(ticketId);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(">>> getURL: " + sb.toString());
|
||||
}
|
||||
|
||||
return new URL(sb.toString());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Responsible for splitting the feed task into feed jobs (to be executed locally or on a grid)
|
||||
*/
|
||||
public class FeedTaskSplit
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(FeedTaskSplit.class);
|
||||
|
||||
public Collection<JobSettings> split(int gridSize, JobSettings splitSettings)
|
||||
{
|
||||
long maxSequence = splitSettings.getMaxSeq();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("split: start - gridSize = " + gridSize + ", maxSequence = " + maxSequence);
|
||||
}
|
||||
|
||||
long minSequence = maxSequence - splitSettings.getMaxItemsPerCycle() + 1;
|
||||
|
||||
splitSettings.setMinSeq((minSequence >= 0L ? minSequence : 0L));
|
||||
|
||||
List<JobSettings> jobs = new ArrayList<JobSettings>(gridSize);
|
||||
|
||||
int maxNodeHash = splitSettings.getJobTaskNode();
|
||||
|
||||
// note: gridSize may change between runs, hence use maximum node hash/bucket for this cycle
|
||||
for (int n = 1; n <= maxNodeHash; n++)
|
||||
{
|
||||
// every job gets its own copy of the jobSettings (with different nodeHash) as an argument.
|
||||
JobSettings jobSettings = splitSettings.clone();
|
||||
jobSettings.setJobTaskNode(n);
|
||||
|
||||
jobs.add(jobSettings);
|
||||
}
|
||||
|
||||
return jobs;
|
||||
}
|
||||
}
|
100
source/java/org/alfresco/repo/activities/feed/JobSettings.java
Normal file
100
source/java/org/alfresco/repo/activities/feed/JobSettings.java
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Job settings passed from grid task to grid job
|
||||
*/
|
||||
public class JobSettings implements Serializable
|
||||
{
|
||||
public static final long serialVersionUID = -3896042917378679686L;
|
||||
|
||||
private int jobTaskNode;
|
||||
private long maxSeq;
|
||||
private long minSeq;
|
||||
private RepoCtx ctx;
|
||||
private int maxItemsPerCycle;
|
||||
|
||||
public int getJobTaskNode()
|
||||
{
|
||||
return jobTaskNode;
|
||||
}
|
||||
|
||||
public void setJobTaskNode(int jobTaskNode)
|
||||
{
|
||||
this.jobTaskNode = jobTaskNode;
|
||||
}
|
||||
|
||||
public long getMaxSeq()
|
||||
{
|
||||
return maxSeq;
|
||||
}
|
||||
|
||||
public void setMaxSeq(long maxSeq)
|
||||
{
|
||||
this.maxSeq = maxSeq;
|
||||
}
|
||||
|
||||
public long getMinSeq()
|
||||
{
|
||||
return minSeq;
|
||||
}
|
||||
|
||||
public void setMinSeq(long minSeq)
|
||||
{
|
||||
this.minSeq = minSeq;
|
||||
}
|
||||
|
||||
public RepoCtx getWebScriptsCtx() {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
public void setWebScriptsCtx(RepoCtx ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
public int getMaxItemsPerCycle()
|
||||
{
|
||||
return maxItemsPerCycle;
|
||||
}
|
||||
|
||||
public void setMaxItemsPerCycle(int maxItemsPerCycle)
|
||||
{
|
||||
this.maxItemsPerCycle = maxItemsPerCycle;
|
||||
}
|
||||
|
||||
public JobSettings clone()
|
||||
{
|
||||
JobSettings js = new JobSettings();
|
||||
js.setMaxItemsPerCycle(this.maxItemsPerCycle);
|
||||
js.setMaxSeq(this.maxSeq);
|
||||
js.setMinSeq(this.minSeq);
|
||||
js.setJobTaskNode(this.jobTaskNode);
|
||||
js.setWebScriptsCtx(this.ctx); // note: shallow copy
|
||||
return js;
|
||||
}
|
||||
}
|
57
source/java/org/alfresco/repo/activities/feed/RepoCtx.java
Normal file
57
source/java/org/alfresco/repo/activities/feed/RepoCtx.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Repository context passed from grid task to grid job
|
||||
*/
|
||||
public class RepoCtx implements Serializable
|
||||
{
|
||||
private String repoEndPoint; // http://hostname:port/webapp (eg. http://localhost:8080/alfresco)
|
||||
private String ticket;
|
||||
|
||||
public static final long serialVersionUID = -3896042917378679686L;
|
||||
|
||||
public RepoCtx(String repoEndPoint)
|
||||
{
|
||||
this.repoEndPoint = repoEndPoint.endsWith("/") ? repoEndPoint.substring(0, repoEndPoint.length()-1) : repoEndPoint;
|
||||
}
|
||||
|
||||
public String getRepoEndPoint() {
|
||||
return repoEndPoint;
|
||||
}
|
||||
|
||||
public String getTicket()
|
||||
{
|
||||
return ticket;
|
||||
}
|
||||
|
||||
public void setTicket(String ticket)
|
||||
{
|
||||
this.ticket = ticket;
|
||||
}
|
||||
}
|
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed.cleanup;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.activities.feed.ActivityFeedDaoService;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.alfresco.util.VmShutdownListener;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
/**
|
||||
* The feed cleaner component is responsible for purging 'obsolete' activity feed entries
|
||||
*/
|
||||
public class FeedCleaner
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(FeedCleaner.class);
|
||||
|
||||
private static VmShutdownListener vmShutdownListener = new VmShutdownListener(FeedCleaner.class.getName());
|
||||
|
||||
private int maxAgeMins = 0;
|
||||
|
||||
private ActivityFeedDaoService feedDaoService;
|
||||
|
||||
public void setFeedDaoService(ActivityFeedDaoService feedDaoService)
|
||||
{
|
||||
this.feedDaoService = feedDaoService;
|
||||
}
|
||||
|
||||
public void setMaxAgeMins(int mins)
|
||||
{
|
||||
this.maxAgeMins = mins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform basic checks to ensure that the necessary dependencies were injected.
|
||||
*/
|
||||
private void checkProperties()
|
||||
{
|
||||
PropertyCheck.mandatory(this, "feedDaoService", feedDaoService);
|
||||
|
||||
// check the max age
|
||||
if (maxAgeMins <= 0)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Property 'maxAgeMins' must be greater than 0");
|
||||
}
|
||||
}
|
||||
|
||||
public void execute() throws JobExecutionException
|
||||
{
|
||||
checkProperties();
|
||||
try
|
||||
{
|
||||
long nowTimeOffset = new Date().getTime();
|
||||
long keepTimeOffset = nowTimeOffset - (maxAgeMins*60*1000); // millsecs = mins * 60 secs * 1000 msecs
|
||||
Date keepDate = new Date(keepTimeOffset);
|
||||
|
||||
// clean old entries
|
||||
int deletedCount = feedDaoService.deleteFeedEntries(keepDate);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
|
||||
logger.debug("Cleaned " + deletedCount + " entries (upto " + keepDate + ", max age " + maxAgeMins + " mins)");
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
logger.error("Exception during cleanup of feeds", e);
|
||||
throw new JobExecutionException(e);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// If the VM is shutting down, then ignore
|
||||
if (vmShutdownListener.isVmShuttingDown())
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.error("Exception during cleanup of feeds", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed.cleanup;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobDataMap;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
/**
|
||||
* Executes scheduled feed cleaner quartz-job - refer to scheduled-jobs-context.xml
|
||||
*/
|
||||
public class FeedCleanupJob implements Job
|
||||
{
|
||||
public FeedCleanupJob()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the feed cleaner to do its work
|
||||
*/
|
||||
public void execute(JobExecutionContext context) throws JobExecutionException
|
||||
{
|
||||
JobDataMap jobData = context.getJobDetail().getJobDataMap();
|
||||
// extract the feed cleaner to use
|
||||
Object feedCleanerObj = jobData.get("feedCleaner");
|
||||
if (feedCleanerObj == null || !(feedCleanerObj instanceof FeedCleaner))
|
||||
{
|
||||
throw new AlfrescoRuntimeException(
|
||||
"FeedCleanupJob data must contain valid 'feedCleaner' reference");
|
||||
}
|
||||
FeedCleaner feedCleaner = (FeedCleaner)feedCleanerObj;
|
||||
feedCleaner.execute();
|
||||
}
|
||||
}
|
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed.control;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.alfresco.service.cmr.activities.FeedControl;
|
||||
|
||||
/**
|
||||
* Activity Feed Control DAO
|
||||
*/
|
||||
public class FeedControlDAO
|
||||
{
|
||||
private long id; // internal DB-generated id
|
||||
private String feedUserId;
|
||||
private String siteNetwork;
|
||||
private String appTool;
|
||||
|
||||
private Date lastModified; // when inserted
|
||||
|
||||
// TODO - review - deleted feed controls are not kept and available feed controls are currently retrieved during generation, hence
|
||||
// it is possible for a feed control to be applied even if lastModified is greater than postDate - could check the date !
|
||||
// it is also possible for a feed control to not be applied if it is deleted just after the post - would need to keep, at least until next generation
|
||||
|
||||
public FeedControlDAO()
|
||||
{
|
||||
}
|
||||
|
||||
public FeedControlDAO(String feedUserId)
|
||||
{
|
||||
this.feedUserId = feedUserId;
|
||||
}
|
||||
|
||||
public FeedControlDAO(String feedUserId, FeedControl feedControl)
|
||||
{
|
||||
this.feedUserId = feedUserId;
|
||||
this.siteNetwork = feedControl.getSiteId();
|
||||
this.appTool = feedControl.getAppToolId();
|
||||
}
|
||||
|
||||
public FeedControl getFeedControl()
|
||||
{
|
||||
return new FeedControl(this.siteNetwork, this.appTool);
|
||||
}
|
||||
|
||||
public long getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getSiteNetwork()
|
||||
{
|
||||
return siteNetwork;
|
||||
}
|
||||
|
||||
public void setSiteNetwork(String siteNetwork)
|
||||
{
|
||||
this.siteNetwork = siteNetwork;
|
||||
}
|
||||
|
||||
public String getAppTool()
|
||||
{
|
||||
return appTool;
|
||||
}
|
||||
|
||||
public void setAppTool(String appTool)
|
||||
{
|
||||
this.appTool = appTool;
|
||||
}
|
||||
|
||||
public String getFeedUserId()
|
||||
{
|
||||
return feedUserId;
|
||||
}
|
||||
|
||||
public void setFeedUserId(String feedUserId)
|
||||
{
|
||||
this.feedUserId = feedUserId;
|
||||
}
|
||||
|
||||
public Date getLastModified()
|
||||
{
|
||||
return lastModified;
|
||||
}
|
||||
|
||||
public void setLastModified(Date lastModified)
|
||||
{
|
||||
this.lastModified = lastModified;
|
||||
}
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed.control;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Interface for user activity feed controls DAO service
|
||||
*/
|
||||
public interface FeedControlDaoService
|
||||
{
|
||||
public long insertFeedControl(FeedControlDAO activityFeedControl) throws SQLException;
|
||||
|
||||
public int deleteFeedControl(FeedControlDAO activityFeedControl) throws SQLException;
|
||||
|
||||
public List<FeedControlDAO> selectFeedControls(String userId) throws SQLException;
|
||||
|
||||
public long selectFeedControl(FeedControlDAO activityFeedControl) throws SQLException;
|
||||
}
|
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed.local;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
|
||||
import org.alfresco.repo.activities.feed.AbstractFeedGenerator;
|
||||
import org.alfresco.repo.activities.feed.FeedGridJob;
|
||||
import org.alfresco.repo.activities.feed.FeedTaskProcessor;
|
||||
import org.alfresco.repo.activities.feed.JobSettings;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* The local (ie. not grid) feed generator component is responsible for generating feed entries
|
||||
*/
|
||||
public class LocalFeedGenerator extends AbstractFeedGenerator
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(LocalFeedGenerator.class);
|
||||
|
||||
private FeedTaskProcessor feedTaskProcessor;
|
||||
|
||||
public void setFeedTaskProcessor(FeedTaskProcessor feedTaskProcessor)
|
||||
{
|
||||
this.feedTaskProcessor = feedTaskProcessor;
|
||||
}
|
||||
|
||||
public int getEstimatedGridSize()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public void init() throws Exception
|
||||
{
|
||||
super.init();
|
||||
}
|
||||
|
||||
protected boolean generate() throws Exception
|
||||
{
|
||||
Long maxSequence = getPostDaoService().getMaxActivitySeq();
|
||||
Integer maxNodeHash = getPostDaoService().getMaxNodeHash();
|
||||
|
||||
String gridName = "local";
|
||||
|
||||
if (maxSequence != null)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(">>> Execute job cycle: " + gridName + " (maxSeq: " + maxSequence + ")");
|
||||
}
|
||||
|
||||
long startTime = new Date().getTime();
|
||||
|
||||
// TODO ... or push this upto to job scheduler ... ?
|
||||
AuthenticationUtil.runAs(new RunAsWork<Object>()
|
||||
{
|
||||
public Object doWork()
|
||||
{
|
||||
getWebScriptsCtx().setTicket(getAuthenticationService().getCurrentTicket());
|
||||
return null;
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName()); // need web scripts to support System-level authentication ... see RepositoryContainer !
|
||||
|
||||
JobSettings js = new JobSettings();
|
||||
js.setMaxSeq(maxSequence);
|
||||
js.setJobTaskNode(maxNodeHash);
|
||||
js.setWebScriptsCtx(getWebScriptsCtx());
|
||||
js.setMaxItemsPerCycle(getMaxItemsPerCycle());
|
||||
|
||||
LocalFeedTaskSplitter splitter = new LocalFeedTaskSplitter();
|
||||
splitter.setFeedTaskProcessor(feedTaskProcessor);
|
||||
|
||||
Collection<FeedGridJob> jobs = splitter.split(getEstimatedGridSize(), js);
|
||||
|
||||
for (FeedGridJob job : jobs)
|
||||
{
|
||||
job.execute();
|
||||
}
|
||||
|
||||
long endTime = new Date().getTime();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(">>> Finish job cycle: " + gridName + " (time taken (secs) = " + ((endTime - startTime) / 1000) + ")");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(">>> No work to be done for this job cycle: " + gridName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed.local;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.alfresco.repo.activities.feed.FeedGridJob;
|
||||
import org.alfresco.repo.activities.feed.FeedTaskProcessor;
|
||||
import org.alfresco.repo.activities.feed.JobSettings;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Implementation to execute local (ie. not grid) feed job
|
||||
*/
|
||||
public class LocalFeedGridJob implements FeedGridJob
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(LocalFeedGridJob.class);
|
||||
|
||||
private JobSettings arg;
|
||||
|
||||
private FeedTaskProcessor feedTaskProcessor;
|
||||
|
||||
public void setFeedTaskProcessor(FeedTaskProcessor feedTaskProcessor)
|
||||
{
|
||||
this.feedTaskProcessor = feedTaskProcessor;
|
||||
}
|
||||
|
||||
public Serializable execute() throws Exception
|
||||
{
|
||||
JobSettings js = getArgument();
|
||||
|
||||
if (logger.isDebugEnabled()) { logger.debug(">>> Execute: nodehash '" + js.getJobTaskNode() + "' from seq '" + js.getMinSeq() + "' to seq '" + js.getMaxSeq() + "' on this node"); }
|
||||
|
||||
try
|
||||
{
|
||||
feedTaskProcessor.process(js.getJobTaskNode(), js.getMinSeq(), js.getMaxSeq(), js.getWebScriptsCtx());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.error(e);
|
||||
throw new Exception(e.getMessage(), e.getCause());
|
||||
}
|
||||
|
||||
// This job does not return any result.
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setArgument(JobSettings arg)
|
||||
{
|
||||
this.arg = arg;
|
||||
}
|
||||
|
||||
public JobSettings getArgument()
|
||||
{
|
||||
return this.arg;
|
||||
}
|
||||
}
|
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed.local;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.activities.feed.ActivityFeedDAO;
|
||||
import org.alfresco.repo.activities.feed.ActivityFeedDaoService;
|
||||
import org.alfresco.repo.activities.feed.FeedTaskProcessor;
|
||||
import org.alfresco.repo.activities.feed.control.FeedControlDAO;
|
||||
import org.alfresco.repo.activities.feed.control.FeedControlDaoService;
|
||||
import org.alfresco.repo.activities.post.ActivityPostDAO;
|
||||
import org.alfresco.repo.activities.post.ActivityPostDaoService;
|
||||
|
||||
import com.ibatis.sqlmap.client.SqlMapClient;
|
||||
|
||||
/**
|
||||
* The local (ie. not grid) feed task processor is responsible for processing the individual feed job
|
||||
*/
|
||||
public class LocalFeedTaskProcessor extends FeedTaskProcessor
|
||||
{
|
||||
private ActivityPostDaoService postDaoService;
|
||||
private ActivityFeedDaoService feedDaoService;
|
||||
private FeedControlDaoService feedControlDaoService;
|
||||
|
||||
// used to start/end/commit transaction
|
||||
// note: currently assumes that all dao services are configured with this mapper / data source
|
||||
private SqlMapClient sqlMapper;
|
||||
|
||||
public void setPostDaoService(ActivityPostDaoService postDaoService)
|
||||
{
|
||||
this.postDaoService = postDaoService;
|
||||
}
|
||||
|
||||
public void setFeedDaoService(ActivityFeedDaoService feedDaoService)
|
||||
{
|
||||
this.feedDaoService = feedDaoService;
|
||||
}
|
||||
|
||||
public void setFeedControlDaoService(FeedControlDaoService feedControlDaoService)
|
||||
{
|
||||
this.feedControlDaoService = feedControlDaoService;
|
||||
}
|
||||
|
||||
public void setSqlMapClient(SqlMapClient sqlMapper)
|
||||
{
|
||||
this.sqlMapper = sqlMapper;
|
||||
}
|
||||
|
||||
public void startTransaction() throws SQLException
|
||||
{
|
||||
sqlMapper.startTransaction();
|
||||
}
|
||||
|
||||
public void commitTransaction() throws SQLException
|
||||
{
|
||||
sqlMapper.commitTransaction();
|
||||
}
|
||||
|
||||
public void endTransaction() throws SQLException
|
||||
{
|
||||
sqlMapper.endTransaction();
|
||||
}
|
||||
|
||||
public List<ActivityPostDAO> selectPosts(ActivityPostDAO selector) throws SQLException
|
||||
{
|
||||
return postDaoService.selectPosts(selector);
|
||||
}
|
||||
|
||||
public long insertFeedEntry(ActivityFeedDAO feed) throws SQLException
|
||||
{
|
||||
return feedDaoService.insertFeedEntry(feed);
|
||||
}
|
||||
|
||||
public int updatePostStatus(long id, ActivityPostDAO.STATUS status) throws SQLException
|
||||
{
|
||||
return postDaoService.updatePostStatus(id, status);
|
||||
}
|
||||
|
||||
public List<FeedControlDAO> selectUserFeedControls(String userId) throws SQLException
|
||||
{
|
||||
return feedControlDaoService.selectFeedControls(userId);
|
||||
}
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.feed.local;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.activities.feed.FeedGridJob;
|
||||
import org.alfresco.repo.activities.feed.FeedTaskProcessor;
|
||||
import org.alfresco.repo.activities.feed.FeedTaskSplit;
|
||||
import org.alfresco.repo.activities.feed.JobSettings;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* The local feed task splitter is responsible for splitting the feed task into feed jobs
|
||||
*/
|
||||
public class LocalFeedTaskSplitter
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(LocalFeedTaskSplitter.class);
|
||||
|
||||
private FeedTaskProcessor feedTaskProcessor;
|
||||
|
||||
public void setFeedTaskProcessor(FeedTaskProcessor feedTaskProcessor)
|
||||
{
|
||||
this.feedTaskProcessor = feedTaskProcessor;
|
||||
}
|
||||
|
||||
public Collection<FeedGridJob> split(int gridSize, Object o) throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
FeedTaskSplit feedSplitter = new FeedTaskSplit();
|
||||
Collection<JobSettings> jobs = feedSplitter.split(gridSize, (JobSettings)o);
|
||||
|
||||
List<FeedGridJob> gridJobs = new ArrayList<FeedGridJob>(jobs.size());
|
||||
for (JobSettings job : jobs)
|
||||
{
|
||||
LocalFeedGridJob gridJob = new LocalFeedGridJob();
|
||||
gridJob.setFeedTaskProcessor(feedTaskProcessor);
|
||||
gridJob.setArgument(job);
|
||||
gridJobs.add(gridJob);
|
||||
}
|
||||
return gridJobs;
|
||||
//return (Collection<FeedGridJob>)feedSplitter.split(gridSize, (JobSettings)o, new LocalFeedGridJob());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.equals(e);
|
||||
throw new Exception(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.ibatis;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Common interface for activity DAO service
|
||||
*/
|
||||
public interface ActivityDaoService
|
||||
{
|
||||
public void startTransaction() throws SQLException;
|
||||
|
||||
public void commitTransaction() throws SQLException;
|
||||
|
||||
public void endTransaction() throws SQLException;
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.ibatis;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.activities.feed.ActivityFeedDAO;
|
||||
import org.alfresco.repo.activities.feed.ActivityFeedDaoService;
|
||||
|
||||
public class IBatisActivityFeedDaoServiceImpl extends IBatisSqlMapper implements ActivityFeedDaoService
|
||||
{
|
||||
public long insertFeedEntry(ActivityFeedDAO activityFeed) throws SQLException
|
||||
{
|
||||
Long id = (Long)getSqlMapClient().insert("insert.activity.feed", activityFeed);
|
||||
return (id != null ? id : -1);
|
||||
}
|
||||
|
||||
public int deleteFeedEntries(Date keepDate) throws SQLException
|
||||
{
|
||||
return getSqlMapClient().delete("delete.activity.feed.entries.older.than.date", keepDate);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<ActivityFeedDAO> selectUserFeedEntries(String feedUserId, String format) throws SQLException
|
||||
{
|
||||
ActivityFeedDAO params = new ActivityFeedDAO();
|
||||
params.setFeedUserId(feedUserId);
|
||||
params.setActivitySummaryFormat(format);
|
||||
|
||||
// where feed user is me and post user is not me
|
||||
return (List<ActivityFeedDAO>)getSqlMapClient().queryForList("select.activity.feed.for.feeduser", params);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<ActivityFeedDAO> selectUserFeedEntries(String feedUserId, String format, String siteId) throws SQLException
|
||||
{
|
||||
ActivityFeedDAO params = new ActivityFeedDAO();
|
||||
params.setFeedUserId(feedUserId);
|
||||
params.setPostUserId(feedUserId);
|
||||
params.setActivitySummaryFormat(format);
|
||||
params.setSiteNetwork(siteId);
|
||||
|
||||
// where feed user is me and post user is not me
|
||||
return (List<ActivityFeedDAO>)getSqlMapClient().queryForList("select.activity.feed.for.feeduser.and.site", params);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<ActivityFeedDAO> selectSiteFeedEntries(String siteId, String format) throws SQLException
|
||||
{
|
||||
ActivityFeedDAO params = new ActivityFeedDAO();
|
||||
params.setSiteNetwork(siteId);
|
||||
params.setActivitySummaryFormat(format);
|
||||
|
||||
// where feed user is me and post user is not me
|
||||
return (List<ActivityFeedDAO>)getSqlMapClient().queryForList("select.activity.feed.for.site", params);
|
||||
}
|
||||
}
|
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.ibatis;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.activities.post.ActivityPostDAO;
|
||||
import org.alfresco.repo.activities.post.ActivityPostDaoService;
|
||||
|
||||
public class IBatisActivityPostDaoServiceImpl extends IBatisSqlMapper implements ActivityPostDaoService
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<ActivityPostDAO> selectPosts(ActivityPostDAO activityPost) throws SQLException
|
||||
{
|
||||
if ((activityPost.getJobTaskNode() != -1) &&
|
||||
(activityPost.getMinId() != -1) &&
|
||||
(activityPost.getMaxId() != -1) &&
|
||||
(activityPost.getStatus() != null))
|
||||
{
|
||||
return (List<ActivityPostDAO>)getSqlMapClient().queryForList("select.activity.posts", activityPost);
|
||||
}
|
||||
else if (activityPost.getStatus() != null)
|
||||
{
|
||||
return (List<ActivityPostDAO>)getSqlMapClient().queryForList("select.activity.posts.by.status.only", activityPost);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ArrayList<ActivityPostDAO>(0);
|
||||
}
|
||||
}
|
||||
|
||||
public Long getMaxActivitySeq() throws SQLException
|
||||
{
|
||||
return (Long)getSqlMapClient().queryForObject("select.activity.post.max.seq");
|
||||
}
|
||||
|
||||
public Long getMinActivitySeq() throws SQLException
|
||||
{
|
||||
return (Long)getSqlMapClient().queryForObject("select.activity.post.min.seq");
|
||||
}
|
||||
|
||||
public Integer getMaxNodeHash() throws SQLException
|
||||
{
|
||||
return (Integer)getSqlMapClient().queryForObject("select.activity.post.max.jobtasknode");
|
||||
}
|
||||
|
||||
public int updatePost(long id, String siteNetwork, String activityData, ActivityPostDAO.STATUS status) throws SQLException
|
||||
{
|
||||
ActivityPostDAO post = new ActivityPostDAO();
|
||||
post.setId(id);
|
||||
post.setSiteNetwork(siteNetwork);
|
||||
post.setActivityData(activityData);
|
||||
post.setStatus(status.toString());
|
||||
post.setLastModified(new Date());
|
||||
|
||||
return getSqlMapClient().update("update.activity.post.data", post);
|
||||
}
|
||||
|
||||
public int updatePostStatus(long id, ActivityPostDAO.STATUS status) throws SQLException
|
||||
{
|
||||
ActivityPostDAO post = new ActivityPostDAO();
|
||||
post.setId(id);
|
||||
post.setStatus(status.toString());
|
||||
post.setLastModified(new Date());
|
||||
|
||||
return getSqlMapClient().update("update.activity.post.status", post);
|
||||
}
|
||||
|
||||
public int deletePosts(Date keepDate, ActivityPostDAO.STATUS status) throws SQLException
|
||||
{
|
||||
ActivityPostDAO params = new ActivityPostDAO();
|
||||
params.setPostDate(keepDate);
|
||||
params.setStatus(status.toString());
|
||||
|
||||
return getSqlMapClient().delete("delete.activity.posts.older.than.date", params);
|
||||
}
|
||||
|
||||
public long insertPost(ActivityPostDAO activityPost) throws SQLException
|
||||
{
|
||||
Long id = (Long)getSqlMapClient().insert("insert.activity.post", activityPost);
|
||||
return (id != null ? id : -1);
|
||||
}
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.ibatis;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.activities.feed.control.FeedControlDAO;
|
||||
import org.alfresco.repo.activities.feed.control.FeedControlDaoService;
|
||||
|
||||
public class IBatisFeedControlDaoServiceImpl extends IBatisSqlMapper implements FeedControlDaoService
|
||||
{
|
||||
public long insertFeedControl(FeedControlDAO activityFeedControl) throws SQLException
|
||||
{
|
||||
Long id = (Long)getSqlMapClient().insert("insert.activity.feedcontrol", activityFeedControl);
|
||||
return (id != null ? id : -1);
|
||||
}
|
||||
|
||||
public int deleteFeedControl(FeedControlDAO activityFeedControl) throws SQLException
|
||||
{
|
||||
return getSqlMapClient().delete("delete.activity.feedcontrol", activityFeedControl);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<FeedControlDAO> selectFeedControls(String feedUserId) throws SQLException
|
||||
{
|
||||
FeedControlDAO params = new FeedControlDAO(feedUserId);
|
||||
|
||||
return (List<FeedControlDAO>)getSqlMapClient().queryForList("select.activity.feedcontrols.for.user", params);
|
||||
}
|
||||
|
||||
public long selectFeedControl(FeedControlDAO activityFeedControl) throws SQLException
|
||||
{
|
||||
Long id = (Long)getSqlMapClient().queryForObject("select.activity.feedcontrol", activityFeedControl);
|
||||
return (id != null ? id : -1);
|
||||
}
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.ibatis;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.ibatis.sqlmap.client.SqlMapClient;
|
||||
|
||||
public class IBatisSqlMapper implements ActivityDaoService
|
||||
{
|
||||
private SqlMapClient sqlMapper;
|
||||
|
||||
public void setSqlMapClient(SqlMapClient sqlMapper)
|
||||
{
|
||||
this.sqlMapper = sqlMapper;
|
||||
}
|
||||
|
||||
public SqlMapClient getSqlMapClient()
|
||||
{
|
||||
return this.sqlMapper;
|
||||
}
|
||||
|
||||
public void startTransaction() throws SQLException
|
||||
{
|
||||
sqlMapper.startTransaction();
|
||||
}
|
||||
|
||||
public void commitTransaction() throws SQLException
|
||||
{
|
||||
sqlMapper.commitTransaction();
|
||||
}
|
||||
|
||||
public void endTransaction() throws SQLException
|
||||
{
|
||||
sqlMapper.endTransaction();
|
||||
}
|
||||
}
|
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.post;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Activity Post DAO
|
||||
*/
|
||||
public class ActivityPostDAO
|
||||
{
|
||||
public enum STATUS { POSTED, PENDING, PROCESSED, ERROR };
|
||||
|
||||
private long id; // internal DB-generated sequence id
|
||||
private String activityData;
|
||||
private String activityType;
|
||||
private String userId;
|
||||
private int jobTaskNode = -1;
|
||||
private String siteNetwork;
|
||||
private String appTool;
|
||||
private String status;
|
||||
private Date postDate;
|
||||
private Date lastModified; // for debug
|
||||
|
||||
// for selector
|
||||
private long minId = -1;
|
||||
private long maxId = -1;
|
||||
|
||||
public long getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
public void setId(long id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUserId()
|
||||
{
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId)
|
||||
{
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public int getJobTaskNode()
|
||||
{
|
||||
return jobTaskNode;
|
||||
}
|
||||
|
||||
public void setJobTaskNode(int jobTaskNode)
|
||||
{
|
||||
this.jobTaskNode = jobTaskNode;
|
||||
}
|
||||
|
||||
public long getMinId()
|
||||
{
|
||||
return minId;
|
||||
}
|
||||
|
||||
public void setMinId(long minId)
|
||||
{
|
||||
this.minId = minId;
|
||||
}
|
||||
|
||||
public long getMaxId()
|
||||
{
|
||||
return maxId;
|
||||
}
|
||||
|
||||
public void setMaxId(long maxId)
|
||||
{
|
||||
this.maxId = maxId;
|
||||
}
|
||||
|
||||
public String getSiteNetwork()
|
||||
{
|
||||
return siteNetwork;
|
||||
}
|
||||
|
||||
public void setSiteNetwork(String siteNetwork)
|
||||
{
|
||||
this.siteNetwork = siteNetwork;
|
||||
}
|
||||
|
||||
public String getActivityData()
|
||||
{
|
||||
return activityData;
|
||||
}
|
||||
|
||||
public void setActivityData(String activityData)
|
||||
{
|
||||
this.activityData = activityData;
|
||||
}
|
||||
|
||||
public String getActivityType()
|
||||
{
|
||||
return activityType;
|
||||
}
|
||||
|
||||
public void setActivityType(String activityType)
|
||||
{
|
||||
this.activityType = activityType;
|
||||
}
|
||||
|
||||
public Date getPostDate()
|
||||
{
|
||||
return postDate;
|
||||
}
|
||||
|
||||
public void setPostDate(Date postDate)
|
||||
{
|
||||
this.postDate = postDate;
|
||||
}
|
||||
|
||||
public String getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status)
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Date getLastModified()
|
||||
{
|
||||
return lastModified;
|
||||
}
|
||||
|
||||
public void setLastModified(Date lastModified)
|
||||
{
|
||||
this.lastModified = lastModified;
|
||||
}
|
||||
|
||||
public String getAppTool()
|
||||
{
|
||||
return appTool;
|
||||
}
|
||||
|
||||
public void setAppTool(String appTool)
|
||||
{
|
||||
this.appTool = appTool;
|
||||
}
|
||||
|
||||
// for debug only
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("ActivityPost\n[");
|
||||
sb.append("id=").append(id).append(",");
|
||||
sb.append("status=").append(status).append(",");
|
||||
sb.append("postDate=").append(postDate).append(",");
|
||||
sb.append("userId=").append(userId).append(",");
|
||||
sb.append("siteNetwork=").append(siteNetwork).append(",");
|
||||
sb.append("appTool=").append(appTool).append(",");
|
||||
sb.append("type=").append(activityType).append(",");
|
||||
sb.append("jobTaskNode=").append(jobTaskNode).append(",");
|
||||
sb.append("data=\n").append(activityData).append("\n]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.post;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.activities.ibatis.ActivityDaoService;
|
||||
|
||||
/**
|
||||
* Interface for activity post DAO service
|
||||
*/
|
||||
public interface ActivityPostDaoService extends ActivityDaoService
|
||||
{
|
||||
public List<ActivityPostDAO> selectPosts(ActivityPostDAO activityPost) throws SQLException;
|
||||
|
||||
public Long getMaxActivitySeq() throws SQLException;
|
||||
|
||||
public Long getMinActivitySeq() throws SQLException;
|
||||
|
||||
public Integer getMaxNodeHash() throws SQLException;
|
||||
|
||||
public int deletePosts(Date keepDate, ActivityPostDAO.STATUS status) throws SQLException;
|
||||
|
||||
public long insertPost(ActivityPostDAO activityPost) throws SQLException;
|
||||
|
||||
public int updatePost(long id, String network, String activityData, ActivityPostDAO.STATUS status) throws SQLException;
|
||||
|
||||
public int updatePostStatus(long id, ActivityPostDAO.STATUS status) throws SQLException;
|
||||
}
|
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.post.cleanup;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.activities.post.ActivityPostDAO;
|
||||
import org.alfresco.repo.activities.post.ActivityPostDaoService;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.alfresco.util.VmShutdownListener;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
/**
|
||||
* Thr post cleaner component is responsible for purging 'obsolete' activity posts
|
||||
*/
|
||||
public class PostCleaner
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(PostCleaner.class);
|
||||
|
||||
private static VmShutdownListener vmShutdownListener = new VmShutdownListener(PostCleaner.class.getName());
|
||||
|
||||
private int maxAgeMins = 0;
|
||||
|
||||
private ActivityPostDaoService postDaoService;
|
||||
|
||||
public void setPostDaoService(ActivityPostDaoService postDaoService)
|
||||
{
|
||||
this.postDaoService = postDaoService;
|
||||
}
|
||||
|
||||
public void setMaxAgeMins(int mins)
|
||||
{
|
||||
this.maxAgeMins = mins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform basic checks to ensure that the necessary dependencies were injected.
|
||||
*/
|
||||
private void checkProperties()
|
||||
{
|
||||
PropertyCheck.mandatory(this, "postDaoService", postDaoService);
|
||||
|
||||
// check the max age
|
||||
if (maxAgeMins <= 0)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Property 'maxAgeMins' must be greater than 0");
|
||||
}
|
||||
}
|
||||
|
||||
public void execute() throws JobExecutionException
|
||||
{
|
||||
checkProperties();
|
||||
try
|
||||
{
|
||||
long nowTimeOffset = new Date().getTime();
|
||||
long keepTimeOffset = nowTimeOffset - (maxAgeMins*60*1000); // millsecs = mins * 60 secs * 1000 msecs
|
||||
Date keepDate = new Date(keepTimeOffset);
|
||||
|
||||
// clean old entries - PROCESSED - does not clean POSTED or PENDING, which will need to be done manually, if stuck
|
||||
int deletedCount = postDaoService.deletePosts(keepDate, ActivityPostDAO.STATUS.PROCESSED);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Cleaned " + deletedCount + " entries (upto " + keepDate + ", max age " + maxAgeMins + " mins)");
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
logger.error("Exception during cleanup of posts", e);
|
||||
throw new JobExecutionException(e);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// If the VM is shutting down, then ignore
|
||||
if (vmShutdownListener.isVmShuttingDown())
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.error("Exception during cleanup of posts", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.post.cleanup;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobDataMap;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
/**
|
||||
* Executes scheduled post cleaner quartz-job - refer to scheduled-jobs-context.xml
|
||||
*/
|
||||
public class PostCleanupJob implements Job
|
||||
{
|
||||
public PostCleanupJob()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the post cleaner to do its work
|
||||
*/
|
||||
public void execute(JobExecutionContext context) throws JobExecutionException
|
||||
{
|
||||
JobDataMap jobData = context.getJobDetail().getJobDataMap();
|
||||
// extract the post cleaner to use
|
||||
Object postCleanerObj = jobData.get("postCleaner");
|
||||
if (postCleanerObj == null || !(postCleanerObj instanceof PostCleaner))
|
||||
{
|
||||
throw new AlfrescoRuntimeException(
|
||||
"FeedCleanupJob data must contain valid 'postCleaner' reference");
|
||||
}
|
||||
PostCleaner postCleaner = (PostCleaner)postCleanerObj;
|
||||
postCleaner.execute();
|
||||
}
|
||||
}
|
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.post.lookup;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.activities.post.ActivityPostDAO;
|
||||
import org.alfresco.repo.activities.post.ActivityPostDaoService;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.Path;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.JSONtoFmModel;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.alfresco.util.VmShutdownListener;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONStringer;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
/**
|
||||
* The post lookup component is responsible for updating posts that require a secondary lookup (to get additional activity data)
|
||||
*/
|
||||
public class PostLookup
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(PostLookup.class);
|
||||
|
||||
private static VmShutdownListener vmShutdownListener = new VmShutdownListener(PostLookup.class.getName());
|
||||
|
||||
private ActivityPostDaoService postDaoService;
|
||||
private NodeService nodeService;
|
||||
private PermissionService permissionService;
|
||||
private TransactionService transactionService;
|
||||
private PersonService personService;
|
||||
|
||||
public void setPostDaoService(ActivityPostDaoService postDaoService)
|
||||
{
|
||||
this.postDaoService = postDaoService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setPermissionService(PermissionService permissionService)
|
||||
{
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
public void setTransactionService(TransactionService transactionService)
|
||||
{
|
||||
this.transactionService = transactionService;
|
||||
}
|
||||
|
||||
public void setPersonService(PersonService personService)
|
||||
{
|
||||
this.personService = personService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform basic checks to ensure that the necessary dependencies were injected.
|
||||
*/
|
||||
private void checkProperties()
|
||||
{
|
||||
PropertyCheck.mandatory(this, "postDaoService", postDaoService);
|
||||
PropertyCheck.mandatory(this, "nodeService", nodeService);
|
||||
PropertyCheck.mandatory(this, "permissionService", permissionService);
|
||||
PropertyCheck.mandatory(this, "transactionService", transactionService);
|
||||
PropertyCheck.mandatory(this, "personService", personService);
|
||||
}
|
||||
|
||||
public void execute() throws JobExecutionException
|
||||
{
|
||||
checkProperties();
|
||||
try
|
||||
{
|
||||
ActivityPostDAO params = new ActivityPostDAO();
|
||||
params.setStatus(ActivityPostDAO.STATUS.PENDING.toString());
|
||||
|
||||
List<ActivityPostDAO> activityPosts = postDaoService.selectPosts(params);
|
||||
|
||||
if (activityPosts.size() > 0)
|
||||
{
|
||||
logger.info("Update: " + activityPosts.size() + " activity posts");
|
||||
}
|
||||
|
||||
for (ActivityPostDAO activityPost : activityPosts)
|
||||
{
|
||||
Map<String, Object> model = JSONtoFmModel.convertJSONObjectToMap(activityPost.getActivityData());
|
||||
|
||||
String postUserId = activityPost.getUserId();
|
||||
|
||||
String name = (String)model.get("name"); // can be null
|
||||
|
||||
String nodeRefStr = (String)model.get("nodeRef"); // required
|
||||
NodeRef nodeRef = new NodeRef(nodeRefStr);
|
||||
|
||||
String parentNodeRefStr = (String)model.get("parentNodeRef"); // optional
|
||||
NodeRef parentNodeRef = null;
|
||||
if (parentNodeRefStr != null)
|
||||
{
|
||||
parentNodeRef = new NodeRef(parentNodeRefStr);
|
||||
}
|
||||
|
||||
String typeQName = (String)model.get("typeQName");
|
||||
|
||||
try
|
||||
{
|
||||
postDaoService.startTransaction();
|
||||
|
||||
Pair<String, String> siteNetworkActivityData = lookup(activityPost.getSiteNetwork(), nodeRef, name, typeQName, parentNodeRef, postUserId);
|
||||
|
||||
activityPost.setSiteNetwork(siteNetworkActivityData.getFirst());
|
||||
activityPost.setActivityData(siteNetworkActivityData.getSecond());
|
||||
activityPost.setLastModified(new Date());
|
||||
|
||||
postDaoService.updatePost(activityPost.getId(), activityPost.getSiteNetwork(), activityPost.getActivityData(), ActivityPostDAO.STATUS.POSTED);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
activityPost.setStatus(ActivityPostDAO.STATUS.POSTED.toString()); // for debug output
|
||||
logger.debug("Updated: " + activityPost);
|
||||
}
|
||||
|
||||
postDaoService.commitTransaction();
|
||||
}
|
||||
catch (JSONException e)
|
||||
{
|
||||
// log error, but consume exception (skip this post)
|
||||
logger.error(e);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
logger.error("Exception during update of post", e);
|
||||
throw new JobExecutionException(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
postDaoService.endTransaction();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
logger.error("Exception during select of posts", e);
|
||||
throw new JobExecutionException(e);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// If the VM is shutting down, then ignore
|
||||
if (vmShutdownListener.isVmShuttingDown())
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.error("Exception during update of posts", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Pair<String, String> lookup(final String networkIn, final NodeRef nodeRef, final String nameIn, final String typeQNameIn, final NodeRef parentNodeRef, final String postUserId) throws JSONException
|
||||
{
|
||||
return AuthenticationUtil.runAs(new RunAsWork<Pair<String, String>>()
|
||||
{
|
||||
public Pair<String, String> doWork() throws Exception
|
||||
{
|
||||
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
|
||||
|
||||
// wrap to make the request in a transaction
|
||||
RetryingTransactionCallback<Pair<String, String>> lookup = new RetryingTransactionCallback<Pair<String, String>>()
|
||||
{
|
||||
public Pair<String, String> execute() throws Throwable
|
||||
{
|
||||
String jsonString = null;
|
||||
String displayPath = "";
|
||||
String name = nameIn;
|
||||
String network = networkIn;
|
||||
String typeQName = typeQNameIn;
|
||||
Path path = null;
|
||||
String firstName = "";
|
||||
String lastName = "";
|
||||
|
||||
if (personService.personExists(postUserId))
|
||||
{
|
||||
NodeRef personRef = personService.getPerson(postUserId);
|
||||
|
||||
firstName = (String)nodeService.getProperty(personRef, ContentModel.PROP_FIRSTNAME);
|
||||
lastName = (String)nodeService.getProperty(personRef, ContentModel.PROP_LASTNAME);
|
||||
}
|
||||
|
||||
if (((name == null) || (name.length() == 0)) && (nodeRef != null) && (nodeService.exists(nodeRef)))
|
||||
{
|
||||
// node exists, lookup node name
|
||||
if ((name == null) || (name.length() == 0))
|
||||
{
|
||||
name = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||
}
|
||||
|
||||
path = nodeService.getPath(nodeRef);
|
||||
|
||||
// TODO: missing the prefix ?
|
||||
typeQName = nodeService.getType(nodeRef).toPrefixString();
|
||||
}
|
||||
|
||||
if (((path == null) || (path.size() == 0)) && (parentNodeRef != null) && (nodeService.exists(parentNodeRef)))
|
||||
{
|
||||
// parent node exists, lookup parent node path
|
||||
path = nodeService.getPath(parentNodeRef);
|
||||
}
|
||||
|
||||
|
||||
if (path != null)
|
||||
{
|
||||
// lookup display path
|
||||
displayPath = path.toDisplayPath(nodeService, permissionService);
|
||||
|
||||
// note: for now, also tack on the node name
|
||||
displayPath += "/" + name;
|
||||
}
|
||||
|
||||
if (name == null)
|
||||
{
|
||||
name = "";
|
||||
}
|
||||
|
||||
if (typeQName == null)
|
||||
{
|
||||
typeQName = "";
|
||||
}
|
||||
|
||||
// activity data
|
||||
jsonString = new JSONStringer()
|
||||
.object()
|
||||
.key("name")
|
||||
.value(name)
|
||||
.key("nodeRef")
|
||||
.value(nodeRef)
|
||||
.key("typeQName")
|
||||
.value(typeQName)
|
||||
.key("displayPath")
|
||||
.value(displayPath)
|
||||
.key("firstName")
|
||||
.value(firstName)
|
||||
.key("lastName")
|
||||
.value(lastName)
|
||||
.endObject().toString();
|
||||
|
||||
return new Pair<String, String>(network, jsonString);
|
||||
}
|
||||
};
|
||||
|
||||
// execute in txn
|
||||
return txnHelper.doInTransaction(lookup, true);
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 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.post.lookup;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobDataMap;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
/**
|
||||
* Executes scheduled post lookup quartz-job - refer to scheduled-jobs-context.xml
|
||||
*/
|
||||
public class PostLookupJob implements Job
|
||||
{
|
||||
public PostLookupJob()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the post lookup to do its work
|
||||
*/
|
||||
public void execute(JobExecutionContext context) throws JobExecutionException
|
||||
{
|
||||
JobDataMap jobData = context.getJobDetail().getJobDataMap();
|
||||
// extract the post cleaner to use
|
||||
Object postLookupObj = jobData.get("postLookup");
|
||||
if (postLookupObj == null || !(postLookupObj instanceof PostLookup))
|
||||
{
|
||||
throw new AlfrescoRuntimeException(
|
||||
"FeedCleanupJob data must contain valid 'postLookup' reference");
|
||||
}
|
||||
PostLookup postLookup = (PostLookup)postLookupObj;
|
||||
postLookup.execute();
|
||||
}
|
||||
}
|
111
source/java/org/alfresco/repo/activities/script/Activity.java
Normal file
111
source/java/org/alfresco/repo/activities/script/Activity.java
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 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.script;
|
||||
|
||||
import org.alfresco.repo.jscript.BaseScopableProcessorExtension;
|
||||
import org.alfresco.service.cmr.activities.ActivityService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Scripted Activity Service for posting activities.
|
||||
*/
|
||||
|
||||
public final class Activity extends BaseScopableProcessorExtension
|
||||
{
|
||||
private ActivityService activityService;
|
||||
|
||||
/**
|
||||
* Set the activity service
|
||||
*
|
||||
* @param activityService the activity service
|
||||
*/
|
||||
public void setActivityService(ActivityService activityService)
|
||||
{
|
||||
this.activityService = activityService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post a custom activity type
|
||||
*
|
||||
* @param activityType - required
|
||||
* @param siteId - optional, if null will be stored as empty string
|
||||
* @param appTool - optional, if null will be stored as empty string
|
||||
* @param jsonActivityData - required
|
||||
*/
|
||||
public void postActivity(String activityType, String siteId, String appTool, String jsonActivityData)
|
||||
{
|
||||
activityService.postActivity(activityType, siteId, appTool, jsonActivityData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post a pre-defined activity type - activity data will be looked-up asynchronously, including:
|
||||
*
|
||||
* name
|
||||
* displayPath
|
||||
* typeQName
|
||||
* firstName (of posting user)
|
||||
* lastName (of posting user)
|
||||
*
|
||||
* @param activityType - required
|
||||
* @param siteId - optional, if null will be stored as empty string
|
||||
* @param appTool - optional, if null will be stored as empty string
|
||||
* @param nodeRef - required - do not use for deleted (or about to be deleted) nodeRef
|
||||
*/
|
||||
public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef)
|
||||
{
|
||||
activityService.postActivity(activityType, siteId, appTool, nodeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post a pre-defined activity type - eg. for checked-out nodeRef or renamed nodeRef
|
||||
*
|
||||
* @param activityType - required
|
||||
* @param siteId - optional, if null will be stored as empty string
|
||||
* @param appTool - optional, if null will be stored as empty string
|
||||
* @param nodeRef - required - do not use deleted (or about to be deleted) nodeRef
|
||||
* @param beforeName - optional - name of node (eg. prior to name change)
|
||||
*/
|
||||
public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef, String beforeName)
|
||||
{
|
||||
activityService.postActivity(activityType, siteId, appTool, nodeRef, beforeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post a pre-defined activity type - eg. for deleted nodeRef
|
||||
*
|
||||
* @param activityType - required
|
||||
* @param siteId - optional, if null will be stored as empty string
|
||||
* @param appTool - optional, if null will be stored as empty string
|
||||
* @param nodeRef - required - can be a deleted (or about to be deleted) nodeRef
|
||||
* @param name - optional - name of name
|
||||
* @param typeQName - optional - type of node
|
||||
* @param parentNodeRef - required - used to lookup path/displayPath
|
||||
*/
|
||||
public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef, String name, QName typeQName, NodeRef parentNodeRef)
|
||||
{
|
||||
activityService.postActivity(activityType, siteId, appTool, nodeRef, name, typeQName, parentNodeRef);
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
// called by ActivityServiceImplTest.java (test_JSAPI)
|
||||
|
||||
var failure = "did not complete script";
|
||||
|
||||
// invalid
|
||||
// activities.postActivity("my activity type", null, null, null);
|
||||
// activities.postActivity(null, "my site", "my app tool", '{ 000 }');
|
||||
|
||||
// valid
|
||||
activities.postActivity("test activity type 4", null, null, '{ "item1" : 123 }');
|
||||
activities.postActivity("test activity type 5", "my site", null, '{ "item2" : 456 }');
|
||||
activities.postActivity("test activity type 6", "my site", "my app tool", '{ "item3" : 789 }');
|
||||
activities.postActivity("test activity type 7", "my site", "my app tool", '{ invalidJSON }');
|
||||
|
||||
|
||||
failure = "";
|
||||
|
||||
// Return the failure message
|
||||
failure;
|
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.service.cmr.activities;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
public interface ActivityService
|
||||
{
|
||||
|
||||
/*
|
||||
* Post Activity
|
||||
*/
|
||||
|
||||
/**
|
||||
* Post a custom activity type
|
||||
*
|
||||
* @param activityType - required
|
||||
* @param siteId - optional, if null will be stored as empty string
|
||||
* @param appTool - optional, if null will be stored as empty string
|
||||
* @param jsonActivityData - required
|
||||
*/
|
||||
public void postActivity(String activityType, String siteId, String appTool, String jsonActivityData);
|
||||
|
||||
/**
|
||||
* Post a pre-defined activity type - certain activity data will be looked-up asynchronously, including:
|
||||
*
|
||||
* name (of nodeRef)
|
||||
* displayPath
|
||||
* typeQName
|
||||
* firstName (of posting user)
|
||||
* lastName (of posting user)
|
||||
*
|
||||
* @param activityType - required
|
||||
* @param siteId - optional, if null will be stored as empty string
|
||||
* @param appTool - optional, if null will be stored as empty string
|
||||
* @param nodeRef - required - do not use for deleted (or about to be deleted) nodeRef
|
||||
*/
|
||||
public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef);
|
||||
|
||||
/**
|
||||
* Post a pre-defined activity type - eg. for checked-out nodeRef or renamed nodeRef
|
||||
*
|
||||
* @param activityType - required
|
||||
* @param siteId - optional, if null will be stored as empty string
|
||||
* @param appTool - optional, if null will be stored as empty string
|
||||
* @param nodeRef - required - do not use deleted (or about to be deleted) nodeRef
|
||||
* @param beforeName - optional - name of node (eg. prior to name change)
|
||||
*/
|
||||
public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef, String beforeName);
|
||||
|
||||
/**
|
||||
* Post a pre-defined activity type - eg. for deleted nodeRef
|
||||
*
|
||||
* @param activityType - required
|
||||
* @param siteId - optional, if null will be stored as empty string
|
||||
* @param appTool - optional, if null will be stored as empty string
|
||||
* @param nodeRef - required - can be a deleted (or about to be deleted) nodeRef
|
||||
* @param name - optional - name of name
|
||||
* @param typeQName - optional - type of node
|
||||
* @param parentNodeRef - required - used to lookup path/displayPath
|
||||
*/
|
||||
public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef, String name, QName typeQName, NodeRef parentNodeRef);
|
||||
|
||||
|
||||
/*
|
||||
* Retrieve Feed Entries
|
||||
*/
|
||||
|
||||
/**
|
||||
* Retrieve user feed
|
||||
*
|
||||
* @param userId - required
|
||||
* @param format - required
|
||||
* @param siteId - optional, if set then will filter by given siteId else return all sites
|
||||
*/
|
||||
public List<Map<String, Object>> getUserFeedEntries(String userId, String format, String siteId);
|
||||
|
||||
/**
|
||||
* Retrieve site feed
|
||||
*
|
||||
* @param activityType - required
|
||||
* @param format - required
|
||||
*/
|
||||
public List<Map<String, Object>> getSiteFeedEntries(String siteId, String format);
|
||||
|
||||
|
||||
/*
|
||||
* Manage User Feed Controls
|
||||
*/
|
||||
|
||||
/**
|
||||
* For current user, set feed control (opt-out) for a site or an appTool or a site/appTool
|
||||
*
|
||||
* @param feedControl - required
|
||||
*/
|
||||
public void setFeedControl(FeedControl feedControl);
|
||||
|
||||
/**
|
||||
* For given user, get feed controls
|
||||
*
|
||||
* @param userId - required (must match
|
||||
* @return list of user feed controls
|
||||
*/
|
||||
public List<FeedControl> getFeedControls(String userId);
|
||||
|
||||
/**
|
||||
* For current user, get feed controls
|
||||
*
|
||||
* @return list of user feed controls
|
||||
*/
|
||||
public List<FeedControl> getFeedControls();
|
||||
|
||||
/**
|
||||
* For current user, unset feed control
|
||||
*
|
||||
* @param feedControl - required
|
||||
*/
|
||||
public void unsetFeedControl(FeedControl feedControl);
|
||||
|
||||
/**
|
||||
* For current user, does the feed control exist ?
|
||||
*
|
||||
* @param feedControl - required
|
||||
* @return true, if user feed control exists
|
||||
*/
|
||||
public boolean existsFeedControl(FeedControl feedControl);
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.service.cmr.activities;
|
||||
|
||||
public class FeedControl
|
||||
{
|
||||
private String siteId;
|
||||
private String appToolId;
|
||||
|
||||
public FeedControl(String siteId, String appToolId)
|
||||
{
|
||||
if (siteId == null) siteId = "";
|
||||
this.siteId = siteId;
|
||||
|
||||
if (appToolId == null) appToolId = "";
|
||||
this.appToolId = appToolId;
|
||||
}
|
||||
|
||||
public String getSiteId()
|
||||
{
|
||||
return this.siteId;
|
||||
}
|
||||
|
||||
public String getAppToolId()
|
||||
{
|
||||
return this.appToolId;
|
||||
}
|
||||
}
|
@@ -95,6 +95,10 @@ public abstract class BaseSpringTest extends AbstractTransactionalDataSourceSpri
|
||||
{
|
||||
// The derived class is using the default context
|
||||
defaultContext = true;
|
||||
|
||||
this.setAutowireMode(AUTOWIRE_BY_NAME);
|
||||
//this.setDependencyCheck(false);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Getting config locations");
|
||||
|
Reference in New Issue
Block a user