mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged BRANCHES/DEV/WF-NOTIFICATION to HEAD:
29508: Workflow Notification - First Cut * Notification service to consolidate sending of user notifications (kinds of notifications are provided by Sprung in notification providers) * EMail notification provider implementation (uses standard Email action to send email) * Frist cut workflow email template (still needs lots of details added) * AMP, etc for email template * Hook point within Activit and JBMP implementations * Property added to model (startTask) indicating whether email notifications should be sent * Hook points sensitive to property * Wf forms updated to show property 29703: Workflow Notification: * Remove AMP and replace with exploded XMl and template (easier to maintain) * Bootstrap updated * Patch added * Refactored hooks to use generic workflowTask object (tidies up helper methods) * I18n'ed messages * Task and work package information placed in template model * Email template built with reference to Lintons wire's (still needs some polish!) * Added Notification Servcice to Service Registry git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@29705 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -166,6 +166,7 @@
|
|||||||
class="org.alfresco.repo.workflow.activiti.tasklistener.TaskCreateListener"
|
class="org.alfresco.repo.workflow.activiti.tasklistener.TaskCreateListener"
|
||||||
depends-on="activitiWorkflowManager">
|
depends-on="activitiWorkflowManager">
|
||||||
<property name="propertyConverter" ref="activitiPropertyConverter" />
|
<property name="propertyConverter" ref="activitiPropertyConverter" />
|
||||||
|
<property name="services" ref="ServiceRegistry" />
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="activitiRepositoryService" factory-bean="activitiProcessEngine"
|
<bean id="activitiRepositoryService" factory-bean="activitiProcessEngine"
|
||||||
|
@@ -39,6 +39,7 @@
|
|||||||
<import resource="classpath:alfresco/attributes-service-context.xml"/>
|
<import resource="classpath:alfresco/attributes-service-context.xml"/>
|
||||||
<import resource="classpath:alfresco/deployment-service-context.xml"/>
|
<import resource="classpath:alfresco/deployment-service-context.xml"/>
|
||||||
<import resource="classpath:alfresco/site-services-context.xml"/>
|
<import resource="classpath:alfresco/site-services-context.xml"/>
|
||||||
|
<import resource="classpath:alfresco/notification-services-context.xml"/>
|
||||||
<import resource="classpath:alfresco/activities/activities-feed-context.xml" />
|
<import resource="classpath:alfresco/activities/activities-feed-context.xml" />
|
||||||
<import resource="classpath:alfresco/tagging-services-context.xml"/>
|
<import resource="classpath:alfresco/tagging-services-context.xml"/>
|
||||||
<import resource="classpath:alfresco/invitation-service-context.xml"/>
|
<import resource="classpath:alfresco/invitation-service-context.xml"/>
|
||||||
|
144
config/alfresco/bootstrap/notification/wf-email.html.ftl
Normal file
144
config/alfresco/bootstrap/notification/wf-email.html.ftl
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<style type="text/css"><!--
|
||||||
|
body
|
||||||
|
{
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #4c4c4c;
|
||||||
|
}
|
||||||
|
|
||||||
|
a, a:visited
|
||||||
|
{
|
||||||
|
color: #0072cf;
|
||||||
|
}
|
||||||
|
--></style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#dddddd">
|
||||||
|
<table width="100%" cellpadding="20" cellspacing="0" border="0" bgcolor="#dddddd">
|
||||||
|
<tr>
|
||||||
|
<td width="100%" align="center">
|
||||||
|
<table width="70%" cellpadding="0" cellspacing="0" bgcolor="white" style="background-color: white; border: 1px solid #aaaaaa;">
|
||||||
|
<tr>
|
||||||
|
<td width="100%">
|
||||||
|
<table width="100%" cellpadding="0" cellspacing="0" border="0">
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 10px 30px 0px;">
|
||||||
|
<table width="100%" cellpadding="0" cellspacing="0" border="0">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table cellpadding="0" cellspacing="0" border="0">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<img src="${shareUrl}/res/components/images/task-64.png" alt="" width="64" height="64" border="0" style="padding-right: 20px;" />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div style="font-size: 22px; padding-bottom: 4px;">
|
||||||
|
<#if args.workflowPooled == true>
|
||||||
|
New Pooled Task
|
||||||
|
<#else>
|
||||||
|
You been assigned a task
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
<div style="font-size: 13px;">
|
||||||
|
${date?datetime?string.full}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div style="font-size: 14px; margin: 12px 0px 24px 0px; padding-top: 10px; border-top: 1px solid #aaaaaa;">
|
||||||
|
<p>Hi,</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<#if args.workflowPooled == true>
|
||||||
|
The following pooled task is available to be claimed:
|
||||||
|
<#else>
|
||||||
|
You have been assigned the following task:
|
||||||
|
</#if>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><b>"${args.workflowDescription}"</b></p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<#if (args.workflowDueDate)??>Due: <b>${args.workflowDueDate?date?string.full}</b><br></#if>
|
||||||
|
<#if (args.workflowPriority)??>
|
||||||
|
Priority:
|
||||||
|
<b>
|
||||||
|
<#if args.workflowPriority == 3>
|
||||||
|
Low
|
||||||
|
<#elseif args.workflowPriority == 2>
|
||||||
|
Medium
|
||||||
|
<#else>
|
||||||
|
High
|
||||||
|
</#if>
|
||||||
|
</b>
|
||||||
|
</#if>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<#if (args.workflowDocuments)??>
|
||||||
|
<table cellpadding=0 callspacing=0 border=0>
|
||||||
|
<#list args.workflowDocuments as doc>
|
||||||
|
<tr><td><table cellpadding=0 cellspacing=0 border=0><tr>
|
||||||
|
<td><img src="${shareUrl}/res/components/images/generic-file.png" alt="" width="64" height="64" border="0" style="padding-right: 20px;" /></td>
|
||||||
|
<td><table cellpadding=0 cellspacing=0 border=0>
|
||||||
|
<tr><td><b>${doc.name}</b></td></tr>
|
||||||
|
<tr><td>Click on this link to download the document:</td></tr>
|
||||||
|
<tr><td>
|
||||||
|
<a href="${shareUrl}/proxy/alfresco/api/node/content/workspace/SpacesStore/${doc.id}/${doc.name}?a=true">
|
||||||
|
${shareUrl}/proxy/alfresco/api/node/content/workspace/SpacesStore/${doc.id}/${doc.name}?a=true
|
||||||
|
</a>
|
||||||
|
</td></tr>
|
||||||
|
</table></td>
|
||||||
|
</tr></table></td></tr>
|
||||||
|
</#list>
|
||||||
|
</table>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if args.workflowPooled == true>
|
||||||
|
<p>Click this link to view the task:</p>
|
||||||
|
<p><a href="${shareUrl}/page/task-view?taskId=${args.workflowId}">${shareUrl}/page/task-view?taskId=${args.workflowId}</a>
|
||||||
|
<#else>
|
||||||
|
<p>Click this link to edit the task:</p>
|
||||||
|
<p><a href="${shareUrl}/page/task-details?taskId=${args.workflowId}">${shareUrl}/page/task-edit?taskId=${args.workflowId}</a>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<p>Sincerely,<br />
|
||||||
|
Alfresco ${productName!""}</p>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div style="border-top: 1px solid #aaaaaa;"> </div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 0px 30px; font-size: 13px;">
|
||||||
|
To find out more about Alfresco ${productName!""} visit <a href="http://www.alfresco.com">http://www.alfresco.com</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div style="border-bottom: 1px solid #aaaaaa;"> </div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 10px 30px;">
|
||||||
|
<img src="${shareUrl}/themes/default/images/app-logo.png" alt="" width="117" height="48" border="0" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
@@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<view:view xmlns:view="http://www.alfresco.org/view/repository/1.0"
|
||||||
|
xmlns:app="http://www.alfresco.org/model/application/1.0"
|
||||||
|
xmlns:cm="http://www.alfresco.org/model/content/1.0"
|
||||||
|
xmlns:sys="http://www.alfresco.org/model/system/1.0">
|
||||||
|
<cm:folder view:childName="cm:workflownotification">
|
||||||
|
<view:aspects>
|
||||||
|
<app:uifacets></app:uifacets>
|
||||||
|
</view:aspects>
|
||||||
|
<view:properties>
|
||||||
|
<cm:description>${spaces.templates.email.workflowNotification.description}</cm:description>
|
||||||
|
<app:icon>space-icon-default</app:icon>
|
||||||
|
<cm:title>${spaces.templates.email.workflowNotification.name}</cm:title>
|
||||||
|
<cm:name>${spaces.templates.email.workflowNotification.name}</cm:name>
|
||||||
|
</view:properties>
|
||||||
|
<view:associations>
|
||||||
|
<cm:contains>
|
||||||
|
<cm:content view:childName="cm:invite-email.html.ftl">
|
||||||
|
<view:aspects>
|
||||||
|
<cm:auditable></cm:auditable>
|
||||||
|
<sys:referenceable></sys:referenceable>
|
||||||
|
<app:inlineeditable></app:inlineeditable>
|
||||||
|
</view:aspects>
|
||||||
|
<view:acl></view:acl>
|
||||||
|
<view:properties>
|
||||||
|
<app:editInline>true</app:editInline>
|
||||||
|
<sys:store-protocol>workspace</sys:store-protocol>
|
||||||
|
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||||
|
<sys:node-uuid>wf-email-html-ftl</sys:node-uuid>
|
||||||
|
<cm:name>wf-email.html.ftl</cm:name>
|
||||||
|
<cm:title>wf-email.html.ftl</cm:title>
|
||||||
|
<cm:description>${spaces.templates.email.generate_the_wf_notification_email.description} - ${version.default}</cm:description>
|
||||||
|
<cm:content>contentUrl=classpath:alfresco\bootstrap\notification\wf-email.html.ftl|mimetype=text/plain|size=1455|encoding=UTF-8</cm:content>
|
||||||
|
</view:properties>
|
||||||
|
</cm:content>
|
||||||
|
</cm:contains>
|
||||||
|
</view:associations>
|
||||||
|
</cm:folder>
|
||||||
|
</view:view>
|
@@ -531,6 +531,11 @@
|
|||||||
<prop key="location">alfresco/templates/following-email-templates.acp</prop>
|
<prop key="location">alfresco/templates/following-email-templates.acp</prop>
|
||||||
<prop key="messages">alfresco/messages/bootstrap-spaces</prop>
|
<prop key="messages">alfresco/messages/bootstrap-spaces</prop>
|
||||||
</props>
|
</props>
|
||||||
|
<props>
|
||||||
|
<prop key="path">/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.templates.email.childname}</prop>
|
||||||
|
<prop key="location">alfresco/bootstrap/notification/workflow-email-notification.xml</prop>
|
||||||
|
<prop key="messages">alfresco/messages/bootstrap-spaces</prop>
|
||||||
|
</props>
|
||||||
<props>
|
<props>
|
||||||
<prop key="path">/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.templates.rss.childname}</prop>
|
<prop key="path">/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.templates.rss.childname}</prop>
|
||||||
<prop key="location">alfresco/templates/rss_templates.acp</prop>
|
<prop key="location">alfresco/templates/rss_templates.acp</prop>
|
||||||
|
@@ -93,6 +93,8 @@ spaces.templates.email.notify.description=Notify Email Templates
|
|||||||
|
|
||||||
spaces.templates.email.generate_the_invite_email.description=Email template used to generate the invite email for Alfresco Share
|
spaces.templates.email.generate_the_invite_email.description=Email template used to generate the invite email for Alfresco Share
|
||||||
|
|
||||||
|
spaces.templates.email.generate_the_wf_notification_email.description=Email template for notifying users of new a workflow task
|
||||||
|
|
||||||
email.template.email_template_for_notifying_users=Email template for notifying users from a rule or action
|
email.template.email_template_for_notifying_users=Email template for notifying users from a rule or action
|
||||||
|
|
||||||
email.template.email_template_for_notifying_users.sample=Sample Email template for notifying users from a rule or action
|
email.template.email_template_for_notifying_users.sample=Sample Email template for notifying users from a rule or action
|
||||||
@@ -152,3 +154,6 @@ spaces.transfer_temp.description=Folder to store temporary nodes during transfer
|
|||||||
spaces.inbound_transfer_records.name=Inbound Transfer Records
|
spaces.inbound_transfer_records.name=Inbound Transfer Records
|
||||||
spaces.inbound_transfer_records.title=Inbound Transfer Records
|
spaces.inbound_transfer_records.title=Inbound Transfer Records
|
||||||
spaces.inbound_transfer_records.description=Folder containing records of inbound transfers
|
spaces.inbound_transfer_records.description=Folder containing records of inbound transfers
|
||||||
|
|
||||||
|
spaces.templates.email.workflowNotification.name=Workflow Notification
|
||||||
|
spaces.templates.email.workflowNotification.description=Workflow notification email templates
|
@@ -62,6 +62,8 @@ bpm_businessprocessmodel.property.bpm_workflowDueDate.title=Workflow Due Date
|
|||||||
bpm_businessprocessmodel.property.bpm_workflowDueDate.description=Workflow Due Date
|
bpm_businessprocessmodel.property.bpm_workflowDueDate.description=Workflow Due Date
|
||||||
bpm_businessprocessmodel.property.bpm_workflowPriority.title=Workflow Priority
|
bpm_businessprocessmodel.property.bpm_workflowPriority.title=Workflow Priority
|
||||||
bpm_businessprocessmodel.property.bpm_workflowPriority.description=Workflow Priority
|
bpm_businessprocessmodel.property.bpm_workflowPriority.description=Workflow Priority
|
||||||
|
bpm_businessprocessmodel.property.bpm_sendEMailNotifications.title=Send EMail Notifications
|
||||||
|
bpm_businessprocessmodel.property.bpm_sendEMailNotifications.description=Send EMail Notifications
|
||||||
bpm_businessprocessmodel.association.bpm_assignee.title=Workflow Assignee
|
bpm_businessprocessmodel.association.bpm_assignee.title=Workflow Assignee
|
||||||
bpm_businessprocessmodel.association.bpm_assignee.description=Workflow Assignee
|
bpm_businessprocessmodel.association.bpm_assignee.description=Workflow Assignee
|
||||||
bpm_businessprocessmodel.association.bpm_assignees.title=Workflow Assignees
|
bpm_businessprocessmodel.association.bpm_assignees.title=Workflow Assignees
|
||||||
|
7
config/alfresco/messages/notification-service.properties
Normal file
7
config/alfresco/messages/notification-service.properties
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Notification Service externalised display strings
|
||||||
|
np-does-not-exist=Unable to send notification, because notification provider {0} does not exist.
|
||||||
|
default-sender-used=Sender of email notification has no email set, default sender will be used. (user={0})
|
||||||
|
no-recipients=Unable to send email notification, because no recipients where provided. (document={0})
|
||||||
|
no-body-or-template=Unable to send notification, because no body or body template where specified. (node={0})
|
||||||
|
assigned-task=You have been assigned a task
|
||||||
|
new-pooled-task=New Pooled Task
|
@@ -422,3 +422,5 @@ patch.avmToAdmRemoteStore.complete=Completed Share Surf config migration.
|
|||||||
|
|
||||||
patch.copiedFromAspect.description=Adds peer associations for cm:copiedfrom and cm:workingcopy (new model) and removes cm:source property
|
patch.copiedFromAspect.description=Adds peer associations for cm:copiedfrom and cm:workingcopy (new model) and removes cm:source property
|
||||||
patch.copiedFromAspect.result=Fixed cm:copiedfrom model for {0} nodes. See file {1} for details.
|
patch.copiedFromAspect.result=Fixed cm:copiedfrom model for {0} nodes. See file {1} for details.
|
||||||
|
|
||||||
|
patch.workflowNotification.description=Patch to add workflow email notification email folder and template.
|
@@ -307,12 +307,17 @@
|
|||||||
|
|
||||||
<!-- Priority for the workflow as a whole -->
|
<!-- Priority for the workflow as a whole -->
|
||||||
<property name="bpm:workflowPriority">
|
<property name="bpm:workflowPriority">
|
||||||
<type>d:int</type>
|
<type>d:int</type>RW
|
||||||
<default>2</default>
|
<default>2</default>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint ref="bpm:allowedPriority" />
|
<constraint ref="bpm:allowedPriority" />
|
||||||
</constraints>
|
</constraints>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
|
<property name="bpm:sendEMailNotifications">
|
||||||
|
<type>d:boolean</type>
|
||||||
|
<default>false</default>
|
||||||
|
</property>
|
||||||
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
63
config/alfresco/notification-services-context.xml
Normal file
63
config/alfresco/notification-services-context.xml
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||||
|
|
||||||
|
<beans>
|
||||||
|
|
||||||
|
<!-- Notification service bean -->
|
||||||
|
<bean id="NotificationService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||||
|
<property name="proxyInterfaces">
|
||||||
|
<value>org.alfresco.service.cmr.notification.NotificationService</value>
|
||||||
|
</property>
|
||||||
|
<property name="target">
|
||||||
|
<ref bean="notificationService"/>
|
||||||
|
</property>
|
||||||
|
<property name="interceptorNames">
|
||||||
|
<list>
|
||||||
|
<idref local="NotificationService_transaction"/>
|
||||||
|
<idref bean="AuditMethodInterceptor"/>
|
||||||
|
<idref bean="exceptionTranslator"/>
|
||||||
|
<idref bean="NotificationService_security"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- Notification service transaction bean -->
|
||||||
|
<bean id="NotificationService_transaction" class="org.springframework.transaction.interceptor.TransactionInterceptor">
|
||||||
|
<property name="transactionManager">
|
||||||
|
<ref bean="transactionManager"/>
|
||||||
|
</property>
|
||||||
|
<property name="transactionAttributes">
|
||||||
|
<props>
|
||||||
|
<prop key="*">${server.transaction.mode.default}</prop>
|
||||||
|
</props>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- This service has no security restrictions -->
|
||||||
|
<bean id="NotificationService_security" class="org.alfresco.repo.security.permissions.impl.AlwaysProceedMethodInterceptor" />
|
||||||
|
|
||||||
|
<!-- I18N -->
|
||||||
|
<bean id="notificationServiceResourceBundles" class="org.alfresco.i18n.ResourceBundleBootstrapComponent">
|
||||||
|
<property name="resourceBundles">
|
||||||
|
<list>
|
||||||
|
<value>alfresco.messages.notification-service</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- Notification service implementation bean -->
|
||||||
|
<bean id="notificationService" class="org.alfresco.repo.notification.NotificationServiceImpl" >
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- EMail notification provider -->
|
||||||
|
<bean id="emailNotificationProvider" class="org.alfresco.repo.notification.EMailNotificationProvider" init-method="init">
|
||||||
|
<property name="notificationService" ref="notificationService"/>
|
||||||
|
<property name="nodeService" ref="NodeService"/>
|
||||||
|
<property name="actionService" ref="ActionService"/>
|
||||||
|
<property name="personService" ref="PersonService"/>
|
||||||
|
<property name="repository" ref="repositoryHelper"/>
|
||||||
|
<property name="fileFolderService" ref="FileFolderService"/>
|
||||||
|
<property name="repoAdminService" ref="RepoAdminService"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
</beans>
|
@@ -2944,4 +2944,32 @@
|
|||||||
<property name="batchMaxQueryRange" value="5000"/>
|
<property name="batchMaxQueryRange" value="5000"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<!-- TODO .. update to install workflow email folder ... -->
|
||||||
|
<bean id="patch.workflowNotification" class="org.alfresco.repo.admin.patch.impl.GenericBootstrapPatch" parent="basePatch" >
|
||||||
|
<property name="id"><value>patch.workflowNotification</value></property>
|
||||||
|
<property name="description"><value>patch.workflowNotification.description</value></property>
|
||||||
|
<property name="fixesFromSchema"><value>0</value></property>
|
||||||
|
<property name="fixesToSchema"><value>5014</value></property>
|
||||||
|
<property name="targetSchema"><value>5015</value></property>
|
||||||
|
<property name="dependsOn" >
|
||||||
|
<list>
|
||||||
|
<ref bean="patch.updateDmPermissions" />
|
||||||
|
<ref bean="patch.emailTemplatesFolder" />
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
<property name="importerBootstrap">
|
||||||
|
<ref bean="spacesBootstrap" />
|
||||||
|
</property>
|
||||||
|
<property name="checkPath">
|
||||||
|
<value>/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.templates.email.childname}/${spaces.templates.email.workflowemailnotification.childname}</value>
|
||||||
|
</property>
|
||||||
|
<property name="bootstrapView">
|
||||||
|
<props>
|
||||||
|
<prop key="path">/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.templates.email.childname}</prop>
|
||||||
|
<prop key="location">alfresco/bootstrap/notification/workflow-email-notification.xml</prop>
|
||||||
|
<prop key="messages">alfresco/messages/bootstrap-spaces</prop>
|
||||||
|
</props>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
@@ -422,6 +422,7 @@ spaces.extension_webscripts.childname=cm:extensionwebscripts
|
|||||||
spaces.models.childname=app:models
|
spaces.models.childname=app:models
|
||||||
spaces.workflow.definitions.childname=app:workflow_defs
|
spaces.workflow.definitions.childname=app:workflow_defs
|
||||||
spaces.publishing.root.childname=app:publishing_root
|
spaces.publishing.root.childname=app:publishing_root
|
||||||
|
spaces.templates.email.workflowemailnotification.childname=cm:workflownotification
|
||||||
|
|
||||||
# ADM VersionStore Configuration
|
# ADM VersionStore Configuration
|
||||||
version.store.deprecated.lightWeightVersionStore=workspace://lightWeightVersionStore
|
version.store.deprecated.lightWeightVersionStore=workspace://lightWeightVersionStore
|
||||||
|
@@ -19,4 +19,4 @@ version.build=@build-number@
|
|||||||
|
|
||||||
# Schema number
|
# Schema number
|
||||||
|
|
||||||
version.schema=5014
|
version.schema=5015
|
||||||
|
@@ -580,7 +580,7 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
|
|||||||
if (fromPerson != null)
|
if (fromPerson != null)
|
||||||
{
|
{
|
||||||
model.put("person", new TemplateNode(fromPerson, serviceRegistry, null));
|
model.put("person", new TemplateNode(fromPerson, serviceRegistry, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ref != null)
|
if (ref != null)
|
||||||
{
|
{
|
||||||
|
@@ -0,0 +1,308 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.notification;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.action.executer.MailActionExecuter;
|
||||||
|
import org.alfresco.repo.model.Repository;
|
||||||
|
import org.alfresco.service.cmr.action.Action;
|
||||||
|
import org.alfresco.service.cmr.action.ActionService;
|
||||||
|
import org.alfresco.service.cmr.admin.RepoAdminService;
|
||||||
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
|
import org.alfresco.service.cmr.notification.NotificationContext;
|
||||||
|
import org.alfresco.service.cmr.notification.NotificationProvider;
|
||||||
|
import org.alfresco.service.cmr.notification.NotificationService;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.repository.TemplateService;
|
||||||
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
|
import org.alfresco.util.ModelUtil;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.extensions.surf.util.I18NUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EMail notification provider implementation
|
||||||
|
*
|
||||||
|
* @author Roy Wetherall
|
||||||
|
*/
|
||||||
|
public class EMailNotificationProvider implements NotificationProvider
|
||||||
|
{
|
||||||
|
/** I18N */
|
||||||
|
private static final String MSG_DEFAULT_SENDER_USED = "default-sender-used";
|
||||||
|
private static final String MSG_NO_RECIPIENTS = "no-recipients";
|
||||||
|
private static final String MSG_NO_BODY_OR_TEMPLATE = "no-body-or-template";
|
||||||
|
|
||||||
|
/** Log */
|
||||||
|
private static Log logger = LogFactory.getLog(EMailNotificationProvider.class);
|
||||||
|
|
||||||
|
/** Name of provider */
|
||||||
|
public final static String NAME = "email";
|
||||||
|
|
||||||
|
/** Notification service */
|
||||||
|
private NotificationService notificationService;
|
||||||
|
|
||||||
|
/** Node service */
|
||||||
|
private NodeService nodeService;
|
||||||
|
|
||||||
|
/** Action service */
|
||||||
|
private ActionService actionService;
|
||||||
|
|
||||||
|
/** Person service */
|
||||||
|
private PersonService personService;
|
||||||
|
|
||||||
|
/** Repository object */
|
||||||
|
private Repository repository;
|
||||||
|
|
||||||
|
/** File folder service */
|
||||||
|
private FileFolderService fileFolderService;
|
||||||
|
|
||||||
|
/** Repository administration service */
|
||||||
|
private RepoAdminService repoAdminService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param notificationService notification service
|
||||||
|
*/
|
||||||
|
public void setNotificationService(NotificationService notificationService)
|
||||||
|
{
|
||||||
|
this.notificationService = notificationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param nodeService node service
|
||||||
|
*/
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param actionService action service
|
||||||
|
*/
|
||||||
|
public void setActionService(ActionService actionService)
|
||||||
|
{
|
||||||
|
this.actionService = actionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param personService person service
|
||||||
|
*/
|
||||||
|
public void setPersonService(PersonService personService)
|
||||||
|
{
|
||||||
|
this.personService = personService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param repository repository object
|
||||||
|
*/
|
||||||
|
public void setRepository(Repository repository)
|
||||||
|
{
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param repoAdminService repository administration serviceS
|
||||||
|
*/
|
||||||
|
public void setRepoAdminService(RepoAdminService repoAdminService)
|
||||||
|
{
|
||||||
|
this.repoAdminService = repoAdminService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param fileFolderService file folder service
|
||||||
|
*/
|
||||||
|
public void setFileFolderService(FileFolderService fileFolderService)
|
||||||
|
{
|
||||||
|
this.fileFolderService = fileFolderService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init method registers provider with notification service.
|
||||||
|
*/
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
notificationService.register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.service.cmr.notification.NotificationProvider#getName()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.service.cmr.notification.NotificationProvider#sendNotification(org.alfresco.service.cmr.notification.NotificationContext)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void sendNotification(NotificationContext notificationContext)
|
||||||
|
{
|
||||||
|
Action mail = actionService.createAction(MailActionExecuter.NAME);
|
||||||
|
|
||||||
|
// Set from parameter
|
||||||
|
String from = notificationContext.getFrom();
|
||||||
|
if (from != null && from.length() != 0)
|
||||||
|
{
|
||||||
|
String fromEMail = getEMailFromUser(from);
|
||||||
|
if (fromEMail != null)
|
||||||
|
{
|
||||||
|
mail.setParameterValue(MailActionExecuter.PARAM_FROM, fromEMail);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (logger.isWarnEnabled() == true)
|
||||||
|
{
|
||||||
|
logger.warn(I18NUtil.getMessage(MSG_DEFAULT_SENDER_USED, from));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set to parameter
|
||||||
|
List<String> to = notificationContext.getTo();
|
||||||
|
if (to == null || to.size() == 0)
|
||||||
|
{
|
||||||
|
errorEncountered(notificationContext,
|
||||||
|
I18NUtil.getMessage(MSG_NO_RECIPIENTS, notificationContext.getDocument()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mail.setParameterValue(MailActionExecuter.PARAM_TO_MANY, (Serializable)to);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set subject
|
||||||
|
String subject = notificationContext.getSubject();
|
||||||
|
if (subject != null)
|
||||||
|
{
|
||||||
|
mail.setParameterValue(MailActionExecuter.PARAM_SUBJECT, subject);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set body
|
||||||
|
String body = notificationContext.getBody();
|
||||||
|
if (body != null && body.length() != 0)
|
||||||
|
{
|
||||||
|
mail.setParameterValue(MailActionExecuter.PARAM_TEXT, body);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Check for template
|
||||||
|
NodeRef template = notificationContext.getBodyTemplate();
|
||||||
|
if (template == null)
|
||||||
|
{
|
||||||
|
errorEncountered(notificationContext,
|
||||||
|
I18NUtil.getMessage(MSG_NO_BODY_OR_TEMPLATE, notificationContext.getDocument()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
template = fileFolderService.getLocalizedSibling(template);
|
||||||
|
mail.setParameterValue(MailActionExecuter.PARAM_TEMPLATE, template);
|
||||||
|
mail.setParameterValue(MailActionExecuter.PARAM_TEMPLATE_MODEL,
|
||||||
|
(Serializable)buildTemplateModel(notificationContext.getTemplateArgs()));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set ignore failure
|
||||||
|
mail.setParameterValue(MailActionExecuter.PARAM_IGNORE_SEND_FAILURE, Boolean.valueOf(notificationContext.isIgnoreNotificationFailure()));
|
||||||
|
|
||||||
|
// Execute mail action upon document
|
||||||
|
actionService.executeAction(mail, notificationContext.getDocument(), false, notificationContext.isAsyncNotification());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the email for the given user name. Returns null if none set.
|
||||||
|
*
|
||||||
|
* @param user user name
|
||||||
|
* @return {@link String} user email
|
||||||
|
*/
|
||||||
|
private String getEMailFromUser(String user)
|
||||||
|
{
|
||||||
|
String email = null;
|
||||||
|
|
||||||
|
NodeRef person = personService.getPerson(user);
|
||||||
|
if (person != null)
|
||||||
|
{
|
||||||
|
email = (String)nodeService.getProperty(person, ContentModel.PROP_EMAIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the model for the body template.
|
||||||
|
*
|
||||||
|
* @param templateArgs template args provided by the notification context
|
||||||
|
* @return {@link Map}<{@link String},{@link Serializable}> template model values
|
||||||
|
*/
|
||||||
|
private Map<String, Serializable> buildTemplateModel(Map<String, Serializable> templateArgs)
|
||||||
|
{
|
||||||
|
// Set the core model parts
|
||||||
|
// Note - the user part is skipped, as that's implied via the run-as
|
||||||
|
Map<String, Serializable> model = new HashMap<String, Serializable>();
|
||||||
|
model.put(TemplateService.KEY_COMPANY_HOME, repository.getCompanyHome());
|
||||||
|
NodeRef person = repository.getPerson();
|
||||||
|
if (person != null)
|
||||||
|
{
|
||||||
|
model.put(TemplateService.KEY_PERSON, person);
|
||||||
|
model.put(TemplateService.KEY_USER_HOME, repository.getUserHome(person));
|
||||||
|
}
|
||||||
|
model.put(TemplateService.KEY_PRODUCT_NAME, ModelUtil.getProductName(repoAdminService));
|
||||||
|
|
||||||
|
// Put the notification context information in the model?
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
if (templateArgs != null && templateArgs.size() != 0)
|
||||||
|
{
|
||||||
|
// Put the provided args in the model
|
||||||
|
model.put("args", (Serializable)templateArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// All done
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deals with an error when it is encountered
|
||||||
|
*
|
||||||
|
* @param notificationContext notification context
|
||||||
|
* @param message error message
|
||||||
|
*/
|
||||||
|
private void errorEncountered(NotificationContext notificationContext, String message)
|
||||||
|
{
|
||||||
|
if (logger.isWarnEnabled() == true)
|
||||||
|
{
|
||||||
|
logger.warn(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notificationContext.isIgnoreNotificationFailure() == false)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.notification;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.service.cmr.notification.NotificationContext;
|
||||||
|
import org.alfresco.service.cmr.notification.NotificationProvider;
|
||||||
|
import org.alfresco.service.cmr.notification.NotificationService;
|
||||||
|
import org.alfresco.util.ParameterCheck;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.extensions.surf.util.I18NUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification service implementation.
|
||||||
|
*
|
||||||
|
* @author Roy Wetherall
|
||||||
|
*/
|
||||||
|
public class NotificationServiceImpl implements NotificationService
|
||||||
|
{
|
||||||
|
/** I18N */
|
||||||
|
private static final String MSG_NP_DOES_NOT_EXIST = "np-does-not-exist";
|
||||||
|
|
||||||
|
/** Log */
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static Log logger = LogFactory.getLog(EMailNotificationProvider.class);
|
||||||
|
|
||||||
|
/** Map of registered notification providers */
|
||||||
|
private Map<String, NotificationProvider> providers = new HashMap<String, NotificationProvider>(3);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.service.cmr.notification.NotificationService#register(org.alfresco.service.cmr.notification.NotificationProvider)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void register(NotificationProvider notificationProvider)
|
||||||
|
{
|
||||||
|
// Check mandatory params
|
||||||
|
ParameterCheck.mandatory("notificationProvider", notificationProvider);
|
||||||
|
|
||||||
|
// Add the notification provider to the map
|
||||||
|
providers.put(notificationProvider.getName(), notificationProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.service.cmr.notification.NotificationService#exists(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean exists(String notificationProvider)
|
||||||
|
{
|
||||||
|
// Check the mandatory params
|
||||||
|
ParameterCheck.mandatory("notificationProvider", notificationProvider);
|
||||||
|
|
||||||
|
return providers.containsKey(notificationProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.service.cmr.notification.NotificationService#getNotificationProviders()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<String> getNotificationProviders()
|
||||||
|
{
|
||||||
|
return new ArrayList<String>(providers.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.service.cmr.notification.NotificationService#sendNotification(java.lang.String, org.alfresco.service.cmr.notification.NotificationContext)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void sendNotification(String notificationProvider, NotificationContext notificationContext)
|
||||||
|
{
|
||||||
|
// Check the mandatory params
|
||||||
|
ParameterCheck.mandatory("notificationProvider", notificationProvider);
|
||||||
|
ParameterCheck.mandatory("notificationContext", notificationContext);
|
||||||
|
|
||||||
|
// Check that the notificaiton provider exists
|
||||||
|
if (exists(notificationProvider) == false)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_NP_DOES_NOT_EXIST, notificationProvider));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the notification provider and send notification
|
||||||
|
NotificationProvider provider = providers.get(notificationProvider);
|
||||||
|
provider.sendNotification(notificationContext);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,224 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.notification;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
|
import org.alfresco.repo.model.Repository;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
|
import org.alfresco.service.cmr.notification.NotificationContext;
|
||||||
|
import org.alfresco.service.cmr.notification.NotificationService;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.security.MutableAuthenticationService;
|
||||||
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.BaseAlfrescoTestCase;
|
||||||
|
import org.alfresco.util.GUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification service implementation test.
|
||||||
|
*
|
||||||
|
* @author Roy Wetherall
|
||||||
|
*/
|
||||||
|
public class NotificationServiceImplSystemTest extends BaseAlfrescoTestCase
|
||||||
|
{
|
||||||
|
private static final String FROM_USER = "fromUser" + GUID.generate();;
|
||||||
|
private static final String FROM_EMAIL = "test@alfresco.com";
|
||||||
|
private static final String FROM_FIRST_NAME = "Grace";
|
||||||
|
private static final String FROM_LAST_NAME = "Wetherall";
|
||||||
|
|
||||||
|
private static final String TO_USER1 = "userOne" + GUID.generate();;
|
||||||
|
private static final String TO_USER2 = "userTwo" + GUID.generate();;
|
||||||
|
private static final String TO_USER3 = "userThree" + GUID.generate();;
|
||||||
|
|
||||||
|
private static final String EMAIL = "rwetherall@alfresco.com";
|
||||||
|
private static final String PASSWORD = "password";
|
||||||
|
private static final String FIRST_NAME = "Peter";
|
||||||
|
private static final String LAST_NAME = "Wetherall";
|
||||||
|
|
||||||
|
private static final String SUBJECT = "Notification Test";
|
||||||
|
private static final String BODY = "This is a test notification from org.alfresco.repo.notification.NotificationServiceImplSystemTest. Please do not respond!";
|
||||||
|
|
||||||
|
private static final String TEMPLATE =
|
||||||
|
"<html>" +
|
||||||
|
" <body bgcolour='#dddddd'>" +
|
||||||
|
" <p>This is a test notification from org.alfresco.repo.notification.NotificationServiceImplSystemTest. Please do not respond!</p>" +
|
||||||
|
" <br>" +
|
||||||
|
" Template context:<br><br>" +
|
||||||
|
" userhome: ${userhome}<br>" +
|
||||||
|
" companyhome: ${companyhome}<br>" +
|
||||||
|
" productname: ${productName}<br>" +
|
||||||
|
"";
|
||||||
|
|
||||||
|
private NotificationService notificationService;
|
||||||
|
private MutableAuthenticationService authenticationService;
|
||||||
|
private PersonService personService;
|
||||||
|
private Repository repository;
|
||||||
|
private FileFolderService fileFolderService;
|
||||||
|
|
||||||
|
private NodeRef fromPerson;
|
||||||
|
private NodeRef toPerson1;
|
||||||
|
private NodeRef toPerson2;
|
||||||
|
private NodeRef toPerson3;
|
||||||
|
|
||||||
|
private NodeRef template;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception
|
||||||
|
{
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
// Get the notification service
|
||||||
|
notificationService = (NotificationService)ctx.getBean("NotificationService");
|
||||||
|
authenticationService = (MutableAuthenticationService)ctx.getBean("AuthenticationService");
|
||||||
|
personService = (PersonService)ctx.getBean("PersonService");
|
||||||
|
repository = (Repository)ctx.getBean("repositoryHelper");
|
||||||
|
fileFolderService = (FileFolderService)ctx.getBean("FileFolderService");
|
||||||
|
|
||||||
|
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
// As system user
|
||||||
|
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
||||||
|
|
||||||
|
// Create people and users
|
||||||
|
fromPerson = createPerson(FROM_USER, PASSWORD, FROM_FIRST_NAME, FROM_LAST_NAME, FROM_EMAIL);
|
||||||
|
toPerson1 = createPerson(TO_USER1, PASSWORD, FIRST_NAME, LAST_NAME, EMAIL);
|
||||||
|
toPerson2 = createPerson(TO_USER2, PASSWORD, FIRST_NAME, LAST_NAME, EMAIL);
|
||||||
|
toPerson3 = createPerson(TO_USER3, PASSWORD, FIRST_NAME, LAST_NAME, EMAIL);
|
||||||
|
|
||||||
|
// Create a test template
|
||||||
|
NodeRef companyHome = repository.getCompanyHome();
|
||||||
|
template = fileFolderService.create(companyHome, "testTemplate" + GUID.generate() + ".ftl", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||||
|
|
||||||
|
ContentWriter writer = contentService.getWriter(template, ContentModel.PROP_CONTENT, true);
|
||||||
|
writer.setEncoding("UTF-8");
|
||||||
|
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||||||
|
writer.putContent(TEMPLATE);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tearDown() throws Exception
|
||||||
|
{
|
||||||
|
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
// As system user
|
||||||
|
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
||||||
|
|
||||||
|
// Delete the template
|
||||||
|
nodeService.deleteNode(template);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
private NodeRef createPerson(String userName, String password, String firstName, String lastName, String email)
|
||||||
|
{
|
||||||
|
NodeRef person = null;
|
||||||
|
|
||||||
|
if (authenticationService.authenticationExists(userName) == false)
|
||||||
|
{
|
||||||
|
authenticationService.createAuthentication(userName, password.toCharArray());
|
||||||
|
|
||||||
|
Map<QName, Serializable> properties = new HashMap<QName, Serializable>(7);
|
||||||
|
properties.put(ContentModel.PROP_USERNAME, userName);
|
||||||
|
properties.put(ContentModel.PROP_FIRSTNAME, firstName);
|
||||||
|
properties.put(ContentModel.PROP_LASTNAME, lastName);
|
||||||
|
properties.put(ContentModel.PROP_EMAIL, email);
|
||||||
|
|
||||||
|
person = personService.createPerson(properties);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
person = personService.getPerson(userName);
|
||||||
|
}
|
||||||
|
return person;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean useSpacesStore()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSimpleEmailNotification()
|
||||||
|
{
|
||||||
|
doTestInTransaction(new Test<Void>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Void run()
|
||||||
|
{
|
||||||
|
NotificationContext context = new NotificationContext();
|
||||||
|
|
||||||
|
context.setFrom(FROM_EMAIL);
|
||||||
|
context.addTo(TO_USER1);
|
||||||
|
context.setSubject(SUBJECT);
|
||||||
|
context.setBody(BODY);
|
||||||
|
|
||||||
|
notificationService.sendNotification(EMailNotificationProvider.NAME, context);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testTemplateEmailNotification()
|
||||||
|
{
|
||||||
|
doTestInTransaction(new Test<Void>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Void run()
|
||||||
|
{
|
||||||
|
NotificationContext context = new NotificationContext();
|
||||||
|
|
||||||
|
context.setFrom(FROM_EMAIL);
|
||||||
|
context.addTo(TO_USER1);
|
||||||
|
context.setSubject(SUBJECT);
|
||||||
|
context.setBodyTemplate(template);
|
||||||
|
|
||||||
|
Map<String, Serializable> templateArgs = new HashMap<String, Serializable>(1);
|
||||||
|
templateArgs.put("template", template);
|
||||||
|
context.setTemplateArgs(templateArgs);
|
||||||
|
|
||||||
|
notificationService.sendNotification(EMailNotificationProvider.NAME, context);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@@ -51,6 +51,7 @@ import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
|
|||||||
import org.alfresco.service.cmr.ml.EditionService;
|
import org.alfresco.service.cmr.ml.EditionService;
|
||||||
import org.alfresco.service.cmr.ml.MultilingualContentService;
|
import org.alfresco.service.cmr.ml.MultilingualContentService;
|
||||||
import org.alfresco.service.cmr.model.FileFolderService;
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
|
import org.alfresco.service.cmr.notification.NotificationService;
|
||||||
import org.alfresco.service.cmr.rating.RatingService;
|
import org.alfresco.service.cmr.rating.RatingService;
|
||||||
import org.alfresco.service.cmr.rendition.RenditionService;
|
import org.alfresco.service.cmr.rendition.RenditionService;
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
@@ -108,6 +109,12 @@ public class MockedTestServiceRegistry implements ServiceRegistry
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NotificationService getNotificationService()
|
||||||
|
{
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public WebProjectService getWebProjectService()
|
public WebProjectService getWebProjectService()
|
||||||
{
|
{
|
||||||
|
@@ -49,6 +49,7 @@ import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
|
|||||||
import org.alfresco.service.cmr.ml.EditionService;
|
import org.alfresco.service.cmr.ml.EditionService;
|
||||||
import org.alfresco.service.cmr.ml.MultilingualContentService;
|
import org.alfresco.service.cmr.ml.MultilingualContentService;
|
||||||
import org.alfresco.service.cmr.model.FileFolderService;
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
|
import org.alfresco.service.cmr.notification.NotificationService;
|
||||||
import org.alfresco.service.cmr.rating.RatingService;
|
import org.alfresco.service.cmr.rating.RatingService;
|
||||||
import org.alfresco.service.cmr.rendition.RenditionService;
|
import org.alfresco.service.cmr.rendition.RenditionService;
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
@@ -339,6 +340,15 @@ public class ServiceDescriptorRegistry
|
|||||||
{
|
{
|
||||||
return (WorkflowService)getService(WORKFLOW_SERVICE);
|
return (WorkflowService)getService(WORKFLOW_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.alfresco.service.ServiceRegistry#getNotificationService()
|
||||||
|
*/
|
||||||
|
public NotificationService getNotificationService()
|
||||||
|
{
|
||||||
|
return (NotificationService)getService(NOTIFICATION_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.alfresco.service.ServiceRegistry#getWorkflowService()
|
* @see org.alfresco.service.ServiceRegistry#getWorkflowService()
|
||||||
|
@@ -86,5 +86,7 @@ public interface WorkflowModel
|
|||||||
static final QName PROP_WORKFLOW_DEF_ENGINE_ID = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "engineId");
|
static final QName PROP_WORKFLOW_DEF_ENGINE_ID = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "engineId");
|
||||||
static final QName PROP_WORKFLOW_DEF_NAME = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "definitionName");
|
static final QName PROP_WORKFLOW_DEF_NAME = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "definitionName");
|
||||||
static final QName PROP_WORKFLOW_DEF_DEPLOYED = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "definitionDeployed");
|
static final QName PROP_WORKFLOW_DEF_DEPLOYED = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "definitionDeployed");
|
||||||
|
|
||||||
|
static final QName PROP_SEND_EMAIL_NOTIFICATIONS = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "sendEMailNotifications");
|
||||||
|
|
||||||
}
|
}
|
@@ -0,0 +1,146 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.workflow;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.repo.notification.EMailNotificationProvider;
|
||||||
|
import org.alfresco.service.ServiceRegistry;
|
||||||
|
import org.alfresco.service.cmr.notification.NotificationContext;
|
||||||
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.springframework.extensions.surf.util.I18NUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class containing methods to help when sending workflow notifications.
|
||||||
|
*
|
||||||
|
* TODO? Move to workflow serivce??
|
||||||
|
*
|
||||||
|
* @author Roy Wetherall
|
||||||
|
*/
|
||||||
|
public abstract class WorkflowNotificationUtils
|
||||||
|
{
|
||||||
|
/** Send EMail notifications property */
|
||||||
|
public static final String PROP_SEND_EMAIL_NOTIFICATIONS = "bpm_sendEMailNotifications";
|
||||||
|
|
||||||
|
/** I18N */
|
||||||
|
public static final String MSG_ASSIGNED_TASK = "assigned-task";
|
||||||
|
public static final String MSG_NEW_POOLED_TASK = "new-pooled-task";
|
||||||
|
|
||||||
|
/** Standard workflow assigned template */
|
||||||
|
private static final NodeRef WF_ASSIGNED_TEMPLATE = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "wf-email-html-ftl");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send workflow assigned email notification.
|
||||||
|
*
|
||||||
|
* @param services service registry
|
||||||
|
* @param taskId workflow global task id
|
||||||
|
* @param assignedAuthority assigned authority
|
||||||
|
* @param pooled true if pooled task, false otherwise
|
||||||
|
*/
|
||||||
|
public static void sendWorkflowAssignedNotificationEMail(ServiceRegistry services,
|
||||||
|
String taskId,
|
||||||
|
String assignedAuthority,
|
||||||
|
boolean pooled)
|
||||||
|
{
|
||||||
|
sendWorkflowAssignedNotificationEMail(services, taskId, new String[]{assignedAuthority}, pooled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send workflow assigned email notification.
|
||||||
|
*
|
||||||
|
* @param services service registry
|
||||||
|
* @param taskId workflow global task id
|
||||||
|
* @param assignedAuthorites assigned authorities
|
||||||
|
* @param pooled true if pooled task, false otherwise
|
||||||
|
*/
|
||||||
|
public static void sendWorkflowAssignedNotificationEMail(ServiceRegistry services,
|
||||||
|
String taskId,
|
||||||
|
String[] assignedAuthorites,
|
||||||
|
boolean pooled)
|
||||||
|
{
|
||||||
|
WorkflowTask workflowTask = services.getWorkflowService().getTaskById(taskId);
|
||||||
|
Map<QName, Serializable> props = workflowTask.getProperties();
|
||||||
|
NotificationContext notificationContext = new NotificationContext();
|
||||||
|
|
||||||
|
// Determine the subject of the notification
|
||||||
|
String subject = null;
|
||||||
|
if (pooled == false)
|
||||||
|
{
|
||||||
|
subject = I18NUtil.getMessage(MSG_ASSIGNED_TASK);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
subject = I18NUtil.getMessage(MSG_NEW_POOLED_TASK);
|
||||||
|
}
|
||||||
|
notificationContext.setSubject(subject);
|
||||||
|
|
||||||
|
// Set the email template
|
||||||
|
notificationContext.setBodyTemplate(WF_ASSIGNED_TEMPLATE);
|
||||||
|
|
||||||
|
// Build the template args
|
||||||
|
Map<String, Serializable>templateArgs = new HashMap<String, Serializable>(7);
|
||||||
|
templateArgs.put("workflowId", workflowTask.getId());
|
||||||
|
templateArgs.put("workflowTitle", workflowTask.getTitle());
|
||||||
|
|
||||||
|
// Get the description
|
||||||
|
String description = (String)props.get(WorkflowModel.PROP_DESCRIPTION);
|
||||||
|
if (description == null)
|
||||||
|
{
|
||||||
|
description = workflowTask.getDescription();
|
||||||
|
}
|
||||||
|
templateArgs.put("workflowDescription", description);
|
||||||
|
|
||||||
|
// Get the due date
|
||||||
|
Date dueDate = (Date)props.get(WorkflowModel.PROP_DUE_DATE);
|
||||||
|
if (dueDate != null)
|
||||||
|
{
|
||||||
|
templateArgs.put("workflowDueDate", dueDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the workflow priority
|
||||||
|
Integer priority = (Integer)props.get(WorkflowModel.PROP_PRIORITY);
|
||||||
|
if (priority != null)
|
||||||
|
{
|
||||||
|
templateArgs.put("workflowPriority", priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate whether this is a pooled workflow item or not
|
||||||
|
templateArgs.put("workflowPooled", pooled);
|
||||||
|
|
||||||
|
// Add details of associated content
|
||||||
|
NodeRef workflowPackage = workflowTask.getPath().getInstance().getWorkflowPackage();
|
||||||
|
List<ChildAssociationRef> assocs = services.getNodeService().getChildAssocs(workflowPackage);
|
||||||
|
NodeRef[] docs = new NodeRef[assocs.size()];
|
||||||
|
if (assocs.size() != 0)
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
for (ChildAssociationRef assoc : assocs)
|
||||||
|
{
|
||||||
|
docs[index] = assoc.getChildRef();
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
templateArgs.put("workflowDocuments", docs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the template args
|
||||||
|
notificationContext.setTemplateArgs(templateArgs);
|
||||||
|
|
||||||
|
// Set the notification recipients
|
||||||
|
for (String assignedAuthority : assignedAuthorites)
|
||||||
|
{
|
||||||
|
notificationContext.addTo(assignedAuthority);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send email notification
|
||||||
|
services.getNotificationService().sendNotification(EMailNotificationProvider.NAME, notificationContext);
|
||||||
|
}
|
||||||
|
}
|
@@ -23,9 +23,12 @@ import org.activiti.engine.delegate.DelegateTask;
|
|||||||
import org.activiti.engine.delegate.TaskListener;
|
import org.activiti.engine.delegate.TaskListener;
|
||||||
import org.activiti.engine.form.FormData;
|
import org.activiti.engine.form.FormData;
|
||||||
import org.activiti.engine.impl.form.TaskFormHandler;
|
import org.activiti.engine.impl.form.TaskFormHandler;
|
||||||
|
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
|
||||||
import org.activiti.engine.impl.persistence.entity.TaskEntity;
|
import org.activiti.engine.impl.persistence.entity.TaskEntity;
|
||||||
|
import org.alfresco.repo.workflow.WorkflowNotificationUtils;
|
||||||
import org.alfresco.repo.workflow.activiti.ActivitiConstants;
|
import org.alfresco.repo.workflow.activiti.ActivitiConstants;
|
||||||
import org.alfresco.repo.workflow.activiti.properties.ActivitiPropertyConverter;
|
import org.alfresco.repo.workflow.activiti.properties.ActivitiPropertyConverter;
|
||||||
|
import org.alfresco.service.ServiceRegistry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tasklistener that is notified when a task is created. This will set all
|
* Tasklistener that is notified when a task is created. This will set all
|
||||||
@@ -38,6 +41,17 @@ public class TaskCreateListener implements TaskListener
|
|||||||
{
|
{
|
||||||
private ActivitiPropertyConverter propertyConverter;
|
private ActivitiPropertyConverter propertyConverter;
|
||||||
|
|
||||||
|
/** Service Registry */
|
||||||
|
private ServiceRegistry services;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param services the service registry
|
||||||
|
*/
|
||||||
|
public void setServices(ServiceRegistry services)
|
||||||
|
{
|
||||||
|
this.services = services;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notify(DelegateTask task)
|
public void notify(DelegateTask task)
|
||||||
{
|
{
|
||||||
@@ -51,6 +65,19 @@ public class TaskCreateListener implements TaskListener
|
|||||||
{
|
{
|
||||||
task.setVariableLocal(ActivitiConstants.PROP_TASK_FORM_KEY, taskFormKey);
|
task.setVariableLocal(ActivitiConstants.PROP_TASK_FORM_KEY, taskFormKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine whether we need to send the workflow notification or not
|
||||||
|
ExecutionEntity executionEntity = ((ExecutionEntity)task.getExecution()).getProcessInstance();
|
||||||
|
Boolean value = (Boolean)executionEntity.getVariable(WorkflowNotificationUtils.PROP_SEND_EMAIL_NOTIFICATIONS);
|
||||||
|
if (Boolean.TRUE.equals(value) == true)
|
||||||
|
{
|
||||||
|
// Send email notification
|
||||||
|
WorkflowNotificationUtils.sendWorkflowAssignedNotificationEMail(
|
||||||
|
services,
|
||||||
|
"activiti$" + task.getId(),
|
||||||
|
task.getAssignee(),
|
||||||
|
false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFormKey(DelegateTask task)
|
private String getFormKey(DelegateTask task)
|
||||||
|
@@ -25,6 +25,7 @@ import java.util.List;
|
|||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.jscript.ScriptNode;
|
import org.alfresco.repo.jscript.ScriptNode;
|
||||||
import org.alfresco.repo.security.authority.AuthorityDAO;
|
import org.alfresco.repo.security.authority.AuthorityDAO;
|
||||||
|
import org.alfresco.repo.workflow.WorkflowNotificationUtils;
|
||||||
import org.alfresco.service.ServiceRegistry;
|
import org.alfresco.service.ServiceRegistry;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.cmr.workflow.WorkflowException;
|
import org.alfresco.service.cmr.workflow.WorkflowException;
|
||||||
@@ -195,17 +196,41 @@ public class AlfrescoAssignment extends JBPMSpringAssignmentHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Determine whether we need to send email notifications of not
|
||||||
|
Boolean sendEMailNotification = (Boolean)executionContext.getVariable(WorkflowNotificationUtils.PROP_SEND_EMAIL_NOTIFICATIONS);
|
||||||
|
|
||||||
//
|
//
|
||||||
// make the assignment
|
// make the assignment
|
||||||
//
|
//
|
||||||
if (assignedActor != null)
|
if (assignedActor != null)
|
||||||
{
|
{
|
||||||
assignable.setActorId(assignedActor);
|
assignable.setActorId(assignedActor);
|
||||||
|
|
||||||
|
if (Boolean.TRUE.equals(sendEMailNotification) == true)
|
||||||
|
{
|
||||||
|
// Send the notification
|
||||||
|
WorkflowNotificationUtils.sendWorkflowAssignedNotificationEMail(
|
||||||
|
services,
|
||||||
|
JBPMEngine.ENGINE_ID + "$" + executionContext.getTaskInstance().getId(),
|
||||||
|
assignedActor,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (assignedPooledActors != null)
|
if (assignedPooledActors != null)
|
||||||
{
|
{
|
||||||
assignable.setPooledActors(assignedPooledActors);
|
assignable.setPooledActors(assignedPooledActors);
|
||||||
}
|
|
||||||
|
if (Boolean.TRUE.equals(sendEMailNotification) == true)
|
||||||
|
{
|
||||||
|
// Send the notification
|
||||||
|
WorkflowNotificationUtils.sendWorkflowAssignedNotificationEMail(
|
||||||
|
services,
|
||||||
|
JBPMEngine.ENGINE_ID + "$" + executionContext.getTaskInstance().getId(),
|
||||||
|
assignedPooledActors,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -48,6 +48,7 @@ import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
|
|||||||
import org.alfresco.service.cmr.ml.EditionService;
|
import org.alfresco.service.cmr.ml.EditionService;
|
||||||
import org.alfresco.service.cmr.ml.MultilingualContentService;
|
import org.alfresco.service.cmr.ml.MultilingualContentService;
|
||||||
import org.alfresco.service.cmr.model.FileFolderService;
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
|
import org.alfresco.service.cmr.notification.NotificationService;
|
||||||
import org.alfresco.service.cmr.rating.RatingService;
|
import org.alfresco.service.cmr.rating.RatingService;
|
||||||
import org.alfresco.service.cmr.rendition.RenditionService;
|
import org.alfresco.service.cmr.rendition.RenditionService;
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
@@ -142,6 +143,7 @@ public interface ServiceRegistry
|
|||||||
static final QName NODE_LOCATOR_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "nodeLocatorService");
|
static final QName NODE_LOCATOR_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "nodeLocatorService");
|
||||||
static final QName BLOG_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "BlogService");
|
static final QName BLOG_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "BlogService");
|
||||||
static final QName CALENDAR_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CalendarService");
|
static final QName CALENDAR_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CalendarService");
|
||||||
|
static final QName NOTIFICATION_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "NotificationService");
|
||||||
|
|
||||||
// WCM / AVM
|
// WCM / AVM
|
||||||
static final QName AVM_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AVMService");
|
static final QName AVM_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AVMService");
|
||||||
@@ -353,6 +355,12 @@ public interface ServiceRegistry
|
|||||||
*/
|
*/
|
||||||
@NotAuditable
|
@NotAuditable
|
||||||
WorkflowService getWorkflowService();
|
WorkflowService getWorkflowService();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the notification service (or null if on is not provided)
|
||||||
|
*/
|
||||||
|
@NotAuditable
|
||||||
|
NotificationService getNotificationService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the audit service (or null if one is not provided)
|
* @return the audit service (or null if one is not provided)
|
||||||
|
@@ -0,0 +1,228 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.service.cmr.notification;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification context. Provides the contextual information about a notification.
|
||||||
|
*
|
||||||
|
* @author Roy Wetherall
|
||||||
|
*/
|
||||||
|
public class NotificationContext
|
||||||
|
{
|
||||||
|
/** Authority name notification is being sent from */
|
||||||
|
private String from;
|
||||||
|
|
||||||
|
/** Authorities notification is being sent to */
|
||||||
|
private List<String> to;
|
||||||
|
|
||||||
|
/** Subject of the notification */
|
||||||
|
private String subject;
|
||||||
|
|
||||||
|
/** Body of the notification */
|
||||||
|
private String body;
|
||||||
|
|
||||||
|
/** Template node used to generate the body of the notification */
|
||||||
|
private NodeRef bodyTemplate;
|
||||||
|
|
||||||
|
/** Template arguments (appear as map under 'arg' property in template model) */
|
||||||
|
private Map<String, Serializable> templateArgs;
|
||||||
|
|
||||||
|
/** Document giving notification context */
|
||||||
|
private NodeRef document;
|
||||||
|
|
||||||
|
/** Indicates whether notification failure should be ignored or not */
|
||||||
|
private boolean ignoreNotificationFailure = true;
|
||||||
|
|
||||||
|
/** Indicates whether the notification should be sent asynchronously or not */
|
||||||
|
private boolean asyncNotification = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor
|
||||||
|
*/
|
||||||
|
public NotificationContext()
|
||||||
|
{
|
||||||
|
to = new ArrayList<String>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param from from authority
|
||||||
|
*/
|
||||||
|
public void setFrom(String from)
|
||||||
|
{
|
||||||
|
this.from = from;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@link String} from authority
|
||||||
|
*/
|
||||||
|
public String getFrom()
|
||||||
|
{
|
||||||
|
return from;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param to to authorities
|
||||||
|
*/
|
||||||
|
public void addTo(String to)
|
||||||
|
{
|
||||||
|
this.to.add(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@link List}<{@link String}> to authorities
|
||||||
|
*/
|
||||||
|
public List<String> getTo()
|
||||||
|
{
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param subject subject of notification
|
||||||
|
*/
|
||||||
|
public void setSubject(String subject)
|
||||||
|
{
|
||||||
|
this.subject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return subject of notification
|
||||||
|
*/
|
||||||
|
public String getSubject()
|
||||||
|
{
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: this takes presendence over the body template if both are set
|
||||||
|
*
|
||||||
|
* @param body body of notification.
|
||||||
|
*/
|
||||||
|
public void setBody(String body)
|
||||||
|
{
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@link String} body of notification
|
||||||
|
*/
|
||||||
|
public String getBody()
|
||||||
|
{
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The body template is a node reference to a template that can be executed with the given
|
||||||
|
* template arguments to produce the body of the notification.
|
||||||
|
*
|
||||||
|
* @param bodyTemplate body template
|
||||||
|
*/
|
||||||
|
public void setBodyTemplate(NodeRef bodyTemplate)
|
||||||
|
{
|
||||||
|
this.bodyTemplate = bodyTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@link NodeRef} body template
|
||||||
|
*/
|
||||||
|
public NodeRef getBodyTemplate()
|
||||||
|
{
|
||||||
|
return bodyTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The template arguments are used as context for the body template when it is executed. Any values placed in this map will
|
||||||
|
* be available in the template from the root object 'args'. For example '${args.workflowDescription}'.
|
||||||
|
*
|
||||||
|
* @param templateArgs template arguments
|
||||||
|
*/
|
||||||
|
public void setTemplateArgs(Map<String, Serializable> templateArgs)
|
||||||
|
{
|
||||||
|
this.templateArgs = templateArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@link Map}<{@link String}, {@link Serializable}> template arguments
|
||||||
|
*/
|
||||||
|
public Map<String, Serializable> getTemplateArgs()
|
||||||
|
{
|
||||||
|
return templateArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Document that the notification relates to. This does not have to be set. Will be used to populate the 'document' root object accessable within the body template
|
||||||
|
* if set.
|
||||||
|
*
|
||||||
|
* @param document related document
|
||||||
|
*/
|
||||||
|
public void setDocument(NodeRef document)
|
||||||
|
{
|
||||||
|
this.document = document;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@link NodeRef} related document
|
||||||
|
*/
|
||||||
|
public NodeRef getDocument()
|
||||||
|
{
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether to ignore a notification failure or not.
|
||||||
|
*
|
||||||
|
* @param ignoreNotificationFailure true if ignore notification failure, false otherwise
|
||||||
|
*/
|
||||||
|
public void setIgnoreNotificationFailure(boolean ignoreNotificationFailure)
|
||||||
|
{
|
||||||
|
this.ignoreNotificationFailure = ignoreNotificationFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return boolean true if ignore notification failure, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isIgnoreNotificationFailure()
|
||||||
|
{
|
||||||
|
return ignoreNotificationFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the notification will be sent asynchronously or not.
|
||||||
|
*
|
||||||
|
* @param asyncNotification true if notification sent asynchronously, false otherwise
|
||||||
|
*/
|
||||||
|
public void setAsyncNotification(boolean asyncNotification)
|
||||||
|
{
|
||||||
|
this.asyncNotification = asyncNotification;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return boolean true if notification send asynchronously, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isAsyncNotification()
|
||||||
|
{
|
||||||
|
return asyncNotification;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.service.cmr.notification;
|
||||||
|
|
||||||
|
import org.alfresco.service.NotAuditable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification Provider interface.
|
||||||
|
*
|
||||||
|
* @author Roy Wetherall
|
||||||
|
*/
|
||||||
|
public interface NotificationProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Gets the name of the notification provider.
|
||||||
|
*
|
||||||
|
* @return notification provider name
|
||||||
|
*/
|
||||||
|
@NotAuditable
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a notification using the notification provider.
|
||||||
|
*
|
||||||
|
* @param notificationContext notification context
|
||||||
|
*/
|
||||||
|
@NotAuditable
|
||||||
|
void sendNotification(NotificationContext notificationContext);
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.service.cmr.notification;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.service.NotAuditable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification Service Interface.
|
||||||
|
*
|
||||||
|
* @author Roy Wetherall
|
||||||
|
*/
|
||||||
|
public interface NotificationService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Registers a notification provider with the notification service.
|
||||||
|
*
|
||||||
|
* @param notificationProvider notification provider
|
||||||
|
*/
|
||||||
|
@NotAuditable
|
||||||
|
void register(NotificationProvider notificationProvider);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of all the currently available notification providers.
|
||||||
|
*
|
||||||
|
* @return {@link List}<{@link String}> notification provider names
|
||||||
|
*/
|
||||||
|
@NotAuditable
|
||||||
|
List<String> getNotificationProviders();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether a notification provider exists or not.
|
||||||
|
*
|
||||||
|
* @param notificationProvider notification provider
|
||||||
|
* @return boolean true if exists, false otherwise
|
||||||
|
*/
|
||||||
|
@NotAuditable
|
||||||
|
boolean exists(String notificationProvider);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send notification using the names notification provider and notification context.
|
||||||
|
*
|
||||||
|
* @param notificationProvider notification provider
|
||||||
|
* @param notificationContext notification context
|
||||||
|
*/
|
||||||
|
@NotAuditable
|
||||||
|
void sendNotification(String notificationProvider, NotificationContext notificationContext);
|
||||||
|
}
|
@@ -20,7 +20,9 @@ package org.alfresco.util;
|
|||||||
|
|
||||||
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
import org.alfresco.service.ServiceRegistry;
|
import org.alfresco.service.ServiceRegistry;
|
||||||
import org.alfresco.service.cmr.action.ActionService;
|
import org.alfresco.service.cmr.action.ActionService;
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
@@ -82,6 +84,14 @@ public abstract class BaseAlfrescoTestCase extends RetryingTransactionHelperTest
|
|||||||
ctx = ApplicationContextHelper.getApplicationContext();
|
ctx = ApplicationContextHelper.getApplicationContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if using spaces store, otherwise creates own store
|
||||||
|
*/
|
||||||
|
protected boolean useSpacesStore()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see junit.framework.TestCase#setUp()
|
* @see junit.framework.TestCase#setUp()
|
||||||
*/
|
*/
|
||||||
@@ -102,13 +112,31 @@ public abstract class BaseAlfrescoTestCase extends RetryingTransactionHelperTest
|
|||||||
this.transactionService = serviceRegistry.getTransactionService();
|
this.transactionService = serviceRegistry.getTransactionService();
|
||||||
this.retryingTransactionHelper = (RetryingTransactionHelper)ctx.getBean("retryingTransactionHelper");
|
this.retryingTransactionHelper = (RetryingTransactionHelper)ctx.getBean("retryingTransactionHelper");
|
||||||
|
|
||||||
// Authenticate as the system user - this must be done before we create the store
|
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Object>()
|
||||||
authenticationComponent.setSystemUserAsCurrentUser();
|
{
|
||||||
|
@Override
|
||||||
|
public Object execute() throws Throwable
|
||||||
|
{
|
||||||
|
// As system user
|
||||||
|
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
||||||
|
|
||||||
// Create the store and get the root node
|
if (useSpacesStore() == false)
|
||||||
this.storeRef = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
|
{
|
||||||
this.rootNodeRef = this.nodeService.getRootNode(this.storeRef);
|
// Create the store and get the root node
|
||||||
|
storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use the spaces store
|
||||||
|
storeRef = StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the root node reference
|
||||||
|
rootNodeRef = nodeService.getRootNode(storeRef);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -126,15 +154,24 @@ public abstract class BaseAlfrescoTestCase extends RetryingTransactionHelperTest
|
|||||||
@Override
|
@Override
|
||||||
protected void tearDown() throws Exception
|
protected void tearDown() throws Exception
|
||||||
{
|
{
|
||||||
try
|
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Object>()
|
||||||
{
|
{
|
||||||
authenticationComponent.clearCurrentSecurityContext();
|
@Override
|
||||||
}
|
public Object execute() throws Throwable
|
||||||
catch (Throwable e)
|
{
|
||||||
{
|
// As system user
|
||||||
e.printStackTrace();
|
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
||||||
// Don't let this mask any previous exceptions
|
|
||||||
}
|
if (useSpacesStore() == false)
|
||||||
|
{
|
||||||
|
// Delete the created store
|
||||||
|
nodeService.deleteStore(storeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
super.tearDown();
|
super.tearDown();
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -53,6 +53,17 @@ public abstract class TestWithUserUtils
|
|||||||
NodeService nodeService,
|
NodeService nodeService,
|
||||||
MutableAuthenticationService authenticationService)
|
MutableAuthenticationService authenticationService)
|
||||||
{
|
{
|
||||||
|
createUser(userName, password, null, rootNodeRef, nodeService, authenticationService);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void createUser(
|
||||||
|
String userName,
|
||||||
|
String password,
|
||||||
|
String email,
|
||||||
|
NodeRef rootNodeRef,
|
||||||
|
NodeService nodeService,
|
||||||
|
MutableAuthenticationService authenticationService)
|
||||||
|
{
|
||||||
// ignore if the user's authentication already exists
|
// ignore if the user's authentication already exists
|
||||||
if (authenticationService.authenticationExists(userName))
|
if (authenticationService.authenticationExists(userName))
|
||||||
{
|
{
|
||||||
@@ -69,10 +80,13 @@ public abstract class TestWithUserUtils
|
|||||||
|
|
||||||
HashMap<QName, Serializable> properties = new HashMap<QName, Serializable>();
|
HashMap<QName, Serializable> properties = new HashMap<QName, Serializable>();
|
||||||
properties.put(ContentModel.PROP_USERNAME, userName);
|
properties.put(ContentModel.PROP_USERNAME, userName);
|
||||||
|
if (email != null && email.length() != 0)
|
||||||
|
{
|
||||||
|
properties.put(ContentModel.PROP_EMAIL, email);
|
||||||
|
}
|
||||||
nodeService.createNode(typesNodeRef, children, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, userName) , container, properties);
|
nodeService.createNode(typesNodeRef, children, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, userName) , container, properties);
|
||||||
|
|
||||||
// Create the users
|
// Create the users
|
||||||
|
|
||||||
authenticationService.createAuthentication(userName, password.toCharArray());
|
authenticationService.createAuthentication(userName, password.toCharArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user