You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by Conor MacNeill <co...@m64.com> on 2000/08/07 15:14:16 UTC

Namespace management

Jason,

Good to see the licensing issues have been resolved to everyone's
satisfaction (hopefully). I'm just curious about the package in which you
have chosen to place this code. org.apache.tools.mail is outside the ant
namespace, org.apache.tools.ant. I can see that the mail code is potentially
useful in other non-ant projects. It does raise for me two wider issues,
however. How is the org.apache.tools namespace managed? Can the ant
sub-project create new packages anywhere in the org.apache.tools or even
org.apache namespaces? If the org.apache.tools.mail package is to be used
outside of ant, I wonder how it will be packaged? What jar will it be in?
which project will build it?

It is great to have the mail code and I hope someone contributes an email
task to utilise it (Tim ?). I'm genuinely curious about the namespace
management issues and would be interested in your's and everyone's views.

Conor

> -----Original Message-----
> From: jhunter@locus.apache.org [mailto:jhunter@locus.apache.org]
> Sent: Saturday, 5 August 2000 11:29
> To: jakarta-ant-cvs@apache.org
> Subject: cvs commit: jakarta-ant/src/main/org/apache/tools/mail
> MailMessage.java
>
>
> jhunter     00/08/04 18:28:50
>
>   Modified:    .        build.xml
>   Added:       src/main/org/apache/tools/mail MailMessage.java
>   Removed:     src/main/com/oreilly/servlet MailMessage.java
>   Log:
>   Moved MailMessage from com.oreilly.servlet to org.apache.tools.mail
>   (imitating org.apache.tools.tar).  Also made it pure copyright ASF.
>   For those interested in legalities, my understanding is I'm granting
>   the ASF copyright on this code but have my own copyright on the code
>   as it existed before the grant.  That means I can include my own code
>   in my book without following the Apache license, but I can't use
>   improvements to the ASF code without following the Apache license
>   (as is perfectly appropriate).
>
>   Changed build.xml to no longer build com/**.
>
>   -jh-
>
>   Revision  Changes    Path
>   1.58      +2 -2      jakarta-ant/build.xml
>
>   Index: build.xml
>   ===================================================================
>   RCS file: /home/cvs/jakarta-ant/build.xml,v
>   retrieving revision 1.57
>   retrieving revision 1.58
>   diff -u -r1.57 -r1.58
>   --- build.xml	2000/08/04 14:58:40	1.57
>   +++ build.xml	2000/08/05 01:28:47	1.58
>   @@ -28,7 +28,7 @@
>      <property name="ant.dist.dir" value="../dist/ant"/>
>
>      <property name="classpath" value=""/>
>   -  <property name="packages"
> value="org.apache.tools.*,com.oreilly.servlet.*"/>
>   +  <property name="packages" value="org.apache.tools.*"/>
>      <property name="manifest" value="src/etc/manifest"/>
>
>      <property name="build.compiler" value="classic"/>
>   @@ -108,7 +108,7 @@
>        <mkdir dir="${lib.dir}"/>
>        <jar jarfile="${lib.dir}/${name}.jar"
>             basedir="${build.classes}"
>   -         includes="org/**,com/**"
>   +         includes="org/**"
>             manifest="${manifest}"
>        />
>      </target>
>
>
>
>   1.1
> jakarta-ant/src/main/org/apache/tools/mail/MailMessage.java
>
>   Index: MailMessage.java
>   ===================================================================
>   /*
>    * The Apache Software License, Version 1.1
>    *
>    * Copyright (c) 1999 The Apache Software Foundation.  All rights
>    * reserved.
>    *
>    * Redistribution and use in source and binary forms, with or without
>    * modification, are permitted provided that the following conditions
>    * are met:
>    *
>    * 1. Redistributions of source code must retain the above copyright
>    *    notice, this list of conditions and the following disclaimer.
>    *
>    * 2. Redistributions in binary form must reproduce the above copyright
>    *    notice, this list of conditions and the following disclaimer in
>    *    the documentation and/or other materials provided with the
>    *    distribution.
>    *
>    * 3. The end-user documentation included with the redistribution, if
>    *    any, must include the following acknowlegement:
>    *       "This product includes software developed by the
>    *        Apache Software Foundation (http://www.apache.org/)."
>    *    Alternately, this acknowlegement may appear in the
> software itself,
>    *    if and wherever such third-party acknowlegements normally appear.
>    *
>    * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
>    *    Foundation" must not be used to endorse or promote
> products derived
>    *    from this software without prior written permission. For written
>    *    permission, please contact apache@apache.org.
>    *
>    * 5. Products derived from this software may not be called "Apache"
>    *    nor may "Apache" appear in their names without prior written
>    *    permission of the Apache Group.
>    *
>    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
>    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
>    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
>    * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
>    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
>    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
>    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
>    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
>    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
>    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>    * SUCH DAMAGE.
>    * ====================================================================
>    *
>    */
>
>   /*
>    * The original version of this class was donated by Jason Hunter,
>    * who wrote the class as part of the com.oreilly.servlet
>    * package for his book "Java Servlet Programming" (O'Reilly).
>    * See http://www.servlets.com.
>    *
>    */
>
>   package org.apache.tools.mail;
>
>   import java.io.*;
>   import java.net.*;
>   import java.util.*;
>
>   /**
>    * A class to help send SMTP email.
>    * This class is an improvement on the sun.net.smtp.SmtpClient class
>    * found in the JDK.  This version has extra functionality, and
> can be used
>    * with JVMs that did not extend from the JDK.  It's not as robust as
>    * the JavaMail Standard Extension classes, but it's easier to use and
>    * easier to install, and has an Open Source license.
>    * <p>
>    * It can be used like this:
>    * <blockquote><pre>
>    * String mailhost = "localhost";  // or another mail host
>    * String from = "Mail Message Servlet &lt;MailMessage@server.com&gt;";
>    * String to = "to@you.com";
>    * String cc1 = "cc1@you.com";
>    * String cc2 = "cc2@you.com";
>    * String bcc = "bcc@you.com";
>    * &nbsp;
>    * MailMessage msg = new MailMessage(mailhost);
>    * msg.from(from);
>    * msg.to(to);
>    * msg.cc(cc1);
>    * msg.cc(cc2);
>    * msg.bcc(bcc);
>    * msg.setSubject("Test subject");
>    * PrintStream out = msg.getPrintStream();
>    * &nbsp;
>    * Enumeration enum = req.getParameterNames();
>    * while (enum.hasMoreElements()) {
>    *   String name = (String)enum.nextElement();
>    *   String value = req.getParameter(name);
>    *   out.println(name + " = " + value);
>    * }
>    * &nbsp;
>    * msg.sendAndClose();
>    * </pre></blockquote>
>    * <p>
>    * Be sure to set the from address, then set the recepient
>    * addresses, then set the subject and other headers, then get the
>    * PrintStream, then write the message, and finally send and close.
>    * The class does minimal error checking internally; it counts
> on the mail
>    * host to complain if there's any malformatted input or out of order
>    * execution.
>    * <p>
>    * An attachment mechanism based on RFC 1521 could be
> implemented on top of
>    * this class.  In the meanwhile, JavaMail is the best solution
> for sending
>    * email with attachments.
>    * <p>
>    * Still to do:
>    * <ul>
>    * <li>Figure out how to close the connection in case of error
>    * </ul>
>    *
>    * @author Jason Hunter
>    * @version 1.1, 2000/03/19, added angle brackets to address,
> helps some servers
>    * version 1.0, 1999/12/29
>    */
>   public class MailMessage {
>
>     String host;
>     String from;
>     Vector to, cc;
>     Hashtable headers;
>     MailPrintStream out;
>     BufferedReader in;
>     Socket socket;
>
>     /**
>      * Constructs a new MailMessage to send an email.
>      * Use localhost as the mail server.
>      *
>      * @exception IOException if there's any problem contacting
> the mail server
>      */
>     public MailMessage() throws IOException {
>       this("localhost");
>     }
>
>     /**
>      * Constructs a new MailMessage to send an email.
>      * Use the given host as the mail server.
>      *
>      * @param host the mail server to use
>      * @exception IOException if there's any problem contacting
> the mail server
>      */
>     public MailMessage(String host) throws IOException {
>       this.host = host;
>       to = new Vector();
>       cc = new Vector();
>       headers = new Hashtable();
>       setHeader("X-Mailer", "com.oreilly.servlet.MailMessage
> (www.servlets.com)");
>       connect();
>       sendHelo();
>     }
>
>     /**
>      * Sets the from address.  Also sets the "From" header.  This
> method should
>      * be called only once.
>      *
>      * @exception IOException if there's any problem reported by
> the mail server
>      */
>     public void from(String from) throws IOException {
>       sendFrom(from);
>       this.from = from;
>     }
>
>     /**
>      * Sets the to address.  Also sets the "To" header.  This
> method may be
>      * called multiple times.
>      *
>      * @exception IOException if there's any problem reported by
> the mail server
>      */
>     public void to(String to) throws IOException {
>       sendRcpt(to);
>       this.to.addElement(to);
>     }
>
>     /**
>      * Sets the cc address.  Also sets the "Cc" header.  This
> method may be
>      * called multiple times.
>      *
>      * @exception IOException if there's any problem reported by
> the mail server
>      */
>     public void cc(String cc) throws IOException {
>       sendRcpt(cc);
>       this.cc.addElement(cc);
>     }
>
>     /**
>      * Sets the bcc address.  Does NOT set any header since it's
> a *blind* copy.
>      * This method may be called multiple times.
>      *
>      * @exception IOException if there's any problem reported by
> the mail server
>      */
>     public void bcc(String bcc) throws IOException {
>       sendRcpt(bcc);
>       // No need to keep track of Bcc'd addresses
>     }
>
>     /**
>      * Sets the subject of the mail message.  Actually sets the "Subject"
>      * header.
>      */
>     public void setSubject(String subj) {
>       headers.put("Subject", subj);
>     }
>
>     /**
>      * Sets the named header to the given value.  RFC 822
> provides the rules for
>      * what text may constitute a header name and value.
>      */
>     public void setHeader(String name, String value) {
>       // Blindly trust the user doesn't set any invalid headers
>       headers.put(name, value);
>     }
>
>     /**
>      * Returns a PrintStream that can be used to write the body
> of the message.
>      * A stream is used since email bodies are byte-oriented.  A
> writer could
>      * be wrapped on top if necessary for internationalization.
>      *
>      * @exception IOException if there's any problem reported by
> the mail server
>      */
>     public PrintStream getPrintStream() throws IOException {
>       setFromHeader();
>       setToHeader();
>       setCcHeader();
>       sendData();
>       flushHeaders();
>       return out;
>     }
>
>     void setFromHeader() {
>       setHeader("From", from);
>     }
>
>     void setToHeader() {
>       setHeader("To", vectorToList(to));
>     }
>
>     void setCcHeader() {
>       setHeader("Cc", vectorToList(cc));
>     }
>
>     String vectorToList(Vector v) {
>       StringBuffer buf = new StringBuffer();
>       Enumeration e = v.elements();
>       while (e.hasMoreElements()) {
>         buf.append(e.nextElement());
>         if (e.hasMoreElements()) {
>           buf.append(", ");
>         }
>       }
>       return buf.toString();
>     }
>
>     void flushHeaders() throws IOException {
>       // XXX Should I care about order here?
>       Enumeration e = headers.keys();
>       while (e.hasMoreElements()) {
>         String name = (String) e.nextElement();
>         String value = (String) headers.get(name);
>         out.println(name + ": " + value);
>       }
>       out.println();
>       out.flush();
>     }
>
>     /**
>      * Sends the message and closes the connection to the server.
>      * The MailMessage object cannot be reused.
>      *
>      * @exception IOException if there's any problem reported by
> the mail server
>      */
>     public void sendAndClose() throws IOException {
>       sendDot();
>       disconnect();
>     }
>
>     // Make a limited attempt to extract a sanitized email address
>     // Prefer text in <brackets>, ignore anything in (parentheses)
>     static String sanitizeAddress(String s) {
>       int paramDepth = 0;
>       int start = 0;
>       int end = 0;
>       int len = s.length();
>
>       for (int i = 0; i < len; i++) {
>         char c = s.charAt(i);
>         if (c == '(') {
>           paramDepth++;
>           if (start == 0) {
>             end = i;  // support "address (name)"
>           }
>         }
>         else if (c == ')') {
>           paramDepth--;
>           if (end == 0) {
>             start = i + 1;  // support "(name) address"
>           }
>         }
>         else if (paramDepth == 0 && c == '<') {
>           start = i + 1;
>         }
>         else if (paramDepth == 0 && c == '>') {
>           end = i;
>         }
>       }
>
>       if (end == 0) {
>         end = len;
>       }
>
>       return s.substring(start, end);
>     }
>
>     // * * * * * Raw protocol methods below here * * * * *
>
>     void connect() throws IOException {
>       socket = new Socket(host, 25);
>       out = new MailPrintStream(
>             new BufferedOutputStream(
>             socket.getOutputStream()));
>       in = new BufferedReader(new
> InputStreamReader(socket.getInputStream()));
>       getReady();
>     }
>
>     void getReady() throws IOException {
>       String response = in.readLine();
>       int[] ok = { 220 };
>       if (!isResponseOK(response, ok)) {
>         throw new IOException(
>           "Didn't get introduction from server: " + response);
>       }
>     }
>
>     void sendHelo() throws IOException {
>       String local = InetAddress.getLocalHost().getHostName();
>       int[] ok = { 250 };
>       send("HELO " + local, ok);
>     }
>
>     void sendFrom(String from) throws IOException {
>       int[] ok = { 250 };
>       send("MAIL FROM: " + "<" + sanitizeAddress(from) + ">", ok);
>     }
>
>     void sendRcpt(String rcpt) throws IOException {
>       int[] ok = { 250, 251 };
>       send("RCPT TO: " + "<" + sanitizeAddress(rcpt) + ">", ok);
>     }
>
>     void sendData() throws IOException {
>       int[] ok = { 354 };
>       send("DATA", ok);
>     }
>
>     void sendDot() throws IOException {
>       int[] ok = { 250 };
>       send("\r\n.", ok);  // make sure dot is on new line
>     }
>
>     void sendQuit() throws IOException {
>       int[] ok = { 221 };
>       send("QUIT", ok);
>     }
>
>     void send(String msg, int[] ok) throws IOException {
>       out.rawPrint(msg + "\r\n");  // raw supports <CRLF>.<CRLF>
>       //System.out.println("S: " + msg);
>       String response = in.readLine();
>       //System.out.println("R: " + response);
>       if (!isResponseOK(response, ok)) {
>         throw new IOException(
>           "Unexpected reply to command: " + msg + ": " + response);
>       }
>     }
>
>     boolean isResponseOK(String response, int[] ok) {
>       // Check that the response is one of the valid codes
>       for (int i = 0; i < ok.length; i++) {
>         if (response.startsWith("" + ok[i])) {
>           return true;
>         }
>       }
>       return false;
>     }
>
>     void disconnect() throws IOException {
>       if (out != null) out.close();
>       if (in != null) in.close();
>       if (socket != null) socket.close();
>     }
>   }
>
>   // This PrintStream subclass makes sure that <CRLF>. becomes <CRLF>..
>   // per RFC 821.  It also ensures that new lines are always \r\n.
>   //
>   class MailPrintStream extends PrintStream {
>
>     int lastChar;
>
>     public MailPrintStream(OutputStream out) {
>       super(out, true);  // deprecated, but email is byte-oriented
>     }
>
>     // Mac does \n\r, but that's tough to distinguish from
> Windows \r\n\r\n.
>     // Don't tackle that problem right now.
>     public void write(int b) {
>       if (b == '\n' && lastChar != '\r') {
>         rawWrite('\r');  // ensure always \r\n
>         rawWrite(b);
>       }
>       else if (b == '.' && lastChar == '\n') {
>         rawWrite('.');  // add extra dot
>         rawWrite(b);
>       }
>       else {
>         rawWrite(b);
>       }
>       lastChar = b;
>     }
>
>     public void write(byte buf[], int off, int len) {
>       for (int i = 0; i < len; i++) {
>         write(buf[off + i]);
>       }
>     }
>
>     void rawWrite(int b) {
>       super.write(b);
>     }
>
>     void rawPrint(String s) {
>       int len = s.length();
>       for (int i = 0; i < len; i++) {
>         rawWrite(s.charAt(i));
>       }
>     }
>   }
>
>
>
>


Re: Namespace management

Posted by Peter Donald <do...@mad.scientist.com>.
At 11:14  7/8/00 +1000, you wrote:
>It is great to have the mail code and I hope someone contributes an email
>task to utilise it (Tim ?). I'm genuinely curious about the namespace
>management issues and would be interested in your's and everyone's views.

FWIW I would like to see it in org.apache.util.net or something similar. I
heard that there was going to be a project setup that dealt specifically
with common utility code between the projects. In which case placing the
mail in this package seems to indicate that it will go there in the future
... which is where it belongs IMHO.

Thats my 2c :P


Cheers,

Pete

*------------------------------------------------------*
| "Nearly all men can stand adversity, but if you want |
| to test a man's character, give him power."          |
|       -Abraham Lincoln                               |
*------------------------------------------------------*