blob: 46f41c7eb50c6696bac6d87bcf1ca4bd710b5d15 [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.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Provider;
import javax.mail.Store;
import javax.mail.URLName;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.acting.ServiceableAction;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Redirector;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.Session;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.mail.command.AbstractMailCommand;
/**
* This action creates javamail objects, and puts XMLizable object wrappers
* of these objects into the request attribute map.
* <p>
* This action enables javamail access as action. It creates an http sesion,
* and puts the MailContext object into the session attributes.
* </p>
*
* @see MailContext
*
* @author Bernhard Huber
* @version $Id$
* @since Cocoon 2.1, 16 December 2002
*/
public class MailAction extends ServiceableAction implements ThreadSafe {
/**
* Request attribute name of a XMLizable folder
*/
public final static String REQUEST_ATTRIBUTE_FOLDER = "folder";
/**
* Request attribute name of a XMLizable folders object
*/
public final static String REQUEST_ATTRIBUTE_FOLDERS = "folders";
/**
* Request attribute name of a XMLizable message object
*/
public final static String REQUEST_ATTRIBUTE_MESSAGE = "message";
/**
* Request attribute name of a XMLizable messages object
*/
public final static String REQUEST_ATTRIBUTE_MESSAGES = "messages";
/**
* Execute mail commands.
*
* @param redirector Cocoon's redirector
* @param resolver Cocoon's source resolver, used for testing if a source is resolvable
* @param source the source, e.g.: index.html
* @param objectModel Description of the Parameter
* @param par Description of the Parameter
* @exception Exception Description of the Exception
*/
public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters par)
throws Exception {
Map actionMap = new HashMap();
Request request = ObjectModelHelper.getRequest(objectModel);
String command = request.getParameter("cmd");
String folderName = request.getParameter("folder");
String userid = request.getParameter("mail-userid");
String password = request.getParameter("mail-password");
// assert mailContext is available
Session session = request.getSession(true);
MailContext mailContext = (MailContext) session.getAttribute(MailContext.SESSION_MAIL_CONTEXT);
if (mailContext == null) {
// no mailContext is yet available
// create it and put it into http-session
mailContext = new MailContextHttpSession(null);
mailContext.enableLogging(getLogger());
session.setAttribute(MailContext.SESSION_MAIL_CONTEXT, mailContext);
}
// assert mailSession is available
javax.mail.Session mailSession;
Store mailStore;
try {
try {
mailSession = (javax.mail.Session) mailContext.get(MailContext.MAIL_SESSION_ENTRY);
} catch (ContextException ce) {
// build session properties
Properties sessionProperties = new Properties();
String[] allParameterNames = par.getNames();
for (int i = 0; i < allParameterNames.length; i++) {
String parameterName = allParameterNames[i];
final String PARAMETER_NAME_PREFIX = "javax.mail.Session.props:";
if (parameterName.startsWith(PARAMETER_NAME_PREFIX)) {
String sessionPropName = parameterName.substring(PARAMETER_NAME_PREFIX.length());
String sessionPropValue = par.getParameter(parameterName, null);
if (sessionPropValue != null) {
getLogger().debug("Add session property " +
String.valueOf(sessionPropName) + ": " +
String.valueOf(sessionPropValue));
sessionProperties.put(sessionPropName, sessionPropValue);
}
}
}
mailSession = javax.mail.Session.getDefaultInstance(sessionProperties, null);
checkProviders(mailSession);
mailContext.put(MailContext.MAIL_SESSION_ENTRY, mailSession);
}
} catch (Exception e) {
String message = "Cannot create mail session";
getLogger().error(message, e);
throw new ProcessingException(message, e);
}
// assert mailStore is available
String storeURLNameExpanded = null;
String storeURLNameTemplate = par.getParameter("store-urlname", null);
try {
try {
mailStore = (Store) mailContext.get(MailContext.MAIL_STORE_ENTRY);
} catch (ContextException ce) {
// imap://{userid}:{password}@host:port/
storeURLNameExpanded = getURLNameExpanded(storeURLNameTemplate, userid, password);
URLName urlNameExpanded = new URLName(storeURLNameExpanded);
getLogger().info("get store using URLName " + String.valueOf(urlNameExpanded));
mailStore = mailSession.getStore(urlNameExpanded);
mailStore.connect();
mailContext.put(MailContext.MAIL_STORE_ENTRY, mailStore);
}
} catch (Exception e) {
String message = "Cannot get store, and connect " + String.valueOf(storeURLNameExpanded);
getLogger().error(message, e);
throw new ProcessingException(message, e);
}
if (folderName != null) {
// make folderName the current working folder (a la cwd)
// check foldername a bit
mailContext.put(MailContext.MAIL_CURRENT_WORKING_FOLDER_ENTRY, folderName);
} else {
// no folderName in request parameter, retrieve current working folder
folderName = (String) mailContext.get(MailContext.MAIL_CURRENT_WORKING_FOLDER_ENTRY);
}
actionMap.put(MailContext.MAIL_CURRENT_WORKING_FOLDER_ENTRY, folderName);
if (command != null) {
mailContext.put(MailContext.MAIL_CURRENT_WORKING_COMMAND_ENTRY, command);
} else {
command = (String) mailContext.get(MailContext.MAIL_CURRENT_WORKING_COMMAND_ENTRY);
}
actionMap.put(MailContext.MAIL_CURRENT_WORKING_COMMAND_ENTRY, command);
// mailSession and mailStore are available
// excecute mail command, and populate request attribute
mailContext.setRequest(request);
populateRequestAttribute(request, mailContext);
// it's better to release ref to request, as it is not needed, and helps
// recycling of the request
mailContext.setRequest(null);
return actionMap;
}
/**
* Gets the uRLNameExpanded attribute of the MailGenerator object
*
* @param storeURLNameTemplate Description of the Parameter
* @param userid Description of the Parameter
* @param password Description of the Parameter
* @return The uRLNameExpanded value
*/
protected String getURLNameExpanded(String storeURLNameTemplate, String userid, String password) {
String tokenStart = "''";
String tokenEnd = "''";
Properties filters = new Properties();
filters.put("mail-userid", userid);
filters.put("mail-passwd", password);
return filter(tokenStart, tokenEnd, storeURLNameTemplate, filters);
}
/**
* Replace occurences of <code>TOKEN_STARTxxxTOKEN_END</code> by value of entry xxx in tokens table.
*
* @param tokenStart token start marker
* @param tokenEnd token end marker
* @param s the string examined
* @param tokens Description of the Parameter
* @return String replaced all tokenized entries of original String s.
*/
protected String filter(final String tokenStart, final String tokenEnd, String s, Properties tokens) {
int index = s.indexOf(tokenStart);
if (index > -1) {
try {
StringBuffer b = new StringBuffer();
int i = 0;
String token;
String value;
do {
int endIndex = s.indexOf(tokenEnd, index + tokenStart.length() + 1);
if (endIndex == -1) {
break;
}
token = s.substring(index + tokenStart.length(), endIndex);
b.append(s.substring(i, index));
if (tokens.containsKey(token)) {
value = (String) tokens.get(token);
b.append(value);
i = index + tokenStart.length() + token.length() + tokenEnd.length();
} else {
// just append TOKEN_START and search further
b.append(tokenStart);
i = index + tokenStart.length();
}
} while ((index = s.indexOf(tokenStart, i)) > -1);
b.append(s.substring(i));
return b.toString();
} catch (StringIndexOutOfBoundsException e) {
return s;
}
} else {
return s;
}
}
/**
* Check that the provider need is available
*
* @param session The javamail Session used for checking its providers.
*/
protected void checkProviders(javax.mail.Session session) {
Provider[] providers = session.getProviders();
// just log the available providers
for (int i = 0; i < providers.length; i++) {
getLogger().info("mail provider " + providers[i]);
}
}
/**
* Populate request attribute map.
* <p>
* Execute mail command, and populate request attribute map with
* XMLizable javamail objects, created by the mail command
* </p>
*
* @param request triggering the creation of javamail objects
* @param mailContext javamail context, store, session, folders
* @exception Exception Description of the Exception
*/
protected void populateRequestAttribute(Request request, MailContext mailContext) throws Exception {
String folderName = (String) mailContext.get(MailContext.MAIL_CURRENT_WORKING_FOLDER_ENTRY);
request.setAttribute(MailContext.MAIL_CURRENT_WORKING_FOLDER_ENTRY, folderName);
String command = (String) mailContext.get(MailContext.MAIL_CURRENT_WORKING_COMMAND_ENTRY);
request.setAttribute(MailContext.MAIL_CURRENT_WORKING_COMMAND_ENTRY, command);
// build javamail objects
List javaMailResult = retrieveJavaMailObjects(mailContext);
Iterator javaMailResultIterator;
// put javamail objects into request attribute map
javaMailResultIterator = javaMailResult.iterator();
//Request request = ObjectModelHelper.getRequest(objectModel);
putXMLizerToRequestAttribute(request, javaMailResultIterator);
}
/**
* Put XMLizable javamail objects into request attribute map
*
* @param request holding the destination attribute map
* @param resultIterator Iterator of
*/
protected void putXMLizerToRequestAttribute(Request request, Iterator resultIterator) {
if (resultIterator != null) {
// marshal java mail objects
Logger logger = getLogger();
// make it an optional parameter?
String datePattern = "dd.MM.yyyy HH:mm";
SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
while (resultIterator.hasNext()) {
Object objRef = resultIterator.next();
getLogger().debug("Creating XMLizer for " + String.valueOf(objRef));
if (objRef instanceof Folder) {
MailContentHandlerDelegate.FolderXMLizer fx = new MailContentHandlerDelegate.FolderXMLizer((Folder) objRef);
fx.enableLogging(logger);
request.setAttribute(REQUEST_ATTRIBUTE_FOLDER, fx);
} else if (objRef instanceof Folder[]) {
Folder[] folders = (Folder[]) objRef;
MailContentHandlerDelegate.FolderXMLizer[] fxs = new MailContentHandlerDelegate.FolderXMLizer[folders.length];
for (int i = 0; i < folders.length; i++) {
fxs[i] = new MailContentHandlerDelegate.FolderXMLizer(folders[i]);
fxs[i].enableLogging(logger);
}
// trust that array of XMLizable is handled
request.setAttribute(REQUEST_ATTRIBUTE_FOLDERS, fxs);
} else if (objRef instanceof Message) {
MailContentHandlerDelegate.MessageXMLizer mx = new MailContentHandlerDelegate.MessageXMLizer((Message) objRef);
mx.enableLogging(logger);
mx.setSimpleDateFormat(sdf);
request.setAttribute(REQUEST_ATTRIBUTE_MESSAGE, mx);
} else if (objRef instanceof Message[]) {
MailContentHandlerDelegate.MessageEnvelopeXMLizer mex = new MailContentHandlerDelegate.MessageEnvelopeXMLizer((Message[]) objRef);
mex.enableLogging(logger);
mex.setSimpleDateFormat(sdf);
request.setAttribute(REQUEST_ATTRIBUTE_MESSAGES, mex);
}
}
}
}
/**
* Retrieve javamail objects
*
* @param mailContext Description of the Parameter
* @return List of retrieved javamail objects
* @exception ProcessingException thrown iff retrieval fails
*/
protected List retrieveJavaMailObjects(MailContext mailContext) throws ProcessingException {
List result;
try {
// do we have a MailCommandManager ?
MailCommandManager mam = new MailCommandManager();
mam.enableLogging(getLogger());
// build the MailCommand(s)
MailCommandBuilder mab = new MailCommandBuilder();
mab.enableLogging(getLogger());
AbstractMailCommand ama = mab.buildAbstractMailCommand(mailContext);
getLogger().debug("Executing " + String.valueOf(ama));
// execute the command(s)
result = mam.execute(ama);
// return the javamail objects
return result;
} catch (Exception e) {
String message = "Cannot retrieve javamail objects";
getLogger().error(message, e);
throw new ProcessingException(message, e);
}
}
}