/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/rwiki/branches/sakai-2.8.1/rwiki-impl/impl/src/java/uk/ac/cam/caret/sakai/rwiki/component/service/impl/SiteEmailNotificationRWiki.java $
* $Id: SiteEmailNotificationRWiki.java 62986 2009-05-28 09:57:23Z s.swinsburg@lancaster.ac.uk $
***********************************************************************************
*
* Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
*
* Licensed under the Educational Community License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ecl1.php
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**********************************************************************************/
package uk.ac.cam.caret.sakai.rwiki.component.service.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Vector;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.authz.api.SecurityService;
import org.sakaiproject.component.cover.ServerConfigurationService;
import org.sakaiproject.email.api.DigestService;
import org.sakaiproject.entity.api.EntityManager;
import org.sakaiproject.entity.api.Reference;
import org.sakaiproject.entity.api.ResourceProperties;
import org.sakaiproject.event.api.Event;
import org.sakaiproject.event.api.Notification;
import org.sakaiproject.event.api.NotificationAction;
import org.sakaiproject.event.api.NotificationService;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.SiteService;
import org.sakaiproject.thread_local.api.ThreadLocalManager;
import org.sakaiproject.time.api.TimeService;
import org.sakaiproject.user.api.User;
import org.sakaiproject.user.api.UserDirectoryService;
import org.sakaiproject.user.api.UserNotDefinedException;
import org.sakaiproject.util.SiteEmailNotification;
import org.sakaiproject.util.Web;
import uk.ac.cam.caret.sakai.rwiki.component.Messages;
import uk.ac.cam.caret.sakai.rwiki.service.api.RWikiObjectService;
import uk.ac.cam.caret.sakai.rwiki.service.api.RenderService;
import uk.ac.cam.caret.sakai.rwiki.service.api.model.RWikiEntity;
import uk.ac.cam.caret.sakai.rwiki.service.api.model.RWikiObject;
import uk.ac.cam.caret.sakai.rwiki.service.message.api.PreferenceService;
import uk.ac.cam.caret.sakai.rwiki.utils.DigestHtml;
import uk.ac.cam.caret.sakai.rwiki.utils.NameHelper;
/**
* <p>
* SiteEmailNotificationRWiki fills the notification message and headers with
* details from the content change that triggered the notification event.
* </p>
*
* @author Sakai Software Development Team
* @author ieb
*/
public class SiteEmailNotificationRWiki extends SiteEmailNotification {
public class MessageContent {
public String title;
public String user;
public String content;
public String moddate;
public String localName;
public String url;
public String contentHTML;
}
private static Log log = LogFactory
.getLog(SiteEmailNotificationRWiki.class);
private RenderService renderService = null;
private RWikiObjectService rwikiObjectService = null;
private PreferenceService preferenceService = null;
private SiteService siteService;
private SecurityService securityService;
private EntityManager entityManager;
private ThreadLocalManager threadLocalManager;
private TimeService timeService;
private DigestService digestService;
private UserDirectoryService userDirectoryService;
/**
* Construct.
*/
public SiteEmailNotificationRWiki(RWikiObjectService rwikiObjectService,
RenderService renderService, PreferenceService preferenceService,
SiteService siteService, SecurityService securityService,
EntityManager entityManager, ThreadLocalManager threadLocalManager,
TimeService timeService, DigestService digestService, UserDirectoryService userDirectoryService) {
this.renderService = renderService;
this.rwikiObjectService = rwikiObjectService;
this.preferenceService = preferenceService;
this.siteService = siteService;
this.securityService = securityService;
this.entityManager = entityManager;
this.threadLocalManager = threadLocalManager;
this.timeService = timeService;
this.digestService = digestService;
this.userDirectoryService = userDirectoryService;
}
/**
* Construct.
*/
public SiteEmailNotificationRWiki(RWikiObjectService rwikiObjectService,
RenderService renderService, PreferenceService preferenceService,
SiteService siteService, SecurityService securityService,
EntityManager entityManager, ThreadLocalManager threadLocalManager,
TimeService timeService, DigestService digestService, UserDirectoryService userDirectoryService, String siteId) {
super(siteId);
this.renderService = renderService;
this.rwikiObjectService = rwikiObjectService;
this.preferenceService = preferenceService;
this.siteService = siteService;
this.securityService = securityService;
this.entityManager = entityManager;
this.threadLocalManager = threadLocalManager;
this.timeService = timeService;
this.digestService = digestService;
this.userDirectoryService = userDirectoryService;
}
/**
* @inheritDoc
*/
public NotificationAction getClone() {
SiteEmailNotificationRWiki clone = new SiteEmailNotificationRWiki(
rwikiObjectService, renderService, preferenceService,
siteService, securityService, entityManager,
threadLocalManager, timeService, digestService, userDirectoryService);
clone.set(this);
return clone;
}
protected String getSiteId(String context) {
if (context.startsWith("/site/")) //$NON-NLS-1$
{
context = context.substring("/site/".length()); //$NON-NLS-1$
}
int il = context.indexOf("/"); //$NON-NLS-1$
if (il != -1) {
context = context.substring(0, il);
}
return context;
}
/**
* @inheritDoc
*/
protected String getPlainMessage(Event event) {
MessageContent mc = getMessageContent(event);
String message = Messages.getString("SiteEmailNotificationRWiki.5") + mc.title + Messages.getString("SiteEmailNotificationRWiki.6") //$NON-NLS-1$ //$NON-NLS-2$
+ ServerConfigurationService.getString("ui.service", "Sakai") + " (" + ServerConfigurationService.getPortalUrl() //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ ") " + " \n" + " \n" + Messages.getString("SiteEmailNotificationRWiki.13") + mc.title + "\" > Wiki > " + mc.localName + "\n" + Messages.getString("SiteEmailNotificationRWiki.16") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
+ mc.moddate
+ "\n" + Messages.getString("SiteEmailNotificationRWiki.18") + mc.user + "\n" + " \n" + " Page: " + mc.localName + " " + mc.url + " \n" + " \n" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ Messages.getString("SiteEmailNotificationRWiki.4") + mc.content + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
log.debug("Message is " + message);
return message;
}
protected String getHtmlMessage(Event event) {
MessageContent mc = getMessageContent(event);
String message =
Messages.getString("SiteEmailNotificationRWiki.5") + mc.title + Messages.getString("SiteEmailNotificationRWiki.6") //$NON-NLS-1$ //$NON-NLS-2$
+ ServerConfigurationService.getString("ui.service", "Sakai") + " (" + ServerConfigurationService.getPortalUrl() //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ ") " + " \n" + " \n" + Messages.getString("SiteEmailNotificationRWiki.13") + mc.title + "\" > Wiki > " + mc.localName + "\n" + Messages.getString("SiteEmailNotificationRWiki.16") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
+ mc.moddate
+ "\n" + Messages.getString("SiteEmailNotificationRWiki.18") + mc.user + "\n" + " \n" + " Page: " + mc.localName + " " + mc.url + " \n" + " \n" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ Messages.getString("SiteEmailNotificationRWiki.4");
message = Web.escapeHtml(message, true) + mc.contentHTML;
log.debug("Message is " + message);
return message;
}
private MessageContent getMessageContent(Event event) {
MessageContent messageContent = new MessageContent();
// get the content & properties
Reference ref = entityManager.newReference(event.getResource());
ResourceProperties props = ref.getProperties();
// get the function
// String function = event.getEvent();
// use either the configured site, or if not configured, the site
// (context) of the resource
String siteId = (getSite() != null) ? getSite() : getSiteId(ref
.getContext());
try {
Site site = siteService.getSite(siteId);
messageContent.title = site.getTitle();
} catch (IdUnusedException e) {
messageContent.title = siteId;
}
// get the URL and resource name.
// StringBuffer buf = new StringBuffer();
messageContent.url = ref.getUrl() + "html"; //$NON-NLS-1$
String pageName = props.getProperty(RWikiEntity.RP_NAME);
String realm = props.getProperty(RWikiEntity.RP_REALM);
messageContent.localName = NameHelper.localizeName(pageName, realm);
String userId = props.getProperty(RWikiEntity.RP_USER);
try {
User u = userDirectoryService.getUser(userId);
messageContent.user = u.getDisplayId();
} catch (UserNotDefinedException e) {
messageContent.user = userId;
}
messageContent.moddate = new Date(Long.parseLong(props
.getProperty(RWikiEntity.RP_VERSION))).toString();
try {
RWikiEntity rwe = (RWikiEntity) rwikiObjectService.getEntity(ref);
RWikiObject rwikiObject = rwe.getRWikiObject();
String pageSpace = NameHelper.localizeSpace(pageName, realm);
ComponentPageLinkRenderImpl cplr = new ComponentPageLinkRenderImpl(
pageSpace, true);
messageContent.contentHTML = renderService.renderPage(rwikiObject, pageSpace, cplr);
messageContent.content = DigestHtml.digest(messageContent.contentHTML);
} catch (Exception ex) {
}
return messageContent;
}
@Override
protected String plainTextContent(Event event) {
return getPlainMessage(event);
}
@Override
protected String htmlContent(Event event) {
return getHtmlMessage(event);
}
/**
* @inheritDoc
*/
protected List getHeaders(Event e) {
List rv = super.getHeaders(e);
Reference ref = entityManager.newReference(e.getResource());
ResourceProperties props = ref.getProperties();
String pageName = props.getProperty(RWikiEntity.RP_NAME);
String realm = props.getProperty(RWikiEntity.RP_REALM);
String localName = NameHelper.localizeName(pageName, realm);
String subjectHeader = Messages
.getString("SiteEmailNotificationRWiki.27") + localName + Messages.getString("SiteEmailNotificationRWiki.28"); //$NON-NLS-1$ //$NON-NLS-2$
// the Subject
rv.add(subjectHeader);
// from
rv.add(getFrom(e));
// to
rv.add(getTo(e));
return rv;
}
/**
* @inheritDoc
*/
protected String getTag(String newline, String title) {
// tag the message
String rv = "----------------------\n" + Messages.getString("SiteEmailNotificationRWiki.30") //$NON-NLS-1$ //$NON-NLS-2$
+ ServerConfigurationService.getString("ui.service", "Sakai") + " (" + ServerConfigurationService.getPortalUrl() //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ Messages.getString("SiteEmailNotificationRWiki.3") + title + Messages.getString("SiteEmailNotificationRWiki.35") //$NON-NLS-1$ //$NON-NLS-2$
+ Messages.getString("SiteEmailNotificationRWiki.36"); //$NON-NLS-1$
/*
* String rv = newline + "------" + newline + rb.getString("this") + " " +
* ServerConfigurationService.getString("ui.service", "Sakai") + " (" +
* ServerConfigurationService.getPortalUrl() + ") " +
* rb.getString("forthe") + " " + title + " " + rb.getString("site") +
* newline + rb.getString("youcan") + newline;
*/
return rv;
}
protected int getOption(User user, String notificationId, String resourceFilter, int eventPriority, Event event) {
// FIXME I don't think this should be here, but it certainly shouldn't
// be in preferenceService
// We really want a entity reference to page name, without going via the
// db!
String resourceReference = event.getResource();
if (resourceReference == null
|| !resourceReference
.startsWith(RWikiObjectService.REFERENCE_ROOT)
|| resourceReference.length() == RWikiObjectService.REFERENCE_ROOT
.length()) {
return NotificationService.PREF_IGNORE;
}
resourceReference = resourceReference.substring(
RWikiObjectService.REFERENCE_ROOT.length(), resourceReference
.lastIndexOf('.'));
String preference = preferenceService.findPreferenceAt(user.getId(),
resourceReference, PreferenceService.MAIL_NOTIFCIATION);
if (preference == null || "".equals(preference)) //$NON-NLS-1$
{
return NotificationService.PREF_IGNORE;
}
if (PreferenceService.NONE_PREFERENCE.equals(preference)) {
return NotificationService.PREF_IGNORE;
}
if (PreferenceService.DIGEST_PREFERENCE.equals(preference)) {
return NotificationService.PREF_DIGEST;
}
if (PreferenceService.SEPARATE_PREFERENCE.equals(preference)) {
return NotificationService.PREF_IMMEDIATE;
}
return NotificationService.PREF_IGNORE;
}
/**
* @inheritDoc
*/
protected List getRecipients(Event event) {
// get the resource reference
Reference ref = entityManager.newReference(event.getResource());
// use either the configured site, or if not configured, the site
// (context) of the resource
String siteId = getSite();
if (siteId == null) {
siteId = getSiteId(ref.getContext());
}
// if the site is published, use the list of users who can SITE_VISIT
// the site,
// else use the list of users who can SITE_VISIT_UNP the site.
try {
Site site = siteService.getSite(siteId);
String ability = SiteService.SITE_VISIT;
if (!site.isPublished()) {
ability = SiteService.SITE_VISIT_UNPUBLISHED;
}
// get the list of users who can do the right kind of visit
List users = securityService.unlockUsers(ability, ref
.getReference());
// get the list of users who have the appropriate access to the
// resource
if (getResourceAbility() != null) {
List users2 = securityService.unlockUsers(getResourceAbility(),
ref.getReference());
// find intersection of users and user2
users.retainAll(users2);
}
// add any other users
addSpecialRecipients(users, ref);
return users;
} catch (Exception any) {
log.error("Exception in getRecipients()", any); //$NON-NLS-1$
return new Vector();
}
}
}