blob: 72e83e5d802511fe77fa48ddbb31e9e7a6e8b91f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache 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.apache.org/licenses/LICENSE-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.apache.cocoon.mail;
import java.io.IOException;
import java.util.List;
import javax.mail.FetchProfile;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Store;
import javax.mail.UIDFolder;
import javax.mail.search.FromStringTerm;
import javax.mail.search.OrTerm;
import javax.mail.search.SearchTerm;
import javax.mail.search.SubjectTerm;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.cocoon.mail.command.AbstractMailCommand;
import org.apache.cocoon.mail.command.MailCommands;
/**
* Manage invocation of mail commands.
*
* @author Bernhard Huber
* @since 23 October 2002
* @version $Id$
*/
public class MailCommandManager extends AbstractLogEnabled {
/**
* Description of the Field
*/
public final static String DEFAULT_FOLDER_NAME = "INBOX";
/**
* Description of the Field
*/
public final static String DEFAULT_FOLDER_PATTERN = "%";
/**
* Context key specifying the foldername.
*/
public final static String CONTEXT_FOLDER_ENTRY = "folder";
/**
* Description of the Field
*/
public final static String CONTEXT_UID_ENTRY = "uid";
/**
* Description of the Field
*/
public final static String CONTEXT_ID_ENTRY = "id";
/**
* Description of the Field
*/
public final static String CONTEXT_PARTID_ENTRY = "part-id";
/**
* Description of the Field
*/
public final static String CONTEXT_FOLDER_PATTERN_ENTRY = "folder-pattern";
/**
* Description of the Field
*/
public final static String CONTEXT_MAX_FOLDER_LEVEL_ENTRY = "max-folder-level";
/**
* Creates a new instance of MailHeaderList
*/
public MailCommandManager() { }
/**
* Open a javamail folder
*
* @param f Description of the Parameter
* @param mode folder opening mode, use Folder.READ_WRITE, or Folder.READ_ONLY
* @exception MessagingException Description of the Exception
*/
public static void openFolder(Folder f, int mode) throws MessagingException {
if (!f.isOpen()) {
f.open(mode);
}
}
/**
* Close a javamail folder
*
* @param f Description of the Parameter
* @exception MessagingException Description of the Exception
*/
public static void closeFolder(Folder f) throws MessagingException {
if (f != null && f.isOpen()) {
// fix me : do we need expungeOnExit = true?
f.close(false);
}
}
/**
* Open a javamail store
*
* @param s Description of the Parameter
* @exception MessagingException Description of the Exception
*/
public static void openStore(Store s) throws MessagingException {
if (!s.isConnected()) {
s.connect();
}
}
/**
* Close a javamail store
*
* @param s Description of the Parameter
* @exception MessagingException Description of the Exception
*/
public static void closeStore(Store s) throws MessagingException {
if (s != null && s.isConnected()) {
s.close();
}
}
/**
* Description of the Method
*
* @param aList Description of the Parameter
* @return Description of the Return Value
*/
public List execute(List aList) {
MailCommands folderCommands = new MailCommands(aList);
try {
folderCommands.execute();
} catch (MessagingException me) {
// log exception
getLogger().error("Cannot execute", me);
}
return folderCommands.getResults();
}
/**
* Description of the Method
*
* @param amfa Description of the Parameter
* @return Description of the Return Value
*/
public List execute(AbstractMailCommand amfa) {
try {
amfa.execute();
} catch (MessagingException me) {
// log exception
getLogger().error("Cannot execute", me);
}
return amfa.getResults();
}
/**
* Retrieve folder, and put it as command result.
*/
public static class MailFolderCatCommand extends AbstractMailCommand
implements Contextualizable {
private Folder aFolder;
/**
* Constructor for the MailFolderCommand object
*/
public MailFolderCatCommand() { }
/**
* Description of the Method
*
* @param ctx Description of the Parameter
* @exception ContextException Description of the Exception
*/
public void contextualize(Context ctx) throws ContextException {
MailContext mctx = (MailContext) ctx;
this.aFolder = mctx.getTheFolder(CONTEXT_FOLDER_ENTRY);
}
/**
* Description of the Method
*
* @exception MessagingException Description of the Exception
*/
public void execute() throws MessagingException {
MailCommandManager.openFolder(aFolder, Folder.READ_ONLY);
addResult(aFolder);
}
}
/**
* Retrieve folder, and put it as command result.
*/
public static class MailRefreshFolderCommand extends AbstractMailCommand
implements Contextualizable {
private Folder aFolder;
/**
* Constructor for the MailFolderCommand object
*/
public MailRefreshFolderCommand() { }
/**
* Description of the Method
*
* @param ctx Description of the Parameter
* @exception ContextException Description of the Exception
*/
public void contextualize(Context ctx) throws ContextException {
MailContext mctx = (MailContext) ctx;
this.aFolder = mctx.getTheFolder(CONTEXT_FOLDER_ENTRY);
}
/**
* Description of the Method
*
* @exception MessagingException Description of the Exception
*/
public void execute() throws MessagingException {
MailCommandManager.closeFolder(aFolder);
MailCommandManager.openFolder(aFolder, Folder.READ_ONLY);
addResult(aFolder);
}
}
/**
* Retrieved headers of all messages of a folder, put
* retrieved messages as command result.
*/
public static class MailListMessagesCommand extends AbstractMailCommand
implements Contextualizable {
private Folder aFolder;
/**
* Constructor for the MailAllHeadersCommand object
*/
public MailListMessagesCommand() { }
/**
* Description of the Method
*
* @param ctx Description of the Parameter
* @exception ContextException Description of the Exception
*/
public void contextualize(Context ctx) throws ContextException {
// try to get the folder object
MailContext mctx = (MailContext) ctx;
this.aFolder = mctx.getTheFolder(CONTEXT_FOLDER_ENTRY);
}
/**
* Description of the Method
*
* @exception MessagingException Description of the Exception
*/
public void execute() throws MessagingException {
MailCommandManager.openFolder(aFolder, Folder.READ_ONLY);
// add folder, too
addResult(aFolder);
Message[] messages = aFolder.getMessages();
// Use a suitable FetchProfile
FetchProfile fp = new FetchProfile();
fp.add(FetchProfile.Item.ENVELOPE);
fp.add(FetchProfile.Item.FLAGS);
fp.add("X-Mailer");
aFolder.fetch(messages, fp);
// add all messages to the result
addResult(messages);
}
}
/**
* List all subfolders of a folder, put
* all retrieved folders as command result.
*/
public static class MailListFolderCommand extends AbstractMailCommand
implements Contextualizable {
private Folder aFolder;
private String folderPattern = MailCommandManager.DEFAULT_FOLDER_PATTERN;
/**
* Constructor for the MailFoldersCommand object
*/
public MailListFolderCommand() { }
/**
* Gets the folderPattern attribute of the ListFolderCommand object
*
* @return The folderPattern value
*/
public String getFolderPattern() {
return this.folderPattern;
}
/**
* Description of the Method
*
* @param ctx Description of the Parameter
* @exception ContextException Description of the Exception
*/
public void contextualize(Context ctx) throws ContextException {
MailContext mctx = (MailContext) ctx;
this.aFolder = mctx.getTheFolder(CONTEXT_FOLDER_ENTRY);
try {
this.folderPattern = (String) ctx.get("param:" + CONTEXT_FOLDER_PATTERN_ENTRY);
} catch (ContextException ce) {
// use default folder pattern
this.folderPattern = MailCommandManager.DEFAULT_FOLDER_PATTERN;
}
}
/**
* Description of the Method
*
* @exception MessagingException Description of the Exception
*/
public void execute() throws MessagingException {
// spec say: folder list can be invoked on closed folder MailCommandManager.openFolder(aFolder,Folder.READ_ONLY);
//addResult(aFolder);
Folder[] subFolders = aFolder.list(this.folderPattern);
getLogger().debug("Adding " + String.valueOf(subFolders.length) + " subFolders ");
for (int i = 0; i < subFolders.length; i++) {
getLogger().debug("subFolder " + String.valueOf(i) + " name " + subFolders[i].getFullName());
}
addResult(subFolders);
}
}
/**
* Retrieved a message (envelope plus content) of a folder by its uid, put
* retrieved message as command result.
*/
public static class MailCatMessageByUIDCommand extends AbstractMailCommand
implements Contextualizable {
private int msgUID = 1;
private Folder aFolder;
/**
* Constructor for the MailMessageByUIDCommand object
*/
public MailCatMessageByUIDCommand() { }
/**
* Description of the Method
*
* @param ctx Description of the Parameter
* @exception ContextException Description of the Exception
*/
public void contextualize(Context ctx) throws ContextException {
MailContext mctx = (MailContext) ctx;
this.aFolder = mctx.getTheFolder(CONTEXT_FOLDER_ENTRY);
Integer i = (Integer) ctx.get("param-integer:" + CONTEXT_UID_ENTRY);
if (i == null) {
String message = "Missing mandatory context entry " + String.valueOf(CONTEXT_UID_ENTRY);
throw new ContextException(message);
}
this.msgUID = i.intValue();
}
/**
* Description of the Method
*
* @exception MessagingException Description of the Exception
*/
public void execute() throws MessagingException {
UIDFolder uidFolder = (UIDFolder) aFolder;
MailCommandManager.openFolder(aFolder, Folder.READ_ONLY);
// add folder, too
addResult(aFolder);
Message msg = uidFolder.getMessageByUID(msgUID);
addResult(msg);
}
}
/**
* Retrieved a message (envelope plus content) of a folder by its id, put
* retrieved message as command result.
*/
public static class MailCatMessageByIdCommand extends AbstractMailCommand
implements Contextualizable {
private int msgId = 1;
private Folder aFolder;
/**
* Constructor for the MailMessageByIdCommand object
*/
public MailCatMessageByIdCommand() { }
/**
* Description of the Method
*
* @param ctx Description of the Parameter
* @exception ContextException Description of the Exception
*/
public void contextualize(Context ctx) throws ContextException {
MailContext mctx = (MailContext) ctx;
this.aFolder = mctx.getTheFolder(CONTEXT_FOLDER_ENTRY);
try {
Integer i = (Integer) ctx.get("param-integer:" + CONTEXT_ID_ENTRY);
this.msgId = i.intValue();
} catch (ContextException ce) {
String message = "Missing mandatory context entry " + String.valueOf(CONTEXT_ID_ENTRY);
throw new ContextException(message);
}
}
/**
* Description of the Method
*
* @exception MessagingException Description of the Exception
*/
public void execute() throws MessagingException {
MailCommandManager.openFolder(aFolder, Folder.READ_ONLY);
// add folder, too
addResult(aFolder);
Message msg = aFolder.getMessage(msgId);
addResult(msg);
}
}
/**
* Retrieved a message part by its part id, specifying the message by id, put
* retrieved part as command result.
*/
public static class MailCatAttachmentMessageByIdCommand extends AbstractMailCommand
implements Contextualizable {
private int msgId = -1;
private int partId = -1;
private Folder aFolder;
/**
* Constructor for the MailCatAttachmentMessageByIdCommand object
*/
public MailCatAttachmentMessageByIdCommand() { }
/**
* Description of the Method
*
* @param ctx Description of the Parameter
* @exception ContextException Description of the Exception
*/
public void contextualize(Context ctx) throws ContextException {
MailContext mctx = (MailContext) ctx;
this.aFolder = mctx.getTheFolder(CONTEXT_FOLDER_ENTRY);
Integer i = (Integer) ctx.get("param-integer:" + CONTEXT_ID_ENTRY);
if (i == null) {
String message = "Missing mandatory context entry " + String.valueOf(CONTEXT_ID_ENTRY);
throw new ContextException(message);
}
this.msgId = i.intValue();
i = (Integer) ctx.get("param-integer:" + CONTEXT_PARTID_ENTRY);
if (i == null) {
String message = "Missing mandatory context entry " + String.valueOf(CONTEXT_PARTID_ENTRY);
throw new ContextException(message);
}
this.partId = i.intValue();
}
/**
* Description of the Method
*
* @exception MessagingException Description of the Exception
*/
public void execute() throws MessagingException {
MailCommandManager.openFolder(aFolder, Folder.READ_ONLY);
// add folder, too
addResult(aFolder);
// get the message
Message msg = aFolder.getMessage(msgId);
if (msg == null) {
String message = "Cannot get message for id " + String.valueOf(msgId);
getLogger().warn(message);
return;
}
try {
Part part = null;
Object objRef = msg.getContent();
if (!(objRef instanceof Multipart)) {
String message = "Message of id " + String.valueOf(msgId) + " is not a multipart message!";
getLogger().warn(message);
return;
}
Multipart multipart = (Multipart) objRef;
int numParts = multipart.getCount();
if (partId < numParts) {
part = multipart.getBodyPart(partId);
} else {
String message = "Invalid part id " + String.valueOf(this.partId) + " of message id " + String.valueOf(this.msgId);
getLogger().warn(message);
}
addResult(part);
} catch (IOException ioe) {
String message = "Cannot get content of " +
"message for id " + String.valueOf(msgId);
throw new MessagingException(message, ioe);
}
}
}
/**
* Description of the Class
*/
public static class MailSearchMessagesCommand extends AbstractMailCommand
implements Contextualizable {
private Folder aFolder;
private SearchTerm searchTerm;
/**
* Description of the Method
*
* @param ctx Description of the Parameter
* @exception ContextException Description of the Exception
*/
public void contextualize(Context ctx) throws ContextException {
MailContext mctx = (MailContext) ctx;
this.aFolder = mctx.getTheFolder(CONTEXT_FOLDER_ENTRY);
String searchString = (String) ctx.get("param:" + "search");
if (searchString == null) {
searchString = "";
}
searchTerm = new OrTerm(
new SubjectTerm(searchString),
new FromStringTerm(searchString));
// build searchTerm from searchTermString
/* proposed searchTermString syntax
{header}:comp-op:{value} & {header}:comp-op:{value} | .....
eg. subject:eq:cocoon & date::MM/DD/2002
header:com-op:
subject:[cont|ncont]:
sender:[cont|ncont]:
body:[cont|ncont]:
date:[is|nis|before|after]
status:[is|nis]:[Read|New|Replied|Forwarded]
to:[cont|ncont]:
cc:
age-in-days:[is|nis|gt|lt]:
reply-to:[cont|ncont]:
*/
}
/**
* Description of the Method
*
* @exception MessagingException Description of the Exception
*/
public void execute() throws MessagingException {
MailCommandManager.openFolder(aFolder, Folder.READ_ONLY);
// add folder, too
addResult(aFolder);
Message[] msgs = aFolder.search(searchTerm);
addResult(msgs);
}
}
}