All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sakaiproject.content.impl.DropboxNotification Maven / Gradle / Ivy

There is a newer version: 23.3
Show newest version
/**********************************************************************************
 * $URL$
 * $Id$
 ***********************************************************************************
 *
 * Copyright (c) 2007, 2008 Sakai Foundation
 *
 * Licensed under the Educational Community License, Version 2.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/ECL-2.0
 *
 * 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 org.sakaiproject.content.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Collection;
import java.util.HashSet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.authz.api.SecurityService;
import org.sakaiproject.authz.api.Member;
import org.sakaiproject.component.api.ServerConfigurationService;
import org.sakaiproject.component.cover.ComponentManager;
import org.sakaiproject.content.api.ContentCollection;
import org.sakaiproject.content.api.ContentHostingService;
import org.sakaiproject.entity.api.Entity;
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.NotificationAction;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.exception.PermissionException;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.SiteService;
import org.sakaiproject.user.api.User;
import org.sakaiproject.user.api.UserDirectoryService;
import org.sakaiproject.user.api.UserNotDefinedException;
import org.sakaiproject.util.EmailNotification;
import org.sakaiproject.util.Resource;
import org.sakaiproject.util.ResourceLoader;
import org.sakaiproject.util.StringUtil;
import org.sakaiproject.util.FormattedText;


/**
 * 

* DropboxNotification is the notification action that handles the act of message (email) based notify related to changes in an individual dropbox. *

*

* The following should be specified to extend the class: *

    *
  • getRecipients() - get a collection of Users to send the notification to
  • *
  • getHeaders() - form the complete message headers (like from: to: reply-to: date: subject: etc). from: and to: are for display only
  • *
  • htmlContent() and plainTextContent() - form the complete message body (minus headers)
  • *
  • getTag() - the part of the body at the end that identifies the list
  • *
*

*

* getClone() should also be extended to clone the proper type of object. *

*/ public class DropboxNotification extends EmailNotification { static final Log logger = LogFactory.getLog(DropboxNotification.class); /* property bundles */ private static final String DEFAULT_RESOURCECLASS = "org.sakaiproject.localization.util.SiteemaconProperties"; private static final String DEFAULT_RESOURCEBUNDLE = "org.sakaiproject.localization.bundle.siteemacon.siteemacon"; private static final String RESOURCECLASS = "resource.class.siteemacon"; private static final String RESOURCEBUNDLE = "resource.bundle.siteemacon"; private String resourceClass; private String resourceBundle; private ResourceLoader rb; // private static ResourceBundle rb = ResourceBundle.getBundle("siteemacon"); private final String MULTIPART_BOUNDARY = "======sakai-multi-part-boundary======"; private final String BOUNDARY_LINE = "\n\n--"+MULTIPART_BOUNDARY+"\n"; private final String TERMINATION_LINE = "\n\n--"+MULTIPART_BOUNDARY+"--\n\n"; private final String MIME_ADVISORY = "This message is for MIME-compliant mail readers."; private SecurityService securityService; private ContentHostingService contentHostingService; private EntityManager entityManager; private SiteService siteService; private UserDirectoryService userDirectoryService; private ServerConfigurationService serverConfigurationService; /** * The preferred form for construction is to supply the needed items rather than having to do a lookup. This constructor was * left in place for compatibility with any custom tool that might currently be using it, but should be considered deprecated. * * @deprecated */ public DropboxNotification() { this.securityService = (SecurityService) ComponentManager.get("org.sakaiproject.authz.api.SecurityService"); this.contentHostingService = (ContentHostingService) ComponentManager.get("org.sakaiproject.content.api.ContentHostingService"); this.entityManager = (EntityManager) ComponentManager.get("org.sakaiproject.entity.api.EntityManager"); this.siteService = (SiteService) ComponentManager.get("org.sakaiproject.site.api.SiteService"); this.userDirectoryService = (UserDirectoryService) ComponentManager.get("org.sakaiproject.user.api.UserDirectoryService"); this.serverConfigurationService = (ServerConfigurationService) ComponentManager .get("org.sakaiproject.component.api.ServerConfigurationService"); } private void loadResources() { resourceClass = serverConfigurationService.getString(RESOURCECLASS, DEFAULT_RESOURCECLASS); resourceBundle = serverConfigurationService.getString(RESOURCEBUNDLE, DEFAULT_RESOURCEBUNDLE); rb = new Resource().getLoader(resourceClass, resourceBundle); } public DropboxNotification(SecurityService securityService, ContentHostingService contentHostingService, EntityManager entityManager, SiteService siteService, UserDirectoryService userDirectoryService, ServerConfigurationService serverConfigurationService) { this.securityService = securityService; this.contentHostingService = contentHostingService; this.entityManager = entityManager; this.siteService = siteService; this.userDirectoryService = userDirectoryService; this.serverConfigurationService = serverConfigurationService; loadResources(); } /* (non-Javadoc) * @see org.sakaiproject.util.EmailNotification#getClone() */ @Override public NotificationAction getClone() { // TODO Auto-generated method stub return super.getClone(); } /* (non-Javadoc) * @see org.sakaiproject.util.EmailNotification#getHeaders(org.sakaiproject.event.api.Event) */ @Override protected List getHeaders(Event event) { List rv = super.getHeaders(event); // the Subject rv.add("Subject: " + getSubject(event)); // from rv.add(getFrom(event)); // to List toList = getRecipients(event); Iterator itr = toList.iterator(); StringBuilder recips = new StringBuilder(); while (itr.hasNext()) { User usr = (User) itr.next(); recips.append(usr.getEmail() + ", "); } rv.add("To: " + recips.toString()); return rv; } /** * Extract a 'Set' of user ids from the given set of members. * * @param members The Set of members from which to extract the userIds * @return * The set of user ids that belong to the users in the member set. */ private Set getUserIds(Collection members) { Set userIds = new HashSet(); for (Member member : members) userIds.add(member.getUserId()); return userIds; } /** * Only include actual site members in the notification. * * @param users * List of users that emails would be sent to. * @param site * Site that the emails would be sent to * @return * Refined list of users who are members of this site. */ protected void refineToSiteMembers(List users, Site site) { Set members = site.getMembers(); Set memberUserIds = getUserIds(members); for (Iterator i = users.listIterator(); i.hasNext();) { User user = i.next(); if (!memberUserIds.contains(user.getId())) { i.remove(); } } } /** * Get the list of User objects who are eligible to receive the notification email. * * @param event * The event that matched criteria to cause the notification. * @return the list of User objects who are eligible to receive the notification email. */ protected List getRecipients(Event event) { List recipients = new ArrayList(); String resourceRef = event.getResource(); Reference ref = entityManager.newReference(resourceRef); String siteId = (getSite() != null) ? getSite() : ref.getContext(); Site site; // get a site try { site = siteService.getSite(siteId); } catch (IdUnusedException e) { logger.warn("Could not getSite for " + siteId + " not returning any recipients."); return recipients; } ResourceProperties props = ref.getProperties(); String modifiedBy = props.getProperty(ResourceProperties.PROP_MODIFIED_BY); String parts[] = resourceRef.split("/"); if(parts.length >= 4) { String dropboxOwnerId = parts[4]; if(modifiedBy != null && modifiedBy.equals(dropboxOwnerId)) { // notify instructor(s) StringBuilder buf = new StringBuilder(); buf.append("/content/group-user/"); buf.append(parts[3]); buf.append("/"); String siteDropbox = buf.toString(); recipients.addAll(securityService.unlockUsers(contentHostingService.AUTH_DROPBOX_MAINTAIN, siteDropbox)); refineToSiteMembers(recipients, site); } else { // notify student try { User user = userDirectoryService.getUser(dropboxOwnerId); recipients.add(user); } catch(UserNotDefinedException e0) { try { User user = userDirectoryService.getUserByEid(dropboxOwnerId); recipients.add(user); } catch(UserNotDefinedException e1) { logger.warn("UserNotDefinedException trying to get user: " + dropboxOwnerId); } } } } return recipients; } protected String getSiteDropboxCollectionId(String id) { StringBuilder buf = new StringBuilder(); String parts[] = id.split("/"); if(parts.length >= 3) { buf.append("/group-user/"); buf.append(parts[2]); buf.append("/"); } return buf.toString(); } /* (non-Javadoc) * @see org.sakaiproject.util.EmailNotification#getTag(java.lang.String, java.lang.String) */ @Override protected String getTag(String title, boolean shouldUseHtml) { // tbd: move from addMessageText return ""; } protected String plainTextContent(Event event) { return generateContentForType(false, event); } protected String htmlContent(Event event) { return generateContentForType(true, event); } private String generateContentForType(boolean shouldProduceHtml, Event event) { // get the content & properties Reference ref = entityManager.newReference(event.getResource()); // TODO: ResourceProperties props = ref.getProperties(); // get the function String function = event.getEvent(); String subject = getSubject(event); // use either the configured site, or if not configured, the site (context) of the resource String siteId = (getSite() != null) ? getSite() : ref.getContext(); // get a site title String title = siteId; try { Site site = siteService.getSite(siteId); title = site.getTitle(); } catch (Exception ignore) { } StringBuilder buf = new StringBuilder(); addMessageText(buf, ref, subject, title, function, shouldProduceHtml); return buf.toString(); } /** * @inheritDoc */ private void addMessageText(StringBuilder buf, Reference ref, String subject, String siteTitle, String function, boolean doHtml) { ResourceProperties props = ref.getProperties(); String resourceName = props.getPropertyFormatted(ResourceProperties.PROP_DISPLAY_NAME); String description = props.getPropertyFormatted(ResourceProperties.PROP_DESCRIPTION); String url = ref.getUrl(); String blankLine = "\n\n"; String newLine = "\n"; String dropboxId = contentHostingService.getIndividualDropboxId(ref.getId()); String dropboxTitle = null; try { ResourceProperties dbProps = contentHostingService.getProperties(dropboxId); dropboxTitle = dbProps.getPropertyFormatted(ResourceProperties.PROP_DISPLAY_NAME); } catch (PermissionException e) { logger.warn("PermissionException trying to get title for individual dropbox: " + dropboxId); } catch (IdUnusedException e) { logger.warn("IdUnusedException trying to get title for individual dropbox: " + dropboxId); } if ( doHtml ) { siteTitle = FormattedText.escapeHtmlFormattedTextarea(siteTitle); subject = FormattedText.escapeHtmlFormattedTextarea(subject); resourceName = FormattedText.escapeHtmlFormattedTextarea(resourceName); description = FormattedText.escapeHtmlFormattedTextarea(description); dropboxTitle = FormattedText.escapeHtmlFormattedTextarea(dropboxTitle); blankLine = "\n

\n"; newLine = "
\n"; } // get the resource copyright alert property boolean copyrightAlert = props.getProperty(ResourceProperties.PROP_COPYRIGHT_ALERT) != null ? true : false; // Now build up the message text. if (doHtml) { buf.append("

"); } String portalName = serverConfigurationService.getString("ui.service", "Sakai"); String portalUrl = serverConfigurationService.getPortalUrl(); if(doHtml) { portalUrl = "" + portalName + ""; } if (contentHostingService.EVENT_RESOURCE_AVAILABLE.equals(function)) { buf.append(rb.getFormattedMessage("db.text.new", new String[]{dropboxTitle, siteTitle, portalName, portalUrl})); } else { buf.append(rb.getFormattedMessage("db.text.upd", new String[]{dropboxTitle, siteTitle, portalName, portalUrl})); } buf.append(blankLine); // add location String path = constructPath(ref.getReference()); String item = resourceName; if(copyrightAlert) { item += " (c)"; } if(doHtml) { item = "" + item + ""; } buf.append(rb.getFormattedMessage("db.text.location", new String[]{siteTitle, path, item})); buf.append(blankLine); // resource description if ((description != null) && (description.length() > 0)) { buf.append(rb.getString("descrip") + " " + description); buf.append(blankLine); } // add a reference to the resource for non-HTML if ( ! doHtml ) { buf.append("\n" + rb.getString("resour") + " " + resourceName); if (copyrightAlert) { buf.append(" (c)"); } buf.append(" " + url); buf.append("\n\n"); // End on a blank line } // Add the tag if (doHtml) { buf.append("


"); } else { buf.append(rb.getString("separator")); } buf.append(newLine); buf.append(rb.getFormattedMessage("db.text.prefs", new String[]{portalName, portalUrl, siteTitle})); if (doHtml) { buf.append("

"); } } /** * Get the subject for the email. * * @param event * The event that matched criteria to cause the notification. * @return the subject for the email. */ protected String getSubject(Event event) { Reference ref = entityManager.newReference(event.getResource()); Entity r = ref.getEntity(); 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() : ref.getContext(); // get a site title String siteTitle = siteId; try { Site site = siteService.getSite(siteId); siteTitle = site.getTitle(); } catch (Exception ignore) { } // use the message's subject String resourceName = props.getPropertyFormatted(ResourceProperties.PROP_DISPLAY_NAME); String dropboxId = contentHostingService.getIndividualDropboxId(ref.getId()); String dropboxTitle = null; try { ResourceProperties dbProps = contentHostingService.getProperties(dropboxId); dropboxTitle = dbProps.getPropertyFormatted(ResourceProperties.PROP_DISPLAY_NAME); } catch (PermissionException e) { logger.warn("PermissionException trying to get title for individual dropbox: " + dropboxId); } catch (IdUnusedException e) { logger.warn("IdUnusedException trying to get title for individual dropbox: " + dropboxId); } String[] args = {siteTitle, dropboxTitle, resourceName}; return rb.getFormattedMessage((contentHostingService.EVENT_RESOURCE_AVAILABLE.equals(function) ? "db.subj.new" : "db.subj.upd"), args); } /** * Form a "Bread Crumb" style path showing the folders in which this referenced resource lives, starting with the individual dropbox. * * @param ref * The reference string to the resource. * @return The path string for this resource. */ protected String constructPath(String ref) { StringBuilder buf = new StringBuilder(); // expect the ref to be /content/group/site/folder/folder2/folderEtc/file.ext String[] parts = StringUtil.split(ref, Entity.SEPARATOR); // 0 is null, 1 is "content", 2 is "group-user", 3 is the site-id, 4 is the user-id, the last is the file name if (parts.length > 4) { // grow this collection id as we descend into the collections String root = Entity.SEPARATOR + parts[2] + Entity.SEPARATOR + parts[3] + Entity.SEPARATOR; StringBuilder rootBuilder = new StringBuilder(); rootBuilder.append(root); // take all the collection parts for (int i = 4; i < parts.length - 1; i++) { buf.append(" > "); String collectionId = parts[i]; rootBuilder.append(collectionId + Entity.SEPARATOR); try { // get the display name ContentCollection collection = contentHostingService.getCollection(rootBuilder.toString()); buf.append(collection.getProperties().getPropertyFormatted(ResourceProperties.PROP_DISPLAY_NAME)); } catch (Exception any) { // use the id if there's a problem buf.append(collectionId); } } } return buf.toString(); } public void setSecurityService(SecurityService securityService) { this.securityService = securityService; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy