You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by vg...@apache.org on 2006/10/30 21:21:41 UTC

svn commit: r469258 - in /cocoon/branches/BRANCH_2_1_X: ./ src/blocks/mail/java/org/apache/cocoon/acting/ src/blocks/mail/java/org/apache/cocoon/mail/ src/blocks/mail/java/org/apache/cocoon/mail/datasource/ src/blocks/mail/samples/sendmail/

Author: vgritsenko
Date: Mon Oct 30 12:21:40 2006
New Revision: 469258

URL: http://svn.apache.org/viewvc?view=rev&rev=469258
Log:
    <action dev="VG" type="update">
      Mail: Improve MailSender interface: added setBody(Object), setBodyURL
      methods, deprecated setCharset, setBody(String), setBodyFromSrc,
      setBodyFromSrcMimeType methods. Support byte[], InputStream as body and
      attachment objects.
    </action>
and add sample sending email from flowscript.

Added:
    cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/AbstractDataSource.java   (with props)
    cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/InputStreamDataSource.java   (with props)
    cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/mail.js   (with props)
Modified:
    cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/acting/Sendmail.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/MailMessageSender.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/MailSender.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/FilePartDataSource.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/SourceDataSource.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/form.xml
    cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/sitemap.xmap
    cocoon/branches/BRANCH_2_1_X/status.xml

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/acting/Sendmail.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/acting/Sendmail.java?view=diff&rev=469258&r1=469257&r2=469258
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/acting/Sendmail.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/acting/Sendmail.java Mon Oct 30 12:21:40 2006
@@ -209,18 +209,22 @@
             if (parameters.isParameter("subject")) {
                 mms.setSubject(parameters.getParameter("subject", null));
             }
-            if (parameters.isParameter("charset")) {
-                mms.setCharset(parameters.getParameter("charset", null));
-            }
 
-            if (parameters.isParameter("src")) {
-                mms.setBodyFromSrc(parameters.getParameter("src", null));
+            String bodyURL = parameters.getParameter("src", "");
+            String body = parameters.getParameter("body", "");
+            if (bodyURL.length() > 0) {
+                String type = null;
                 if (parameters.isParameter("srcMimeType")) {
-                    mms.setBodyFromSrcMimeType(
-                        parameters.getParameter("srcMimeType", null));
+                    type = parameters.getParameter("srcMimeType", null);
+                }
+                mms.setBodyURL(bodyURL, type);
+            } else if (body.length() > 0) {
+                String type = null;
+                String charset = parameters.getParameter("charset", "");
+                if (charset.length() > 0) {
+                    type = "text/plain; charset=" + charset;
                 }
-            } else if (parameters.isParameter("body")) {
-                mms.setBody(parameters.getParameter("body", null));
+                mms.setBody(body, type);
             }
 
             if (parameters.isParameter("attachments")) {
@@ -235,9 +239,7 @@
                             getLogger().debug("request-attachment: " + obj);
                         }
                     } else {
-                        mms.addAttachmentURL(srcName,
-                                             null,
-                                             srcName.substring(srcName.lastIndexOf('/') + 1));
+                        mms.addAttachmentURL(srcName);
                         if (getLogger().isDebugEnabled()) {
                             getLogger().debug("sitemap-attachment: " + srcName);
                         }

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/MailMessageSender.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/MailMessageSender.java?view=diff&rev=469258&r1=469257&r2=469258
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/MailMessageSender.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/MailMessageSender.java Mon Oct 30 12:21:40 2006
@@ -16,28 +16,17 @@
  */
 package org.apache.cocoon.mail;
 
-import org.apache.avalon.framework.CascadingRuntimeException;
-import org.apache.avalon.framework.activity.Initializable;
-import org.apache.avalon.framework.component.Component;
-import org.apache.avalon.framework.configuration.Configurable;
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.avalon.framework.service.ServiceException;
-import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.avalon.framework.service.Serviceable;
-
-import org.apache.cocoon.mail.datasource.FilePartDataSource;
-import org.apache.cocoon.mail.datasource.SourceDataSource;
-import org.apache.cocoon.servlet.multipart.Part;
-
-import org.apache.excalibur.source.Source;
-import org.apache.excalibur.source.SourceResolver;
-
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
 import javax.activation.DataHandler;
 import javax.activation.DataSource;
 import javax.mail.Authenticator;
-import javax.mail.BodyPart;
 import javax.mail.Message.RecipientType;
 import javax.mail.MessagingException;
 import javax.mail.Multipart;
@@ -49,13 +38,27 @@
 import javax.mail.internet.MimeBodyPart;
 import javax.mail.internet.MimeMessage;
 import javax.mail.internet.MimeMultipart;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Properties;
+import javax.mail.internet.MimePart;
+
+import org.apache.avalon.framework.CascadingRuntimeException;
+import org.apache.avalon.framework.activity.Initializable;
+import org.apache.avalon.framework.component.Component;
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceResolver;
+
+import org.apache.cocoon.mail.datasource.AbstractDataSource;
+import org.apache.cocoon.mail.datasource.FilePartDataSource;
+import org.apache.cocoon.mail.datasource.InputStreamDataSource;
+import org.apache.cocoon.mail.datasource.SourceDataSource;
+import org.apache.cocoon.servlet.multipart.Part;
 
 /**
  * A helper class used by the {@link org.apache.cocoon.acting.Sendmail}
@@ -91,17 +94,33 @@
     private String cc;
     private String bcc;
     private String subject;
-    private String charset;
-    private String src;
-    private String srcMimeType;
-    private String body;
+
+    private Attachment body;
+    private String bodyType;
+    private String bodySrcType;
     private List attachments;
+
     private Exception exception;
 
+
+    /** Java 1.3 Accessor */
+    private Logger getMyLogger() {
+        return getLogger();
+    }
+
+    /**
+     * Check string for null, empty, and "null".
+     * @param str
+     * @return true if str is null, empty string, or equals "null"
+     */
+    private boolean isNullOrEmpty(String str) {
+        return str == null || "".equals(str) || "null".equals(str);
+    }
+
     /**
      * Helper class for attachment data.
      */
-    private static class Attachment {
+    private class Attachment {
         private Object obj;
         private String type;
         private String name;
@@ -137,24 +156,17 @@
             this.type = type;
             this.name = name;
             this.isURL = isURI;
+
             if (isNullOrEmpty(this.type)) {
                 this.type = null;
             }
+
             if (isNullOrEmpty(this.name)) {
                 this.name = null;
             }
         }
 
         /**
-         * Check String for null or empty.
-         * @param str
-         * @return true if str is null, empty string, or equals "null"
-         */
-        private boolean isNullOrEmpty(String str) {
-            return str == null || "".equals(str) || "null".equals(str);
-        }
-
-        /**
          * Is the encapsulated object a URL?
          * @return true if URL
          */
@@ -163,21 +175,25 @@
         }
 
         /**
-         * Return attachment name. The argument overrides the stored name.
-         * @param name
-         * @return stored name or otherwise parameter
+         * Is the encapsulated object a text?
+         * @return true if text (String object)
          */
-        public String getName(String name) {
-            return (this.name == null ? name : this.name);
+        public boolean isText() {
+            return !isURL() && this.obj instanceof String;
         }
 
         /**
-         * Return attachment type. The argument overrides the stored type.
-         * @param type  attachment type
-         * @return stored type or otherwise parameter
+         * Return attachment name.
          */
-        public String getType(String type) {
-            return (this.type == null ? type : this.type);
+        public String getName() {
+            return this.name;
+        }
+
+        /**
+         * Return attachment type.
+         */
+        public String getType() {
+            return this.type;
         }
 
         /**
@@ -186,6 +202,94 @@
         public Object getObject() {
             return this.obj;
         }
+
+        public String getText() {
+            return (String) this.obj;
+        }
+
+        public DataSource getDataSource(SourceResolver resolver, List sources)
+        throws IOException, MessagingException {
+            AbstractDataSource ds = null;
+
+            if (isURL) {
+                String url = (String) getObject();
+                Source src = resolver.resolveURI(url);
+                sources.add(src);
+                if (src.exists()) {
+                    ds = new SourceDataSource(src, getType(), getName());
+                }
+            } else if (getObject() instanceof Part) {
+                Part part = (Part) getObject();
+                ds = new FilePartDataSource(part, getType(), getName());
+            } else if (getObject() instanceof InputStream) {
+                InputStream in = (InputStream) getObject();
+                ds = new InputStreamDataSource(in, getType(), getName());
+            } else if (getObject() instanceof byte[]) {
+                byte[] data = (byte[]) getObject();
+                ds = new InputStreamDataSource(data, getType(), getName());
+            } else {
+                // TODO: other classes?
+                throw new MessagingException("Not yet supported: " + getObject());
+            }
+
+            if (ds != null) {
+                ds.enableLogging(getMyLogger());
+            }
+            return ds;
+        }
+
+        public void setContentTo(SourceResolver resolver, List sources, MimePart part)
+        throws IOException, MessagingException {
+            if (isText()) {
+                // Set text
+                if (type != null) {
+                    part.setContent(getText(), type);
+                } else {
+                    // Let JavaMail decide on character encoding.
+                    part.setText(getText());
+                }
+                if (name != null) {
+                    part.setFileName(name);
+                }
+            } else {
+                // Set data
+                DataSource ds = getDataSource(resolver, sources);
+                part.setDataHandler(new DataHandler(ds));
+                String name = ds.getName();
+                if (name != null) {
+                    part.setFileName(name);
+                }
+            }
+        }
+
+        public MimeBodyPart getBodyPart(SourceResolver resolver, List sources)
+        throws IOException, MessagingException {
+            MimeBodyPart part = new MimeBodyPart();
+            setContentTo(resolver, sources, part);
+            return part;
+        }
+    }
+
+    private class Body extends Attachment {
+        public Body(Object obj) {
+            super(obj);
+        }
+
+        public Body(Object obj, String type) {
+            super(obj, type, null);
+        }
+
+        public Body(Object obj, String type, boolean isURI) {
+            super(obj, type, null, isURI);
+        }
+
+        // Override to set name to null: body can not have name.
+        public DataSource getDataSource(SourceResolver resolver, List sources)
+        throws IOException, MessagingException {
+            AbstractDataSource ds = (AbstractDataSource) super.getDataSource(resolver, sources);
+            ds.setName(null);
+            return ds;
+        }
     }
 
 
@@ -193,8 +297,9 @@
     }
 
     /**
-     * Creates a new instance of MailMessageSender
+     * Creates a new instance of MailMessageSender.
      * Keep constructor for backwards compatibility.
+     *
      * @param smtpHost The host name or ip-address of a host to accept
      *                 the email for delivery.
      * @deprecated Since 2.1.5. Please use {@link MailSender} component instead.
@@ -209,18 +314,12 @@
         this.manager = manager;
     }
 
-    /* (non-Javadoc)
-     * @see Parameterizable#parameterize(Parameters)
-     */
     public void configure(Configuration config) throws ConfigurationException {
         this.smtpHost = config.getChild("smtp-host").getValue(null);
         this.smtpUser = config.getChild("smtp-user").getValue(null);
         this.smtpPswd = config.getChild("smtp-password").getValue(null);
     }
 
-    /* (non-Javadoc)
-     * @see Initializable#initialize()
-     */
     public void initialize() {
         initSession();
         this.attachments = new ArrayList();
@@ -262,6 +361,7 @@
 
     /**
      * Assemble the message from the defined fields and send it.
+     *
      * @throws AddressException when problems with email addresses are found
      * @throws MessagingException when message could not be send.
      */
@@ -279,6 +379,7 @@
 
     /**
      * Assemble the message from the defined fields and send it.
+     *
      * @throws AddressException when problems with email addresses are found
      * @throws MessagingException when message could not be send.
      * @deprecated Since 2.1.5. Use {@link #send()} which doesn't require passing the source resolver
@@ -291,7 +392,6 @@
 
     private void doSend(SourceResolver resolver)
     throws AddressException, MessagingException {
-        final List sourcesList = new ArrayList();
 
         final MimeMessage message = new MimeMessage(this.session);
 
@@ -354,100 +454,43 @@
         message.setSentDate(new Date());
 
         Attachment a = null;
+        final List sources = new ArrayList();
         try {
             if (this.attachments.isEmpty()) {
-                if (this.src != null) {
-                    SourceDataSource ds = null;
-
-                    Source source = resolver.resolveURI(this.src);
-                    sourcesList.add(source);
-                    if (source.exists()) {
-                        ds = new SourceDataSource(source,
-                                                  this.srcMimeType == null? source.getMimeType(): this.srcMimeType,
-                                                  this.src.substring(this.src.lastIndexOf('/') + 1));
-                        ds.enableLogging(getLogger());
-                    }
-
-                    message.setDataHandler(new DataHandler(ds));
-
-                } else if (this.body != null) {
-                    if (this.charset != null) {
-                        message.setText(this.body, this.charset);
-                    } else {
-                        message.setText(this.body);
-                    }
+                // Message consists of single part
+                if (this.body != null) {
+                    a = this.body;
+                    a.setContentTo(resolver, sources, message);
                 }
             } else {
+                // Message consists of multiple parts
                 Multipart multipart = new MimeMultipart();
-                BodyPart bodypart = new MimeBodyPart();
-                multipart.addBodyPart(bodypart);
                 message.setContent(multipart);
 
-                if (this.src != null) {
-                    SourceDataSource ds = null;
-
-                    Source source = resolver.resolveURI(this.src);
-                    sourcesList.add(source);
-                    if (source.exists()) {
-                        ds = new SourceDataSource(source,
-                                                  this.srcMimeType == null? source.getMimeType(): this.srcMimeType,
-                                                  this.src.substring(this.src.lastIndexOf('/') + 1));
-                        ds.enableLogging(getLogger());
-                    }
-
-                    bodypart.setDataHandler(new DataHandler(ds));
-                    bodypart.setFileName(ds.getName());
-
-                } else if (this.body != null) {
-                    bodypart.setText(this.body);
+                // Body part
+                if (this.body != null) {
+                    a = this.body;
+                    multipart.addBodyPart(a.getBodyPart(resolver, sources));
                 }
 
+                // Attachment parts
                 for (Iterator i = this.attachments.iterator(); i.hasNext();) {
                     a = (Attachment) i.next();
-                    DataSource ds = null;
-
-                    if (a.isURL) {
-                        String name = (String) a.getObject();
-                        Source src = resolver.resolveURI(name);
-                        sourcesList.add(src);
-                        if (src.exists()) {
-                            ds = new SourceDataSource(src,
-                                                      a.getType(src.getMimeType()),
-                                                      a.getName(name.substring(name.lastIndexOf('/') + 1)));
-                            ((SourceDataSource) ds).enableLogging(getLogger());
-                        }
-                    } else {
-                        if (a.getObject() instanceof Part) {
-                            Part part = (Part) a.getObject();
-                            ds = new FilePartDataSource(part,
-                                                        a.getType(part.getMimeType()),
-                                                        a.getName(part.getUploadName()));
-                        } else {
-                            // TODO: other classes?
-                            throw new AddressException("Not yet supported: " + a.getObject());
-                        }
-                    }
-
-                    bodypart = new MimeBodyPart();
-                    bodypart.setDataHandler(new DataHandler(ds));
-                    bodypart.setFileName(ds.getName());
-                    multipart.addBodyPart(bodypart);
+                    multipart.addBodyPart(a.getBodyPart(resolver, sources));
                 }
             }
 
             message.saveChanges();
             Transport.send(message);
         } catch (MalformedURLException e) {
-            throw new AddressException("Malformed attachment URL: " +
-                                       a.getObject() + " error " + e.getMessage());
+            throw new MessagingException("Malformed attachment URL: " +
+                                         a.getObject() + " error " + e.getMessage());
         } catch (IOException e) {
-            throw new AddressException("IOException accessing attachment URL: " +
-                                       a.getObject() + " error " + e.getMessage());
+            throw new MessagingException("IOException accessing attachment URL: " +
+                                         a.getObject() + " error " + e.getMessage());
         } finally {
-            if (sourcesList != null) {
-                for (Iterator j = sourcesList.iterator(); j.hasNext();) {
-                    resolver.release((Source) j.next());
-                }
+            for (Iterator j = sources.iterator(); j.hasNext();) {
+                resolver.release((Source) j.next());
             }
         }
     }
@@ -455,6 +498,7 @@
     /**
      * Invokes the {@link #send()} method but catches any exception thrown. This
      * method is intended to be used from the sendmail logicsheet.
+     *
      * @return true when successful
      */
     public boolean sendIt() {
@@ -497,11 +541,12 @@
 
 
     /**
-     * Set the <CODE>from</CODE> address of the message.
+     * Set the <code>from</code> address of the message.
+     *
      * @param from The address the message appears to be from.
      */
     public void setFrom(String from) {
-        if (!("".equals(from) || "null".equals(from))) {
+        if (!isNullOrEmpty(from)) {
             this.from = from.trim();
         }
     }
@@ -511,11 +556,12 @@
      * is in the format, that
      * {@link javax.mail.internet.InternetAddress#parse(String)} can handle
      * (one or more email addresses separated by a commas).
+     *
      * @param to the destination address(es)
      * @see javax.mail.internet.InternetAddress#parse(String)
      */
     public void setTo(String to) {
-        if (!("".equals(to) || "null".equals(to))) {
+        if (!isNullOrEmpty(to)) {
             this.to = to.trim();
         }
     }
@@ -525,11 +571,12 @@
      * is in the format, that
      * {@link javax.mail.internet.InternetAddress#parse(String)} can handle
      * (one or more email addresses separated by a commas).
+     *
      * @param replyTo the address(es) that replies should be sent to
      * @see javax.mail.internet.InternetAddress#parse(String)
      */
     public void setReplyTo(String replyTo) {
-        if (!("".equals(replyTo) || "null".equals(replyTo))) {
+        if (!isNullOrEmpty(replyTo)) {
             this.replyTo = replyTo.trim();
         }
     }
@@ -539,11 +586,12 @@
      * message. The address is in the format, that
      * {@link javax.mail.internet.InternetAddress#parse(String)} can handle
      * (one or more email addresses separated by a commas).
+     *
      * @param cc the address(es), which should receive a carbon copy.
      * @see javax.mail.internet.InternetAddress#parse(String)
      */
     public void setCc(String cc) {
-        if (!("".equals(cc) || "null".equals(cc))) {
+        if (!isNullOrEmpty(cc)) {
             this.cc = cc.trim();
         }
     }
@@ -553,33 +601,39 @@
      * the message. The address is in the format, that
      * {@link javax.mail.internet.InternetAddress#parse(String)} can handle
      * (one or more email addresses separated by a commas).
+     *
      * @param bcc the address(es), which should receive a black carbon copy.
      * @see javax.mail.internet.InternetAddress#parse(String)
      */
     public void setBcc(String bcc) {
-        if (!("".equals(bcc) || "null".equals(bcc))) {
+        if (!isNullOrEmpty(bcc)) {
             this.bcc = bcc.trim();
         }
     }
 
     /**
-     * Sets the character set for encoding the message. This has no effect,
-     * if any attachments are send in the message.
-     * @param charset the character set to be used for enbcoding the message
+     * Sets the subject line of the message.
+     *
+     * @param subject the subject line of the message
      */
-    public void setCharset(String charset) {
-        if (!("".equals(charset) || "null".equals(charset))) {
-            this.charset = charset.trim();
+    public void setSubject(String subject) {
+        if (!isNullOrEmpty(subject)) {
+            this.subject = subject;
         }
     }
 
     /**
-     * Sets the subject line of the message.
-     * @param subject the subject line of the message
+     * Sets the character set for encoding the message. This has no effect,
+     * if any attachments are send in the message.
+     *
+     * @param charset the character set to be used for enbcoding the message
      */
-    public void setSubject(String subject) {
-        if (!("".equals(subject) || "null".equals(subject))) {
-            this.subject = subject;
+    public void setCharset(String charset) {
+        if (!isNullOrEmpty(charset)) {
+            this.bodyType = "text/plain; charset=" + charset.trim();
+            if (this.body != null && this.body.isText() && this.body.type == null) {
+                this.body.type = this.bodyType;
+            }
         }
     }
 
@@ -589,10 +643,11 @@
      * only the latter will be used.
      *
      * @param body The body text of the email message
+     * @deprecated Since 2.1.10. Use {@link #setBody(Object)}
      */
     public void setBody(String body) {
-        if (!("".equals(body) || "null".equals(body))) {
-            this.body = body;
+        if (!isNullOrEmpty(body)) {
+            setBody(body, bodyType);
         }
     }
 
@@ -602,31 +657,91 @@
      * only the latter will be used.
      *
      * @param src The body source URL of the email message
+     * @deprecated Since 2.1.10. Use {@link #setBodyURL(String)}
      */
     public void setBodyFromSrc(String src) {
-        if (!("".equals(src) || "null".equals(src))) {
-            this.src = src;
+        if (!isNullOrEmpty(src)) {
+           setBodyURL(src, bodySrcType);
         }
     }
 
     /**
      * Sets the optional body source Mime Type of the email message.
+     *
      * @param srcMimeType The optional body source Mime Type of the email message
+     * @deprecated Since 2.1.10. Use {@link #setBodyURL(String, String)}
      */
     public void setBodyFromSrcMimeType(String srcMimeType) {
-        if (!("".equals(srcMimeType) || "null".equals(srcMimeType))) {
-            this.srcMimeType = srcMimeType;
+        if (!isNullOrEmpty(srcMimeType)) {
+            this.bodySrcType = srcMimeType;
+            // Pass into this.body if it was set.
+            if (this.body != null && this.body.isURL() && this.body.type == null) {
+                this.body.type = srcMimeType;
+            }
         }
     }
 
     /**
-     * Add an attachement to the message to be send. The attachment can
-     * be of type <CODE>org.apache.excalibur.source.Source</CODE> or
-     * {@link org.apache.cocoon.servlet.multipart.Part} or its
-     * subclasses.
-     * @param attachment to be send with the message
+     * Sets the body content of the email message.
+     *
+     * <p>The body can be any of: {@link org.apache.excalibur.source.Source},
+     * {@link org.apache.cocoon.servlet.multipart.Part}, {@link java.io.InputStream},
+     * <code>byte[]</code>, {@link String}, or a subclass.
+     *
+     * @param body The body text of the email message
+     */
+    public void setBody(Object body) {
+        setBody(body, null);
+    }
+
+    /**
+     * Sets the body content of the email message.
+     *
+     * <p>The body can be any of: {@link org.apache.excalibur.source.Source},
+     * {@link org.apache.cocoon.servlet.multipart.Part}, {@link java.io.InputStream},
+     * <code>byte[]</code>, {@link String}, or a subclass.
+     *
+     * @param body The body text of the email message
+     * @param type mime type (optional)
+     */
+    public void setBody(Object body, String type) {
+        if (body != null) {
+            this.body = new Body(body, type);
+        }
+    }
+
+    /**
+     * Sets the body content of the email message.
+     *
+     * @param url URL to use as message body
      * @see org.apache.excalibur.source.Source
      */
+    public void setBodyURL(String url) {
+        setBodyURL(url, null);
+    }
+
+    /**
+     * Sets the body content of the email message.
+     *
+     * @param url URL to use as message body
+     * @param type mime type (optional)
+     * @see org.apache.excalibur.source.Source
+     */
+    public void setBodyURL(String url, String type) {
+        if (body != null) {
+            this.body = new Body(url, type, true);
+        }
+    }
+
+    /**
+     * Add an attachement to the message to be send.
+     *
+     * <p>The attachment can be any of: {@link org.apache.excalibur.source.Source},
+     * {@link org.apache.cocoon.servlet.multipart.Part}, {@link java.io.InputStream},
+     * <code>byte[]</code>, {@link String}, or a subclass.
+     *
+     * @param attachment to be send with the message
+     */
     public void addAttachment(Object attachment) {
         if (attachment != null) {
             attachments.add(new Attachment(attachment));
@@ -634,14 +749,15 @@
     }
 
     /**
-     * Add an attachement to the message to be send. The attachment can
-     * be of type <CODE>org.apache.excalibur.source.Source</CODE> or
-     * {@link org.apache.cocoon.servlet.multipart.Part} or its
-     * subclasses.
+     * Add an attachement to the message to be send.
+     *
+     * <p>The attachment can be any of: {@link org.apache.excalibur.source.Source},
+     * {@link org.apache.cocoon.servlet.multipart.Part}, {@link java.io.InputStream},
+     * <code>byte[]</code>, {@link String}, or a subclass.
+     *
      * @param attachment to be send with the message
      * @param type mime type (optional)
      * @param name attachment name (optional)
-     * @see org.apache.excalibur.source.Source
      */
     public void addAttachment(Object attachment, String type, String name) {
         if (attachment != null) {
@@ -650,10 +766,8 @@
     }
 
     /**
-     * Add an attachement to the message to be send. The attachment can
-     * be of type <CODE>org.apache.excalibur.source.Source</CODE> or
-     * {@link org.apache.cocoon.servlet.multipart.Part} or its
-     * subclasses.
+     * Add an attachement to the message to be send.
+     *
      * @param url URL to attach to the message
      * @see org.apache.excalibur.source.Source
      */
@@ -664,10 +778,8 @@
     }
 
     /**
-     * Add an attachement to the message to be send. The attachment can
-     * be of type <CODE>org.apache.excalibur.source.Source</CODE> or
-     * {@link org.apache.cocoon.servlet.multipart.Part} or its
-     * subclasses.
+     * Add an attachement to the message to be send.
+     *
      * @param url URL to attach to the message
      * @param type mime type (optional)
      * @param name attachment name (optional)

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/MailSender.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/MailSender.java?view=diff&rev=469258&r1=469257&r2=469258
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/MailSender.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/MailSender.java Mon Oct 30 12:21:40 2006
@@ -16,16 +16,20 @@
  */
 package org.apache.cocoon.mail;
 
-import org.apache.cocoon.environment.SourceResolver;
 import javax.mail.MessagingException;
 import javax.mail.internet.AddressException;
 
+import org.apache.cocoon.environment.SourceResolver;
+
 /**
  * A helper component used by the {@link org.apache.cocoon.acting.Sendmail}
- * and the <code>sendmail.xsl</code> logicsheet for sending an email message.
+ * action and the <code>sendmail.xsl</code> logicsheet for sending email messages.
+ *
+ * <p>Please note that this component is not (and can not) be
+ * {@link org.apache.avalon.framework.thread.ThreadSafe}, so you need to lookup
+ * new instance in each processing thread.
  *
  * @since 2.1.5
- * @author <a href="mailto:haul@apache.org">Christian Haul</a>
  * @version $Id$
  */
 public interface MailSender {
@@ -52,6 +56,7 @@
 
     /**
      * Set the <code>from</code> address of the message.
+     *
      * @param from The address the message appears to be from.
      */
     void setFrom(String from);
@@ -61,6 +66,7 @@
      * is in the format, that
      * {@link javax.mail.internet.InternetAddress#parse(String)} can handle
      * (one or more email addresses separated by a commas).
+     *
      * @param to the destination address(es)
      * @see javax.mail.internet.InternetAddress#parse(String)
      */
@@ -71,6 +77,7 @@
      * is in the format, that
      * {@link javax.mail.internet.InternetAddress#parse(String)} can handle
      * (one or more email addresses separated by a commas).
+     *
      * @param replyTo the address(es) that replies should be sent to
      * @see javax.mail.internet.InternetAddress#parse(String)
      */
@@ -81,6 +88,7 @@
      * message. The address is in the format, that
      * {@link javax.mail.internet.InternetAddress#parse(String)} can handle
      * (one or more email addresses separated by a commas).
+     *
      * @param cc the address(es), which should receive a carbon copy.
      * @see javax.mail.internet.InternetAddress#parse(String)
      */
@@ -91,29 +99,38 @@
      * the message. The address is in the format, that
      * {@link javax.mail.internet.InternetAddress#parse(String)} can handle
      * (one or more email addresses separated by a commas).
+     *
      * @param bcc the address(es), which should receive a black carbon copy.
      * @see javax.mail.internet.InternetAddress#parse(String)
      */
     void setBcc(String bcc);
 
     /**
-     * Sets the character set for encoding the message. This has no effect,
-     * if any attachments are send in the message.
-     * @param charset the character set to be used for enbcoding the message
-     */
-    void setCharset(String charset);
-
-    /**
      * Sets the subject line of the message.
      * @param subject the subject line of the message
      */
     void setSubject(String subject);
 
+    //
+    // Set the Body
+    //
+
+    /**
+     * Sets the character set for encoding the message. This has effect
+     * only on text set via {@link #setBody(String)}.
+     *
+     * @param charset the character set to be used for encoding the message
+     * @deprecated Since 2.1.10. Use {@link #setBody(Object, String)}
+     */
+    void setCharset(String charset);
+
     /**
      * Sets the body text of the email message.
      * If both a text body and a body read from a source are set,
      * only the latter will be used.
+     *
      * @param body The body text of the email message
+     * @deprecated Since 2.1.10. Use {@link #setBody(Object)}
      */
     void setBody(String body);
 
@@ -121,53 +138,99 @@
      * Sets the body source URL of the email message.
      * If both a text body and a body read from a source are set,
      * only the latter will be used.
+     *
      * @param src The body source URL of the email message
+     * @deprecated Since 2.1.10. Use {@link #setBodyURL(String)}
      */
     void setBodyFromSrc(String src);
 
     /**
      * Sets the optional body source Mime Type of the email message.
+     *
      * @param srcMimeType The optional body source Mime Type of the email message
+     * @deprecated Since 2.1.10. Use {@link #setBodyURL(String, String)}
      */
     void setBodyFromSrcMimeType(String srcMimeType);
 
     /**
-     * Add an attachement to the message to be send. The attachment can
-     * be of type <CODE>org.apache.excalibur.source.Source</CODE> or
-     * {@link org.apache.cocoon.servlet.multipart.Part} or its
-     * subclasses.
-     * @param attachment to be send with the message
+     * Sets the body content of the email message.
+     *
+     * <p>The body can be any of: {@link org.apache.excalibur.source.Source},
+     * {@link org.apache.cocoon.servlet.multipart.Part}, {@link java.io.InputStream},
+     * <code>byte[]</code>, {@link String}, or a subclass.
+     *
+     * @param body The body text of the email message
+     */
+    void setBody(Object body);
+
+    /**
+     * Sets the body content of the email message.
+     *
+     * <p>The body can be any of: {@link org.apache.excalibur.source.Source},
+     * {@link org.apache.cocoon.servlet.multipart.Part}, {@link java.io.InputStream},
+     * <code>byte[]</code>, {@link String}, or a subclass.
+     *
+     * @param body The body text of the email message
+     * @param type mime type (optional)
+     */
+    void setBody(Object body, String type);
+
+    /**
+     * Sets the body content of the email message.
+     *
+     * @param url URL to use as message body
      * @see org.apache.excalibur.source.Source
      */
+    void setBodyURL(String url);
+
+    /**
+     * Sets the body content of the email message.
+     *
+     * @param url URL to use as message body
+     * @param type mime type (optional)
+     * @see org.apache.excalibur.source.Source
+     */
+    void setBodyURL(String url, String type);
+
+    //
+    // Add Attachments
+    //
+
+    /**
+     * Add an attachement to the message to be send.
+     *
+     * <p>The attachment can be any of: {@link org.apache.excalibur.source.Source},
+     * {@link org.apache.cocoon.servlet.multipart.Part}, {@link java.io.InputStream},
+     * <code>byte[]</code>, {@link String}, or a subclass.
+     *
+     * @param attachment to be send with the message
+     */
     void addAttachment(Object attachment);
 
     /**
-     * Add an attachement to the message to be send. The attachment can
-     * be of type <CODE>org.apache.excalibur.source.Source</CODE> or
-     * {@link org.apache.cocoon.servlet.multipart.Part} or its
-     * subclasses.
+     * Add an attachement to the message to be send.
+     *
+     * <p>The attachment can be any of: {@link org.apache.excalibur.source.Source},
+     * {@link org.apache.cocoon.servlet.multipart.Part}, {@link java.io.InputStream},
+     * <code>byte[]</code>, {@link String}, or a subclass.
+     *
      * @param attachment to be send with the message
      * @param type mime type (optional)
      * @param name attachment name (optional)
-     * @see org.apache.excalibur.source.Source
      */
     void addAttachment(Object attachment, String type, String name);
 
     /**
-     * Add an attachement to the message to be send. The attachment can
-     * be of type <CODE>org.apache.excalibur.source.Source</CODE> or
-     * {@link org.apache.cocoon.servlet.multipart.Part} or its
-     * subclasses.
+     * Add an attachement to the message to be send.
+     *
      * @param url URL to attach to the message
      * @see org.apache.excalibur.source.Source
      */
     void addAttachmentURL(String url);
 
     /**
-     * Add an attachement to the message to be send. The attachment can
-     * be of type <CODE>org.apache.excalibur.source.Source</CODE> or
-     * {@link org.apache.cocoon.servlet.multipart.Part} or its
-     * subclasses.
+     * Add an attachement to the message to be send.
+     *
      * @param url URL to attach to the message
      * @param type mime type (optional)
      * @param name attachment name (optional)

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/AbstractDataSource.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/AbstractDataSource.java?view=auto&rev=469258
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/AbstractDataSource.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/AbstractDataSource.java Mon Oct 30 12:21:40 2006
@@ -0,0 +1,90 @@
+/*
+ * Created by IntelliJ IDEA.
+ * User: Vadim
+ * Date: Oct 27, 2006
+ * Time: 12:29:43 PM
+ */
+package org.apache.cocoon.mail.datasource;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import javax.activation.DataSource;
+
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+
+/**
+ * The AbstractDataSource class is a base class for other {@link DataSource}
+ * implementation.
+ *
+ * @version $Id$
+ */
+public abstract class AbstractDataSource extends AbstractLogEnabled
+                                         implements DataSource {
+
+    private String name;
+    private String contentType;
+
+
+    public AbstractDataSource() {
+    }
+
+    /**
+     * @param name Name of the content part
+     * @param type Mime type of the content
+     */
+    public AbstractDataSource(String name, String type) {
+        this.name = name;
+        this.contentType = type;
+        if (isNullOrEmpty(this.name)) {
+            this.name = null;
+        }
+        if (isNullOrEmpty(this.contentType)) {
+            this.contentType = null;
+        }
+    }
+
+    /**
+     * Check String for null or empty.
+     * @param str
+     * @return true if str is null, empty string, or equals "null"
+     */
+    protected static boolean isNullOrEmpty(String str) {
+        return str == null || "".equals(str) || "null".equals(str);
+    }
+
+    /**
+     * Returns the name for this <code>DataSource</code> object.
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * @return The content type (mime type) of this <code>DataSource</code> object.
+     */
+    public String getContentType() {
+        return this.contentType;
+    }
+
+    public void setContentType(String contentType) {
+        this.contentType = contentType;
+    }
+
+    /**
+     * Get the <code>InputStream</code> for this DataSource.
+     */
+    public abstract InputStream getInputStream() throws IOException;
+
+    /**
+     * Not implemented. Throws <code>IOException</code>.
+     * @throws java.io.IOException since unimplemented
+     */
+    public OutputStream getOutputStream() throws IOException {
+        throw new IOException("no data sink available");
+    }
+}

Propchange: cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/AbstractDataSource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/AbstractDataSource.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/FilePartDataSource.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/FilePartDataSource.java?view=diff&rev=469258&r1=469257&r2=469258
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/FilePartDataSource.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/FilePartDataSource.java Mon Oct 30 12:21:40 2006
@@ -19,27 +19,19 @@
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
-
-import javax.activation.DataSource;
 
 import org.apache.cocoon.servlet.multipart.Part;
 
 /**
  * The FilePartDataSource class provides an object, that wraps a
- * Cocoon {@link Part}
- * object in a DataSource interface.
- * @see javax.activation.DataSource
+ * Cocoon {@link Part} object in a DataSource interface.
  *
- * @author <a href="mailto:frank.ridderbusch@gmx.de">Frank Ridderbusch</a>
- * @author <a href="mailto:haul@apache.org">Christian Haul</a>
+ * @see javax.activation.DataSource
  * @version $Id$
  */
-public class FilePartDataSource implements DataSource {
+public class FilePartDataSource extends AbstractDataSource {
 
     private Part part;
-    private String contentType;
-    private String name;
 
     /**
      * Creates a new instance of FilePartDataSource from an
@@ -56,75 +48,70 @@
      * @param part An {@link Part} object.
      */
     public FilePartDataSource(Part part, String type, String name) {
+        super(getName(name, part), getType(type, part));
         this.part = part;
-        this.contentType = type;
-        this.name = name;
-        if (isNullOrEmpty(this.name)) this.name = null;
-        if (isNullOrEmpty(this.contentType)) this.contentType = null;
     }
 
     /**
-     * Check String for null or empty.
-     * @param str
-     * @return true if str is null, empty string, or equals "null"
-     */
-     private boolean isNullOrEmpty(String str) {
-         return (str == null || "".equals(str) || "null".equals(str));
-     }
+     * Determines the name for this <code>DataSource</code> object.
+     * It is first non empty value from the list:
+     * <ul>
+     * <li>The value of <code>name</code> argument.
+     * <li>The value returned by the {@link Part#getFileName()}.
+     * <li>"attachment".
+     * </ul>
+     *
+     * @return the name for this <code>DataSource</code>
+     */
+    private static String getName(String name, Part part) {
+        if (isNullOrEmpty(name)) {
+            name = part.getFileName();
+            if (isNullOrEmpty(name)) {
+                name = "attachment";
+            }
+        }
+
+        return name;
+    }
 
     /**
-     * Return the content type (mime type) obtained from
-     * {@link Part#getMimeType()}.
-     * Return <CODE>application/octet-stream</CODE> if <CODE>getMimeType()</CODE>
-     * returns <CODE>null</CODE>.
-     * @return The content type (mime type) for this <CODE>DataSource</CODE> object.
-     */
-    public String getContentType() {
-        if (this.contentType != null) {
-            return this.contentType;
-        }
-        String mimeType = part.getMimeType();
-        if (isNullOrEmpty(mimeType)) {
-            mimeType = "application/octet-stream";
+     * Determines the mime type for this <code>DataSource</code> object.
+     * It is first non empty value from the list:
+     * <ul>
+     * <li>The value of <code>type</code> argument.
+     * <li>The value returned by {@link Part#getMimeType()}.
+     * <li>"application/octet-stream".
+     * </ul>
+     *
+     * @return The content type (mime type) of this <code>DataSource</code> object.
+     */
+    private static String getType(String type, Part part) {
+        if (isNullOrEmpty(type)) {
+            type = part.getMimeType();
+            if (isNullOrEmpty(type)) {
+                type = "application/octet-stream";
+            }
         }
-        return mimeType;
+
+        return type;
     }
 
     /**
-     * The InputStream object obtained from
-     * {@link Part#getInputStream()}
+     * The InputStream object obtained from {@link Part#getInputStream()}
      * object.
+     *
      * @throws java.io.IOException if an I/O error occurs.
-     * @return The InputStream object for this <CODE>DataSource</CODE> object.
+     * @return The InputStream object for this <code>DataSource</code> object.
      */
     public InputStream getInputStream() throws IOException {
-        InputStream inp;
         try {
-            inp = part.getInputStream();
-        } catch (Exception e) {
-            throw new IOException(e.getMessage());
+            return part.getInputStream();
+        } catch (IOException e) {
+            // Sun's SMTPTransport looses cause exception. Log it now.
+            if (getLogger() != null) {
+                getLogger().warn("Unable to obtain input stream for '" + part.getUploadName() + "'", e);
+            }
+            throw e;
         }
-        return inp;
-    }
-
-    /**
-     * Returns the name for this <CODE>DataSource</CODE> object. This is
-     * what is returned by
-     * {@link Part#getFileName()}.
-     * @return the name for this <CODE>DataSource</CODE> object.
-     */
-    public String getName() {
-        String name = (this.name != null ? this.name : part.getFileName());
-        if (isNullOrEmpty(name)) name="attachment";
-        return name;
-    }
-
-    /**
-     * Unimplemented. Directly throws <CODE>IOException</CODE>.
-     * @throws java.io.IOException since unimplemented
-     * @return nothing
-     */
-    public OutputStream getOutputStream() throws IOException {
-        throw new IOException("no data sink available");
     }
 }

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/InputStreamDataSource.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/InputStreamDataSource.java?view=auto&rev=469258
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/InputStreamDataSource.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/InputStreamDataSource.java Mon Oct 30 12:21:40 2006
@@ -0,0 +1,114 @@
+/*
+ * Created by IntelliJ IDEA.
+ * User: Vadim
+ * Date: Oct 27, 2006
+ * Time: 12:43:13 PM
+ */
+package org.apache.cocoon.mail.datasource;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.excalibur.source.SourceUtil;
+
+/**
+ * The InputStreamDataSource class provides an object, that wraps an
+ * {@link InputStream} object in a DataSource interface.
+ *
+ * @see javax.activation.DataSource
+ * @version $Id$
+ */
+public class InputStreamDataSource extends AbstractDataSource {
+
+    private byte[] data;
+
+    /**
+     * Creates a new instance of FilePartDataSource from an
+     * {@link InputStream} object.
+     *
+     * @param in An {@link InputStream} object.
+     */
+    public InputStreamDataSource(InputStream in) throws IOException {
+        this(in, null, null);
+    }
+
+    /**
+     * Creates a new instance of FilePartDataSource from a byte array.
+     */
+    public InputStreamDataSource(byte[] data, String type, String name) {
+        super(getName(name), getType(type));
+
+        if (data == null) {
+            this.data = new byte[0];
+        } else {
+            this.data = data;
+        }
+    }
+
+    /**
+     * Creates a new instance of FilePartDataSource from an
+     * {@link InputStream} object.
+     *
+     * @param in An {@link InputStream} object.
+     */
+    public InputStreamDataSource(InputStream in, String type, String name) throws IOException {
+        super(getName(name), getType(type));
+
+        // Need to copy contents of InputStream into byte array since getInputStream
+        // method is called more than once by JavaMail API.
+        if (in == null) {
+            data = new byte[0];
+        } else {
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            SourceUtil.copy(in, out);
+            data = out.toByteArray();
+        }
+    }
+
+    /**
+     * Determines the name for this <code>DataSource</code> object.
+     * It is first non empty value from the list:
+     * <ul>
+     * <li>The value of <code>name</code> argument.
+     * <li>"attachment".
+     * </ul>
+     *
+     * @return the name for this <code>DataSource</code>
+     */
+    private static String getName(String name) {
+        if (isNullOrEmpty(name)) {
+            name = "attachment";
+        }
+
+        return name;
+    }
+
+    /**
+     * Determines the mime type for this <code>DataSource</code> object.
+     * It is first non empty value from the list:
+     * <ul>
+     * <li>The value of <code>type</code> argument.
+     * <li>"application/octet-stream".
+     * </ul>
+     *
+     * @return The content type (mime type) of this <code>DataSource</code> object.
+     */
+    private static String getType(String type) {
+        if (isNullOrEmpty(type)) {
+            type = "application/octet-stream";
+        }
+
+        return type;
+    }
+
+    /**
+     * The InputStream object passed into contructor.
+     *
+     * @return The InputStream object for this <code>DataSource</code> object.
+     */
+    public InputStream getInputStream() {
+        return new ByteArrayInputStream(data);
+    }
+}

Propchange: cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/InputStreamDataSource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/InputStreamDataSource.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/SourceDataSource.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/SourceDataSource.java?view=diff&rev=469258&r1=469257&r2=469258
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/SourceDataSource.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/mail/java/org/apache/cocoon/mail/datasource/SourceDataSource.java Mon Oct 30 12:21:40 2006
@@ -18,10 +18,7 @@
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
-import javax.activation.DataSource;
 
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
 import org.apache.excalibur.source.Source;
 
 /**
@@ -31,19 +28,15 @@
  *
  * @see org.apache.excalibur.source.Source
  * @see javax.activation.DataSource
- * @author <a href="mailto:frank.ridderbusch@gmx.de">Frank Ridderbusch</a>
- * @author <a href="mailto:haul@apache.org">Christian Haul</a>
  * @version $Id$
  */
-public class SourceDataSource extends AbstractLogEnabled
-                              implements DataSource {
+public class SourceDataSource extends AbstractDataSource {
 
     private Source src;
-    private String contentType;
-    private String name;
 
     /**
-     * Creates a new instance of SourceDataSource
+     * Creates a new instance of SourceDataSource.
+     *
      * @param src A <code>org.apache.excalibur.source.Source</code> Object.
      */
     public SourceDataSource(Source src) {
@@ -51,54 +44,70 @@
     }
 
     /**
-     * Creates a new instance of SourceDataSource
+     * Creates a new instance of SourceDataSource.
+     *
      * @param src A <code>org.apache.excalibur.source.Source</code> Object.
      */
     public SourceDataSource(Source src, String type, String name) {
+        super(getName(name, src), getType(type, src));
         this.src = src;
-        this.contentType = type;
-        this.name = name;
-        if (isNullOrEmpty(this.name)) {
-            this.name = null;
-        }
-        if (isNullOrEmpty(this.contentType)) {
-            this.contentType = null;
-        }
     }
 
     /**
-     * Check String for null or empty.
-     * @param str
-     * @return true if str is null, empty string, or equals "null"
+     * Determines the name for this <code>DataSource</code> object.
+     * It is first non empty value from the list:
+     * <ul>
+     * <li>The value of <code>name</code> argument.
+     * <li>The last path component (after the last '/') from the value
+     * returned by the {@link Source#getURI()}.
+     * <li>"attachment".
+     * </ul>
+     *
+     * @return the name for this <code>DataSource</code>
      */
-     private boolean isNullOrEmpty(String str) {
-         return str == null || "".equals(str) || "null".equals(str);
-     }
+    private static String getName(String name, Source src) {
+        if (isNullOrEmpty(name)) {
+            name = src.getURI();
+            name = name.substring(name.lastIndexOf('/') + 1);
+            int idx = name.indexOf('?');
+            if (idx > -1) {
+                name = name.substring(0, idx);
+            }
+
+            if (isNullOrEmpty(name)) {
+                name = "attachment";
+            }
+        }
+
+        return name;
+    }
 
     /**
-     * Returns the result of a call to the <code>Source</code>
-     * objects <code>getMimeType()</code> method. Returns
-     * "application/octet-stream", if <code>getMimeType()</code>
-     * returns <code>null</code>.
+     * Determines the mime type for this <code>DataSource</code> object.
+     * It is first non empty value from the list:
+     * <ul>
+     * <li>The value of <code>type</code> argument.
+     * <li>The value returned by {@link Source#getMimeType()}.
+     * <li>"application/octet-stream".
+     * </ul>
+     *
      * @return The content type (mime type) of this <code>DataSource</code> object.
-     * @see org.apache.excalibur.source.Source#getMimeType()
      */
-    public String getContentType() {
-        if (this.contentType != null) {
-            return this.contentType;
-        }
-
-        String mimeType = src.getMimeType();
-        if (isNullOrEmpty(mimeType)) {
-            mimeType = "application/octet-stream";
+    private static String getType(String type, Source src) {
+        if (isNullOrEmpty(type)) {
+            type = src.getMimeType();
+            if (isNullOrEmpty(type)) {
+                type = "application/octet-stream";
+            }
         }
 
-        return mimeType;
+        return type;
     }
 
     /**
      * Get the <code>InputStream</code> object from the
      * <code>Source</code> object.
+     *
      * @throws java.io.IOException if an I/O error occurs.
      * @return The InputStream object from the <code>Source</code> object.
      * @see org.apache.excalibur.source.Source#getInputStream()
@@ -113,32 +122,5 @@
             }
             throw e;
         }
-    }
-
-    /**
-     * Returns the name for this <code>DataSource</code> object. This is
-     * actually the last path component (after the last '/') from the value
-     * returned by the <code>getURI()</code> method of the <code>Source</code>
-     * object.
-     * @return the name for this <code>DataSource</code>
-     * @see org.apache.excalibur.source.Source#getURI()
-     */
-    public String getName() {
-        if (this.name != null){
-            return this.name;
-        }
-
-        String name = src.getURI();
-        name = name.substring(name.lastIndexOf('/') + 1);
-        return "".equals(name)? "attachment" : name;
-    }
-
-    /**
-     * Unimplemented. Directly throws <code>IOException</code>.
-     * @throws java.io.IOException since unimplemented
-     * @return nothing
-     */
-    public OutputStream getOutputStream() throws IOException {
-        throw new IOException("no data sink available");
     }
 }

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/form.xml
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/form.xml?view=diff&rev=469258&r1=469257&r2=469258
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/form.xml (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/form.xml Mon Oct 30 12:21:40 2006
@@ -127,6 +127,7 @@
         <tr>
           <td>Choose the frontend:</td>
           <td>Send mail using
+            <input type="submit" name="use-flow" value="Flow"/>
             <input type="submit" name="use-action" value="Action"/>
             <input type="submit" name="use-oldaction" value="Deprecated Action"/>
             <input type="submit" name="use-logicsheet" value="Logicsheet"/>

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/mail.js
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/mail.js?view=auto&rev=469258
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/mail.js (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/mail.js Mon Oct 30 12:21:40 2006
@@ -0,0 +1,50 @@
+/*
+* 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.
+*/
+
+/**
+ * Simple flow method to send email according to passed in flow parameters.
+ */
+function mail() {
+
+    var mms = null;
+    try {
+        mms = cocoon.getComponent(Packages.org.apache.cocoon.mail.MailSender.ROLE);
+
+        if (cocoon.parameters.host != "" || cocoon.parameters.user != "") {
+            mms.setSmtpHost(cocoon.parameters.host,
+                            cocoon.parameters.user,
+                            cocoon.parameters.password);
+        }
+
+        mms.setFrom(cocoon.parameters.from);
+        mms.setTo(cocoon.parameters.to);
+        mms.setSubject(cocoon.parameters.subject);
+        mms.setCc(cocoon.parameters.cc);
+        mms.setBcc(cocoon.parameters.bcc);
+        mms.setBody(cocoon.parameters.body, "text/plain; charset=utf-8");
+
+        mms.addAttachment(cocoon.request.get("attachment"));
+        mms.addAttachmentURL("cocoon:///");
+        mms.addAttachmentURL("context://welcome.xml");
+
+        mms.send();
+    } finally {
+        cocoon.releaseComponent(mms);
+    }
+
+    cocoon.sendPage("view/page");
+}

Propchange: cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/mail.js
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/mail.js
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/sitemap.xmap
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/sitemap.xmap?view=diff&rev=469258&r1=469257&r2=469258
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/sitemap.xmap (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/mail/samples/sendmail/sitemap.xmap Mon Oct 30 12:21:40 2006
@@ -73,13 +73,25 @@
     </map:resource>
   </map:resources>
 
+  <map:flow language="javascript">
+    <map:script src="mail.js"/>
+  </map:flow>
+
 <!-- =========================== Pipelines ================================= -->
 
   <map:pipelines>
     <map:pipeline>
 
+      <map:match pattern="view/page">
+        <map:call resource="show-page">
+          <map:parameter name="target" value="done.xml"/>
+          <map:parameter name="remove" value="ignored"/>
+        </map:call>
+      </map:match>
+
       <map:match pattern="*">
         <map:match type="host-matcher" pattern="localhost">
+
           <!--+
               | To avoid creating an open SPAM relay in default
               | deployments, only allow "localhost" as server name.
@@ -87,11 +99,28 @@
               +-->
 
           <map:act type="req-params">
-            <map:parameter name="parameters" value="use-action"/>
-              <!--+
-                  | Use action to send mail
-                  +-->
+            <map:parameter name="parameters" value="use-flow"/>
+            <!--+
+                | Use flow to send mail
+                +-->
+            <map:call function="mail">
+              <map:parameter name="host"     value="{request-param:smtphost}"/>
+              <map:parameter name="user"     value="{request-param:smtpuser}"/>
+              <map:parameter name="password" value="{request-param:smtppassword}"/>
+              <map:parameter name="from"     value="{request-param:from}"/>
+              <map:parameter name="to"       value="{request-param:to}"/>
+              <map:parameter name="subject"  value="{request-param:subject}"/>
+              <map:parameter name="body"     value="{request-param:body}"/>
+              <map:parameter name="cc"       value="{request-param:cc}"/>
+              <map:parameter name="bcc"      value="{request-param:bcc}"/>
+            </map:call>
+          </map:act>
 
+          <map:act type="req-params">
+            <map:parameter name="parameters" value="use-action"/>
+            <!--+
+                | Use action to send mail
+                +-->
             <map:act type="sendmail">
               <!--+
                   | New sendmail action extends the deprecated action with options
@@ -120,10 +149,9 @@
 
           <map:act type="req-params">
             <map:parameter name="parameters" value="use-oldaction"/>
-              <!--+
-                  | Use (deprecated) action to send mail
-                  +-->
-
+            <!--+
+                | Use (deprecated) action to send mail
+                +-->
             <map:act type="old-sendmail">
               <map:parameter name="smtp-host"    value="{request-param:mail.smtphost}"/>
               <map:parameter name="smtp-user"   value="{request-param:smtpuser}"/>
@@ -149,15 +177,17 @@
 
           <map:act type="req-params">
             <map:parameter name="parameters" value="use-logicsheet"/>
-              <!--+
-                  | Use logicsheet from XSP to send mail
-                  +-->
+            <!--+
+                | Use logicsheet from XSP to send mail
+                +-->
             <map:call resource="show-page">
               <map:parameter name="target" value="sendmail_xsp.xml"/>
               <map:parameter name="remove" value="{0}"/>
             </map:call>
           </map:act>
+
         </map:match> <!-- type="host-matcher" pattern="localhost" -->
+
 
         <!-- default page -->
         <map:call resource="show-page">

Modified: cocoon/branches/BRANCH_2_1_X/status.xml
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/status.xml?view=diff&rev=469258&r1=469257&r2=469258
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/status.xml (original)
+++ cocoon/branches/BRANCH_2_1_X/status.xml Mon Oct 30 12:21:40 2006
@@ -184,6 +184,12 @@
   <release version="@version@" date="@date@">
 -->
   <release version="2.1.10" date="TBD">
+    <action dev="VG" type="update">
+      Mail: Improve MailSender interface: added setBody(Object), setBodyURL
+      methods, deprecated setCharset, setBody(String), setBodyFromSrc,
+      setBodyFromSrcMimeType methods. Support byte[], InputStream as body and
+      attachment objects.
+    </action>
     <action dev="VG" type="fix">
       Mail: Log exceptions from mail attachments - JavaMail does not preserve
       cause exception.