/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/mailarchive/trunk/mailarchive-impl/impl/src/java/org/sakaiproject/mailarchive/impl/BaseMailArchiveService.java $
* $Id: BaseMailArchiveService.java 131324 2013-11-07 20:22:01Z matthew@longsight.com $
***********************************************************************************
*
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 The 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.mailarchive.impl;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Stack;
import java.util.Vector;
import javax.mail.internet.MimeUtility;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.alias.cover.AliasService;
import org.sakaiproject.authz.cover.FunctionManager;
import org.sakaiproject.authz.cover.SecurityService;
import org.sakaiproject.entity.api.ContextObserver;
import org.sakaiproject.entity.api.Edit;
import org.sakaiproject.entity.api.Entity;
import org.sakaiproject.entity.api.Reference;
import org.sakaiproject.entity.api.ResourceProperties;
import org.sakaiproject.event.api.NotificationEdit;
import org.sakaiproject.event.api.NotificationService;
import org.sakaiproject.exception.IdInvalidException;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.exception.IdUsedException;
import org.sakaiproject.exception.InUseException;
import org.sakaiproject.exception.PermissionException;
import org.sakaiproject.mailarchive.api.MailArchiveChannel;
import org.sakaiproject.mailarchive.api.MailArchiveChannelEdit;
import org.sakaiproject.mailarchive.api.MailArchiveMessage;
import org.sakaiproject.mailarchive.api.MailArchiveMessageEdit;
import org.sakaiproject.mailarchive.api.MailArchiveMessageHeader;
import org.sakaiproject.mailarchive.api.MailArchiveMessageHeaderEdit;
import org.sakaiproject.mailarchive.api.MailArchiveService;
import org.sakaiproject.message.api.Message;
import org.sakaiproject.message.api.MessageChannel;
import org.sakaiproject.message.api.MessageChannelEdit;
import org.sakaiproject.message.api.MessageHeader;
import org.sakaiproject.message.api.MessageHeaderEdit;
import org.sakaiproject.message.util.BaseMessage;
import org.sakaiproject.site.cover.SiteService;
import org.sakaiproject.time.api.Time;
import org.sakaiproject.time.cover.TimeService;
import org.sakaiproject.user.api.User;
import org.sakaiproject.util.BaseResourcePropertiesEdit;
import org.sakaiproject.util.FormattedText;
import org.apache.commons.lang.StringUtils;
import org.sakaiproject.util.Xml;
import org.sakaiproject.util.Web;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* <p>
* BaseMailArchiveService extends the BaseMessage for the specifics of MailArchive.
* </p>
*/
public abstract class BaseMailArchiveService extends BaseMessage implements MailArchiveService, ContextObserver
{
/** Our logger. */
private static Log M_log = LogFactory.getLog(BaseMailArchiveService.class);
/**********************************************************************************************************************************************************************************************************************************************************
* Constructors, Dependencies and their setter methods
*********************************************************************************************************************************************************************************************************************************************************/
/** Dependency: NotificationService. */
protected NotificationService m_notificationService = null;
/**
* Dependency: NotificationService.
*
* @param service
* The NotificationService.
*/
public void setNotificationService(NotificationService service)
{
m_notificationService = service;
}
/**********************************************************************************************************************************************************************************************************************************************************
* Init and Destroy
*********************************************************************************************************************************************************************************************************************************************************/
/**
* Final initialization, once all dependencies are set.
*/
public void init()
{
try
{
super.init();
// register a transient notification for mail
NotificationEdit edit = m_notificationService.addTransientNotification();
// set function
edit.setFunction(eventId(SECURE_ADD));
// set the filter to any email resource (see messageReference())
edit.setResourceFilter(getAccessPoint(true) + Entity.SEPARATOR + REF_TYPE_MESSAGE);
// set the action
edit.setAction(new SiteEmailNotificationMail());
// register functions
FunctionManager.registerFunction(eventId(SECURE_READ));
FunctionManager.registerFunction(eventId(SECURE_ADD));
FunctionManager.registerFunction(eventId(SECURE_REMOVE_ANY));
// entity producer registration
m_entityManager.registerEntityProducer(this, REFERENCE_ROOT);
M_log.info("init()");
}
catch (Throwable t)
{
M_log.warn("init(): ", t);
}
} // init
/**********************************************************************************************************************************************************************************************************************************************************
* StorageUser implementation
*********************************************************************************************************************************************************************************************************************************************************/
/**
* Construct a new continer given just ids.
*
* @param ref
* The channel reference.
* @return The new containe Resource.
*/
public Entity newContainer(String ref)
{
return new BaseMailArchiveChannelEdit(ref);
}
/**
* Construct a new container resource, from an XML element.
*
* @param element
* The XML.
* @return The new container resource.
*/
public Entity newContainer(Element element)
{
return new BaseMailArchiveChannelEdit(element);
}
/**
* Construct a new container resource, as a copy of another
*
* @param other
* The other contianer to copy.
* @return The new container resource.
*/
public Entity newContainer(Entity other)
{
return new BaseMailArchiveChannelEdit((MessageChannel) other);
}
/**
* Construct a new rsource given just an id.
*
* @param container
* The Resource that is the container for the new resource (may be null).
* @param id
* The id for the new object.
* @param others
* (options) array of objects to load into the Resource's fields.
* @return The new resource.
*/
public Entity newResource(Entity container, String id, Object[] others)
{
return new BaseMailArchiveMessageEdit((MessageChannel) container, id);
}
/**
* Construct a new resource, from an XML element.
*
* @param container
* The Resource that is the container for the new resource (may be null).
* @param element
* The XML.
* @return The new resource from the XML.
*/
public Entity newResource(Entity container, Element element)
{
return new BaseMailArchiveMessageEdit((MessageChannel) container, element);
}
/**
* Construct a new resource from another resource of the same type.
*
* @param container
* The Resource that is the container for the new resource (may be null).
* @param other
* The other resource.
* @return The new resource as a copy of the other.
*/
public Entity newResource(Entity container, Entity other)
{
return new BaseMailArchiveMessageEdit((MessageChannel) container, (Message) other);
}
/**
* Construct a new continer given just ids.
*
* @param ref
* The channel reference.
* @return The new containe Resource.
*/
public Edit newContainerEdit(String ref)
{
BaseMailArchiveChannelEdit rv = new BaseMailArchiveChannelEdit(ref);
rv.activate();
return rv;
}
/**
* Construct a new container resource, from an XML element.
*
* @param element
* The XML.
* @return The new container resource.
*/
public Edit newContainerEdit(Element element)
{
BaseMailArchiveChannelEdit rv = new BaseMailArchiveChannelEdit(element);
rv.activate();
return rv;
}
/**
* Construct a new container resource, as a copy of another
*
* @param other
* The other contianer to copy.
* @return The new container resource.
*/
public Edit newContainerEdit(Entity other)
{
BaseMailArchiveChannelEdit rv = new BaseMailArchiveChannelEdit((MessageChannel) other);
rv.activate();
return rv;
}
/**
* Construct a new rsource given just an id.
*
* @param container
* The Resource that is the container for the new resource (may be null).
* @param id
* The id for the new object.
* @param others
* (options) array of objects to load into the Resource's fields.
* @return The new resource.
*/
public Edit newResourceEdit(Entity container, String id, Object[] others)
{
BaseMailArchiveMessageEdit rv = new BaseMailArchiveMessageEdit((MessageChannel) container, id);
rv.activate();
return rv;
}
/**
* Construct a new resource, from an XML element.
*
* @param container
* The Resource that is the container for the new resource (may be null).
* @param element
* The XML.
* @return The new resource from the XML.
*/
public Edit newResourceEdit(Entity container, Element element)
{
BaseMailArchiveMessageEdit rv = new BaseMailArchiveMessageEdit((MessageChannel) container, element);
rv.activate();
return rv;
}
/**
* Construct a new resource from another resource of the same type.
*
* @param container
* The Resource that is the container for the new resource (may be null).
* @param other
* The other resource.
* @return The new resource as a copy of the other.
*/
public Edit newResourceEdit(Entity container, Entity other)
{
BaseMailArchiveMessageEdit rv = new BaseMailArchiveMessageEdit((MessageChannel) container, (Message) other);
rv.activate();
return rv;
}
/**
* Collect the fields that need to be stored outside the XML (for the resource).
*
* @return An array of field values to store in the record outside the XML (for the resource).
*/
public Object[] storageFields(Entity r)
{
Object[] rv = new Object[6];
rv[0] = ((Message) r).getHeader().getDate();
rv[1] = ((Message) r).getHeader().getFrom().getId();
rv[2] = "0";
rv[3] = r.getProperties().getProperty(ResourceProperties.PROP_PUBVIEW) == null ? "0" : "1";
rv[4] = ((MailArchiveMessage) r).getMailArchiveHeader().getSubject();
rv[5] = ((Message) r).getBody();
return rv;
}
/**
* Check if this resource is in draft mode.
*
* @param r
* The resource.
* @return true if the resource is in draft mode, false if not.
*/
public boolean isDraft(Entity r)
{
return false;
}
/**
* Access the resource owner user id.
*
* @param r
* The resource.
* @return The resource owner user id.
*/
public String getOwnerId(Entity r)
{
return ((Message) r).getHeader().getFrom().getId();
}
/**
* Access the resource date.
*
* @param r
* The resource.
* @return The resource date.
*/
public Time getDate(Entity r)
{
return ((Message) r).getHeader().getDate();
}
/**********************************************************************************************************************************************************************************************************************************************************
* Abstractions, etc. satisfied
*********************************************************************************************************************************************************************************************************************************************************/
/**
* Report the Service API name being implemented.
*/
protected String serviceName()
{
return MailArchiveService.class.getName();
}
/**
* Construct a new message header from XML in a DOM element.
*
* @param id
* The message Id.
* @return The new message header.
*/
protected MessageHeaderEdit newMessageHeader(Message msg, String id)
{
return new BaseMailArchiveMessageHeaderEdit(msg, id);
} // newMessageHeader
/**
* Construct a new message header from XML in a DOM element.
*
* @param el
* The XML DOM element that has the header information.
* @return The new message header.
*/
protected MessageHeaderEdit newMessageHeader(Message msg, Element el)
{
return new BaseMailArchiveMessageHeaderEdit(msg, el);
} // newMessageHeader
/**
* Construct a new message header as a copy of another.
*
* @param other
* The other header to copy.
* @return The new message header.
*/
protected MessageHeaderEdit newMessageHeader(Message msg, MessageHeader other)
{
return new BaseMailArchiveMessageHeaderEdit(msg, other);
} // newMessageHeader
/**
* Form a tracking event string based on a security function string.
*
* @param secure
* The security function string.
* @return The event tracking string.
*/
protected String eventId(String secure)
{
return SECURE_MAIL_ROOT + secure;
} // eventId
/**
* Return the reference rooot for use in resource references and urls.
*
* @return The reference rooot for use in resource references and urls.
*/
protected String getReferenceRoot()
{
return REFERENCE_ROOT;
} // getReferenceRoot
/**
* {@inheritDoc}
*/
public boolean parseEntityReference(String reference, Reference ref)
{
if (reference.startsWith(REFERENCE_ROOT))
{
String[] parts = StringUtils.split(reference, Entity.SEPARATOR);
String id = null;
String subType = null;
String context = null;
String container = null;
// the first part will be "mailarchive", then next the service, the third will be "msg" or "channel"
if (parts.length > 1)
{
subType = parts[1];
if (REF_TYPE_CHANNEL.equals(subType))
{
// next is the context id
if (parts.length > 2)
{
context = parts[2];
// next is the channel id
if (parts.length > 3)
{
id = parts[3];
}
}
}
else if (REF_TYPE_MESSAGE.equals(subType))
{
// next three parts are context, channel (container) and mesage id
if (parts.length > 4)
{
context = parts[2];
container = parts[3];
id = parts[4];
}
}
else
M_log.warn("parse(): unknown message subtype: " + subType + " in ref: " + reference);
}
ref.set(APPLICATION_ID, subType, id, container, context);
return true;
}
return false;
}
/**
* {@inheritDoc}
*/
public void contextCreated(String context, boolean toolPlacement)
{
if (toolPlacement) enableMailbox(context);
}
/**
* {@inheritDoc}
*/
public void contextUpdated(String context, boolean toolPlacement)
{
if (toolPlacement) enableMailbox(context);
}
/**
* {@inheritDoc}
*/
public void contextDeleted(String context, boolean toolPlacement)
{
disableMailbox(context);
}
/**
* {@inheritDoc}
*/
public String[] myToolIds()
{
String[] toolIds = { "sakai.mailbox" };
return toolIds;
}
/**
* Setup the mailbox for an active site.
*
* @param siteId
* The site id.
*/
protected void enableMailbox(String siteId)
{
// form the email channel name
String channelRef = channelReference(siteId, SiteService.MAIN_CONTAINER);
// see if there's a channel
MessageChannel channel = null;
try
{
channel = getChannel(channelRef);
}
catch (IdUnusedException e)
{
}
catch (PermissionException e)
{
}
// if it exists, make sure it's enabled
if (channel != null)
{
if (channel.getProperties().getProperty(ResourceProperties.PROP_CHANNEL_ENABLED) == null)
{
try
{
MessageChannelEdit edit = (MessageChannelEdit) editChannel(channelRef);
edit.getPropertiesEdit().addProperty(ResourceProperties.PROP_CHANNEL_ENABLED, "true");
commitChannel(edit);
}
catch (IdUnusedException ignore)
{
}
catch (PermissionException ignore)
{
}
catch (InUseException ignore)
{
}
}
}
// otherwise create it
else
{
try
{
// create a channel and mark it as enabled
MessageChannelEdit edit = addMailArchiveChannel(channelRef);
edit.getPropertiesEdit().addProperty(ResourceProperties.PROP_CHANNEL_ENABLED, "true");
commitChannel(edit);
}
catch (IdUsedException e)
{
}
catch (IdInvalidException e)
{
}
catch (PermissionException e)
{
}
}
}
/**
* Set a site's mailbox to inactive - it remains in existance, just disabled
*
* @param siteId
* The site id.
*/
protected void disableMailbox(String siteId)
{
// form the email channel name
String channelRef = channelReference(siteId, SiteService.MAIN_CONTAINER);
// see if there's a channel
MessageChannel channel = null;
try
{
channel = getChannel(channelRef);
}
catch (IdUnusedException e)
{
}
catch (PermissionException e)
{
}
// if it exists, make sure it's disabled
if (channel != null)
{
if (channel.getProperties().getProperty(ResourceProperties.PROP_CHANNEL_ENABLED) != null)
{
try
{
MessageChannelEdit edit = (MessageChannelEdit) editChannel(channelRef);
edit.getPropertiesEdit().removeProperty(ResourceProperties.PROP_CHANNEL_ENABLED);
commitChannel(edit);
channel = edit;
}
catch (IdUnusedException ignore)
{
}
catch (PermissionException ignore)
{
}
catch (InUseException ignore)
{
}
}
}
// remove any alias
try
{
AliasService.removeTargetAliases(channelRef);
}
catch (PermissionException e)
{
}
}
/**********************************************************************************************************************************************************************************************************************************************************
* MailArchiveService implementation
*********************************************************************************************************************************************************************************************************************************************************/
/**
* Return a specific mail message channel.
*
* @param ref
* The channel reference.
* @return the MailArchiveChannel that has the specified name.
* @exception IdUnusedException
* If this name is not defined for a mail message channel.
* @exception PermissionException
* If the user does not have any permissions to the channel.
*/
public MailArchiveChannel getMailArchiveChannel(String ref) throws IdUnusedException, PermissionException
{
return (MailArchiveChannel) getChannel(ref);
} // getMailArchiveChannel
/**
* Add a new mail message channel.
*
* @param ref
* The channel reference.
* @return The newly created channel.
* @exception IdUsedException
* if the id is not unique.
* @exception IdInvalidException
* if the id is not made up of valid characters.
* @exception PermissionException
* if the user does not have permission to add a channel.
*/
public MailArchiveChannelEdit addMailArchiveChannel(String ref) throws IdUsedException, IdInvalidException, PermissionException
{
return (MailArchiveChannelEdit) addChannel(ref);
} // addMailArchiveChannel
/**********************************************************************************************************************************************************************************************************************************************************
* ResourceService implementation
*********************************************************************************************************************************************************************************************************************************************************/
/**
* {@inheritDoc}
*/
public String getLabel()
{
return "email";
}
/**********************************************************************************************************************************************************************************************************************************************************
* MailArchiveChannel implementation
*********************************************************************************************************************************************************************************************************************************************************/
public class BaseMailArchiveChannelEdit extends BaseMessageChannelEdit implements MailArchiveChannelEdit
{
/**
* Construct with an id.
*
* @param ref
* The channel reference.
*/
public BaseMailArchiveChannelEdit(String ref)
{
super(ref);
} // BaseMailArchiveChannelEdit
/**
* Construct as a copy of another message.
*
* @param other
* The other message to copy.
*/
public BaseMailArchiveChannelEdit(MessageChannel other)
{
super(other);
} // BaseMailArchiveChannelEdit
/**
* Construct from a channel (and possibly messages) already defined in XML in a DOM tree. The Channel is added to storage.
*
* @param el
* The XML DOM element defining the channel.
*/
public BaseMailArchiveChannelEdit(Element el)
{
super(el);
} // BaseMailArchiveChannelEdit
/**
* Return a specific mail message channel message, as specified by message name.
*
* @param messageId
* The id of the message to get.
* @return the MailArchiveMessage that has the specified id.
* @exception IdUnusedException
* If this name is not a defined message in this mail message channel.
* @exception PermissionException
* If the user does not have any permissions to read the message.
*/
public MailArchiveMessage getMailArchiveMessage(String messageId) throws IdUnusedException, PermissionException
{
MailArchiveMessage msg = (MailArchiveMessage) getMessage(messageId);
return msg;
} // getMailArchiveMessage
/**
* A (MailArchiveMessageEdit) cover for editMessage. Return a specific channel message, as specified by message name, locked for update. Must commitEdit() to make official, or cancelEdit() when done!
*
* @param messageId
* The id of the message to get.
* @return the Message that has the specified id.
* @exception IdUnusedException
* If this name is not a defined message in this channel.
* @exception PermissionException
* If the user does not have any permissions to read the message.
* @exception InUseException
* if the current user does not have permission to mess with this user.
*/
public MailArchiveMessageEdit editMailArchiveMessage(String messageId) throws IdUnusedException, PermissionException,
InUseException
{
return (MailArchiveMessageEdit) editMessage(messageId);
} // editMailArchiveMessage
/**
* A (MailArchiveMessageEdit) cover for addMessage. Add a new message to this channel. Must commitEdit() to make official, or cancelEdit() when done!
*
* @return The newly added message, locked for update.
* @exception PermissionException
* If the user does not have write permission to the channel.
*/
public MailArchiveMessageEdit addMailArchiveMessage() throws PermissionException
{
return (MailArchiveMessageEdit) addMessage();
} // addMailArchiveMessage
/**
* a (MailArchiveMessage) cover for addMessage to add a new message to this channel.
*
* @param subject
* The message header subject.
* @param fromAddress
* The mail from: address from the message.
* @param dateSent
* The date: sent from the message.
* @param mailHeaders
* The full set of mail headers from the message.
* @param attachments
* The message header attachments, a vector of Reference objects.
* @param body
* The message body.- body[0] is plain/text; body[1] is html/text
* @return The newly added message.
* @exception PermissionException
* If the user does not have write permission to the channel.
*/
public MailArchiveMessage addMailArchiveMessage(String subject, String fromAddress, Time dateSent, List mailHeaders,
List attachments, String[] body) throws PermissionException
{
MailArchiveMessageEdit edit = (MailArchiveMessageEdit) addMessage();
MailArchiveMessageHeaderEdit archiveHeaders = edit.getMailArchiveHeaderEdit();
edit.setBody(body[0]);
edit.setHtmlBody(body[1]);
archiveHeaders.replaceAttachments(attachments);
archiveHeaders.setSubject(subject);
archiveHeaders.setFromAddress(fromAddress);
archiveHeaders.setDateSent(dateSent);
archiveHeaders.setMailHeaders(mailHeaders);
// lets make sure that folks who have signed up for email get it
//SAK 12800
if (getSendToList()) {
commitMessage(edit, NotificationService.NOTI_OPTIONAL);
} else {
commitMessage(edit, NotificationService.NOTI_NONE);
}
return edit;
} // addMailArchiveMessage
/** @return true if the channel enabled, false if not. */
public boolean getEnabled()
{
boolean enabled = false;
try
{
enabled = getProperties().getBooleanProperty(ResourceProperties.PROP_CHANNEL_ENABLED);
}
catch (Exception ignore)
{
}
return enabled;
} // getEnabled
/** @return true if the channel is open to messages from outside the membership, false if not. */
public boolean getOpen()
{
boolean open = false;
try
{
open = getProperties().getBooleanProperty(PROP_MAIL_CHANNEL_OPEN);
}
catch (Exception ignore)
{
}
return open;
} // getOpen
/**
* Set the enabled status of the channe. Disabled channels will not recieve email.
*
* @param setting
* The new setting.
*/
public void setEnabled(boolean setting)
{
if (setting)
{
getPropertiesEdit().addProperty(ResourceProperties.PROP_CHANNEL_ENABLED, "true");
}
else
{
getPropertiesEdit().removeProperty(ResourceProperties.PROP_CHANNEL_ENABLED);
}
} // setEnabled
/**
* Set the open status of the channe. Open channels will recieve email from anyone - otherwise messages will be accepted only from users (based on the main from email address) with add permission.
*
* @param setting
* The new setting.
*/
public void setOpen(boolean setting)
{
if (setting)
{
getPropertiesEdit().addProperty(PROP_MAIL_CHANNEL_OPEN, "true");
}
else
{
getPropertiesEdit().removeProperty(PROP_MAIL_CHANNEL_OPEN);
}
}
/**
* check permissions for addMessage() for the given user.
*
* @param user
* The user.
* @return true if the specified user is allowed to addMessage(...), false if not.
*/
public boolean allowAddMessage(User user)
{
if (!SecurityService.unlock(user, eventId(SECURE_ADD), getReference()))
{
return false;
}
return true;
}
/*
* (non-Javadoc)
* @see org.sakaiproject.mailarchive.api.MailArchiveChannelEdit#setReplyToList(boolean)
*/
public void setReplyToList(boolean replyToList)
{
if (replyToList)
{
getPropertiesEdit().addProperty(PROP_MAIL_CHANNEL_REPLY_LIST, "true");
}
else
{
getPropertiesEdit().removeProperty(PROP_MAIL_CHANNEL_REPLY_LIST);
}
}
/*
* (non-Javadoc)
* @see org.sakaiproject.mailarchive.api.MailArchiveChannel#getReplyToList()
*/
public boolean getReplyToList()
{
boolean open = false;
try
{
open = getProperties().getBooleanProperty(PROP_MAIL_CHANNEL_REPLY_LIST);
}
catch (Exception ignore)
{
}
return open;
}
/*
* (non-Javadoc)
* @see org.sakaiproject.mailarchive.api.MailArchiveChannelEdit#setSendToList(boolean)
*/
public void setSendToList(boolean sendToList)
{
//If not set it defaults to true
if (sendToList==false)
{
getPropertiesEdit().addProperty(PROP_MAIL_CHANNEL_SENDTO_LIST, "false");
}
else
{
getPropertiesEdit().removeProperty(PROP_MAIL_CHANNEL_SENDTO_LIST);
}
}
/*
* (non-Javadoc)
* @see org.sakaiproject.mailarchive.api.MailArchiveChannel#getSendToList()
*/
public boolean getSendToList()
{
boolean open = true;
//TODO:This shouldn't try/catch for nothing
try
{
open = getProperties().getBooleanProperty(PROP_MAIL_CHANNEL_SENDTO_LIST);
}
catch (Exception ignore)
{
}
return open;
}
} // class BaseMailArchiveChannelEdit
/**********************************************************************************************************************************************************************************************************************************************************
* MailArchiveMessage implementation
*********************************************************************************************************************************************************************************************************************************************************/
public class BaseMailArchiveMessageEdit extends BaseMessageEdit implements MailArchiveMessageEdit
{
protected String m_html_body = null;
/**
* Construct.
*
* @param channel
* The channel in which this message lives.
* @param id
* The message id.
*/
public BaseMailArchiveMessageEdit(MessageChannel channel, String id)
{
super(channel, id);
m_html_body = "";
} // BaseMailArchiveMessageEdit
/**
* Construct as a copy of another message.
*
* @param other
* The other message to copy.
*/
public BaseMailArchiveMessageEdit(MessageChannel channel, Message other)
{
super(channel, other);
} // BaseMailArchiveMessageEdit
/**
* Construct from an existing definition, in xml.
*
* @param channel
* The channel in which this message lives.
* @param el
* The message in XML in a DOM element.
*/
public BaseMailArchiveMessageEdit(MessageChannel channel, Element el)
{
this(channel, "");
m_html_body = Xml.decodeAttribute(el, "body-html");
m_body = Xml.decodeAttribute(el, "body");
// the children (header, body)
NodeList children = el.getChildNodes();
final int length = children.getLength();
for (int i = 0; i < length; i++)
{
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE)
{
Element element = (Element) child;
// look for a header
if (element.getTagName().equals("header"))
{
// re-create a header
m_header = newMessageHeader(this, element);
}
// or look for a body (old style of encoding)
else if (element.getTagName().equals("body"))
{
if ((element.getChildNodes() != null) && (element.getChildNodes().item(0) != null))
{
// convert from plaintext messages to formatted text messages
m_body = element.getChildNodes().item(0).getNodeValue();
if (m_body != null) m_body = FormattedText.convertPlaintextToFormattedText(m_body);
}
if (m_body == null)
{
m_body = "";
}
}
// or look for properties
else if (element.getTagName().equals("properties"))
{
// re-create properties
m_properties = new BaseResourcePropertiesEdit(element);
}
}
}
} // BaseMailArchiveMessageEdit
/**
* Access the mail message message header.
*
* @return The mail message message header.
*/
public MailArchiveMessageHeader getMailArchiveHeader()
{
return (MailArchiveMessageHeader) getHeader();
} // getMailArchiveHeader
/**
* Access the mail message message header.
*
* @return The mail message message header.
*/
public MailArchiveMessageHeaderEdit getMailArchiveHeaderEdit()
{
return (MailArchiveMessageHeaderEdit) getHeader();
} // getMailArchiveHeaderEdit
/**
* Replace the html body, as a string.
*
* @param body
* The html-encoded body, as a string.
*/
public void setHtmlBody(String body)
{
m_html_body = body;
} // setHtmlBody
/**
* Get the html body, as a string.
*
* @return The html-encoded body, as a string.
*/
public String getHtmlBody()
{
return m_html_body;
} // getHtmlBody
/**
* Get the formatted body (either html or plain-text converted to html), as a string.
*
* @return The formatted body as a string.
*/
public String getFormattedBody()
{
if ( getHtmlBody() != null && getHtmlBody().length() > 0 )
return m_html_body;
else
return Web.encodeUrlsAsHtml( FormattedText.convertPlaintextToFormattedText(m_body) );
} // getHtmlBody
/**
* Take all values from this object.
*
* @param other
* The other object to take values from.
*/
protected void setAll(Message other)
{
super.setAll( other );
if ( other instanceof BaseMailArchiveMessageEdit )
m_html_body = ((BaseMailArchiveMessageEdit)other).getHtmlBody();
}
/**
* Serialize the resource into XML, adding an element to the doc under the top of the stack element.
*
* @param doc
* The DOM doc to contain the XML (or null for a string return).
* @param stack
* The DOM elements, the top of which is the containing element of the new "resource" element.
* @return The newly added element.
*/
public Element toXml(Document doc, Stack stack)
{
Element message = super.toXml(doc, stack);
// Over-ride super.toXml() definition of body and body-html attributes
// store the html body in attribute
Xml.encodeAttribute(message, "body-html", getHtmlBody() );
// store the plain-text body in attribute
Xml.encodeAttribute(message, "body", getBody() );
return message;
}
} // class BasicMailArchiveMessageEdit
/**********************************************************************************************************************************************************************************************************************************************************
* MailArchiveMessageHeaderEdit implementation
*********************************************************************************************************************************************************************************************************************************************************/
public class BaseMailArchiveMessageHeaderEdit extends BaseMessageHeaderEdit implements MailArchiveMessageHeaderEdit
{
/** The subject for the mail message. */
protected String m_subject = null;
/** The from: address for the message. */
protected String m_fromAddress = null;
/** The date: sent for the message. */
protected Time m_dateSent = null;
/** The entire set of mail headers. */
protected List m_mailHeaders = new Vector();
/**
* Construct.
*
* @param id
* The unique (within the channel) message id.
* @param from
* The User who sent the message to the channel.
* @param attachments
* The message header attachments, a vector of Reference objects.
*/
public BaseMailArchiveMessageHeaderEdit(Message msg, String id)
{
super(msg, id);
} // BaseMailArchiveMessageHeaderEdit
/**
* Construct, from an already existing XML DOM element.
*
* @param el
* The header in XML in a DOM element.
*/
public BaseMailArchiveMessageHeaderEdit(Message msg, Element el)
{
super(msg, el);
// now extract the subject, from address, date sent
m_subject = el.getAttribute("subject");
m_fromAddress = el.getAttribute("mail-from");
m_dateSent = TimeService.newTimeGmt(el.getAttribute("mail-date"));
// mail headers
NodeList children = el.getChildNodes();
final int length = children.getLength();
for (int i = 0; i < length; i++)
{
Node child = children.item(i);
if (child.getNodeType() != Node.ELEMENT_NODE) continue;
Element element = (Element) child;
// look for a header
if (!element.getTagName().equals("mail-header")) continue;
m_mailHeaders.add(element.getAttribute("value"));
}
} // BaseMailArchiveMessageHeaderEdit
/**
* Construct as a copy of another header.
*
* @param other
* The other message header to copy.
*/
public BaseMailArchiveMessageHeaderEdit(Message msg, MessageHeader other)
{
super(msg, other);
m_subject = ((MailArchiveMessageHeader) other).getSubject();
m_fromAddress = ((MailArchiveMessageHeader) other).getFromAddress();
m_dateSent = ((MailArchiveMessageHeader) other).getDateSent();
m_mailHeaders.addAll(((MailArchiveMessageHeader) other).getMailHeaders());
} // BaseMailArchiveMessageHeaderEdit
/**
* Access the subject of the mail message.
*
* @return The subject of the mail message.
*/
public String getSubject()
{
return ((m_subject == null) ? "" : m_subject);
} // getSubject
/**
* Set the subject of the mail message.
*
* @param subject
* The subject of the mail message.
*/
public void setSubject(String subject)
{
m_subject = subject;
} // setSubject
/**
* Access the from: address of the message.
*
* @return The from: address of the message.
*/
public String getFromAddress()
{
String fromAddress = ((m_fromAddress == null) ? "" : m_fromAddress);
try
{
fromAddress = MimeUtility.decodeText(fromAddress);
}
catch (UnsupportedEncodingException e)
{
// if unable to decode RFC address, just return address as is
M_log.debug(this+".getFromAddress "+e.toString());
}
return fromAddress;
} // getFromAddress
/**
* Set the the from: address of the message.
*
* @param from
* The from: address of the message.
*/
public void setFromAddress(String from)
{
m_fromAddress = from;
} // setFromAddress
/**
* Access the date: sent of the message.
*
* @return The date: sent of the message.
*/
public Time getDateSent()
{
return ((m_dateSent == null) ? this.getDate() : m_dateSent);
} // getDateSent
/**
* Set the date: sent of the message.
*
* @param sent
* The the date: sent of the message.
*/
public void setDateSent(Time sent)
{
m_dateSent = TimeService.newTime(sent.getTime());
} // setDateSent
/**
* Access the entire set of mail headers the message.
*
* @return The entire set of mail headers of the message (List of String).
*/
public List getMailHeaders()
{
return m_mailHeaders;
} // getMailHeaders
/**
* Set the entire set of mail headers of the message.
*
* @param headers
* The the entire set of mail headers of the message.
*/
public void setMailHeaders(List headers)
{
m_mailHeaders.clear();
m_mailHeaders.addAll(headers);
} // setMailHeaders
/**
* Serialize the resource into XML, adding an element to the doc under the top of the stack element.
*
* @param doc
* The DOM doc to contain the XML (or null for a string return).
* @param stack
* The DOM elements, the top of which is the containing element of the new "resource" element.
* @return The newly added element.
*/
public Element toXml(Document doc, Stack stack)
{
// get the basic work done
Element header = super.toXml(doc, stack);
// add draft, subject
header.setAttribute("subject", getSubject());
header.setAttribute("mail-from", getFromAddress());
header.setAttribute("mail-date", getDateSent().toString());
for (int i = 0; i < m_mailHeaders.size(); i++)
{
Element mailHeader = doc.createElement("mail-header");
header.appendChild(mailHeader);
mailHeader.setAttribute("value", (String) m_mailHeaders.get(i));
}
return header;
} // toXml
} // BaseMailArchiveMessageHeader
/* (non-Javadoc)
* @see org.sakaiproject.entity.api.EntitySummary#summarizableToolIds()
*/
public String[] summarizableToolIds()
{
return new String[] {
"sakai.mailarchive"
};
}
} // BaseMailArchiveService