You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by rm...@apache.org on 2014/08/26 20:17:09 UTC

svn commit: r1620683 [14/17] - in /geronimo/specs/trunk: ./ geronimo-javamail_1.5_spec/ geronimo-javamail_1.5_spec/src/ geronimo-javamail_1.5_spec/src/main/ geronimo-javamail_1.5_spec/src/main/java/ geronimo-javamail_1.5_spec/src/main/java/javax/ geron...

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/RFC2231Encoder.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/RFC2231Encoder.java?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/RFC2231Encoder.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/RFC2231Encoder.java Tue Aug 26 18:17:06 2014
@@ -0,0 +1,261 @@
+/*
+ * 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.geronimo.mail.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+import javax.mail.internet.MimeUtility;
+
+/**
+ * Encoder for RFC2231 encoded parameters
+ *
+ * RFC2231 string are encoded as
+ *
+ *    charset'language'encoded-text
+ *
+ * and
+ *
+ *    encoded-text = *(char / hexchar)
+ *
+ * where
+ *
+ *    char is any ASCII character in the range 33-126, EXCEPT
+ *    the characters "%" and " ".
+ *
+ *    hexchar is an ASCII "%" followed by two upper case
+ *    hexadecimal digits.
+ */
+
+public class RFC2231Encoder implements Encoder
+{
+    protected final byte[] encodingTable =
+        {
+            (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
+            (byte)'8', (byte)'9', (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F'
+        };
+
+    protected String DEFAULT_SPECIALS = " *'%";
+    protected String specials = DEFAULT_SPECIALS;
+
+    /*
+     * set up the decoding table.
+     */
+    protected final byte[] decodingTable = new byte[128];
+
+    protected void initialiseDecodingTable()
+    {
+        for (int i = 0; i < encodingTable.length; i++)
+        {
+            decodingTable[encodingTable[i]] = (byte)i;
+        }
+    }
+
+    public RFC2231Encoder()
+    {
+        this(null);
+    }
+
+    public RFC2231Encoder(final String specials)
+    {
+        if (specials != null) {
+            this.specials = DEFAULT_SPECIALS + specials;
+        }
+        initialiseDecodingTable();
+    }
+
+
+    /**
+     * encode the input data producing an RFC2231 output stream.
+     *
+     * @return the number of bytes produced.
+     */
+    public int encode(final byte[] data, final int off, final int length, final OutputStream out) throws IOException {
+
+        int bytesWritten = 0;
+        for (int i = off; i < (off + length); i++)
+        {
+            final int ch = data[i] & 0xff;
+            // character tha must be encoded?  Prefix with a '%' and encode in hex.
+            if (ch <= 32 || ch >= 127 || specials.indexOf(ch) != -1) {
+                out.write((byte)'%');
+                out.write(encodingTable[ch >> 4]);
+                out.write(encodingTable[ch & 0xf]);
+                bytesWritten += 3;
+            }
+            else {
+                // add unchanged.
+                out.write((byte)ch);
+                bytesWritten++;
+            }
+        }
+
+        return bytesWritten;
+    }
+
+
+    /**
+     * decode the RFC2231 encoded byte data writing it to the given output stream
+     *
+     * @return the number of bytes produced.
+     */
+    public int decode(final byte[] data, final int off, final int length, final OutputStream out) throws IOException {
+        int        outLen = 0;
+        final int        end = off + length;
+
+        int i = off;
+        while (i < end)
+        {
+            final byte v = data[i++];
+            // a percent is a hex character marker, need to decode a hex value.
+            if (v == '%') {
+                final byte b1 = decodingTable[data[i++]];
+                final byte b2 = decodingTable[data[i++]];
+                out.write((b1 << 4) | b2);
+            }
+            else {
+                // copied over unchanged.
+                out.write(v);
+            }
+            // always just one byte added
+            outLen++;
+        }
+
+        return outLen;
+    }
+
+    /**
+     * decode the RFC2231 encoded String data writing it to the given output stream.
+     *
+     * @return the number of bytes produced.
+     */
+    public int decode(final String data, final OutputStream out) throws IOException
+    {
+        int        length = 0;
+        final int        end = data.length();
+
+        int i = 0;
+        while (i < end)
+        {
+            final char v = data.charAt(i++);
+            if (v == '%') {
+                final byte b1 = decodingTable[data.charAt(i++)];
+                final byte b2 = decodingTable[data.charAt(i++)];
+
+                out.write((b1 << 4) | b2);
+            }
+            else {
+                out.write((byte)v);
+            }
+            length++;
+        }
+
+        return length;
+    }
+
+
+    /**
+     * Encode a string as an RFC2231 encoded parameter, using the
+     * given character set and language.
+     *
+     * @param charset  The source character set (the MIME version).
+     * @param language The encoding language.
+     * @param data     The data to encode.
+     *
+     * @return The encoded string.
+     */
+    public String encode(final String charset, final String language, final String data) throws IOException {
+
+        byte[] bytes = null;
+        try {
+            // the charset we're adding is the MIME-defined name.  We need the java version
+            // in order to extract the bytes.
+            bytes = data.getBytes(MimeUtility.javaCharset(charset));
+        } catch (final UnsupportedEncodingException e) {
+            // we have a translation problem here.
+            return null;
+        }
+
+        final StringBuffer result = new StringBuffer();
+
+        // append the character set, if we have it.
+        if (charset != null) {
+            result.append(charset);
+        }
+        // the field marker is required.
+        result.append("'");
+
+        // and the same for the language.
+        if (language != null) {
+            result.append(language);
+        }
+        // the field marker is required.
+        result.append("'");
+
+        // wrap an output stream around our buffer for the decoding
+        final OutputStream out = new StringBufferOutputStream(result);
+
+        // encode the data stream
+        encode(bytes, 0, bytes.length, out);
+
+        // finis!
+        return result.toString();
+    }
+
+
+    /**
+     * Decode an RFC2231 encoded string.
+     *
+     * @param data   The data to decode.
+     *
+     * @return The decoded string.
+     * @exception IOException
+     * @exception UnsupportedEncodingException
+     */
+    public String decode(final String data) throws IOException, UnsupportedEncodingException {
+        // get the end of the language field
+        final int charsetEnd = data.indexOf('\'');
+        // uh oh, might not be there
+        if (charsetEnd == -1) {
+            throw new IOException("Missing charset in RFC2231 encoded value");
+        }
+
+        final String charset = data.substring(0, charsetEnd);
+
+        // now pull out the language the same way
+        final int languageEnd = data.indexOf('\'', charsetEnd + 1);
+        if (languageEnd == -1) {
+            throw new IOException("Missing language in RFC2231 encoded value");
+        }
+
+        //final String language = data.substring(charsetEnd + 1, languageEnd);
+
+        final ByteArrayOutputStream out = new ByteArrayOutputStream(data.length());
+
+        // decode the data
+        decode(data.substring(languageEnd + 1), out);
+
+        final byte[] bytes = out.toByteArray();
+        // build a new string from this using the java version of the encoded charset.
+        return new String(bytes, 0, bytes.length, MimeUtility.javaCharset(charset));
+    }
+}

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/SessionUtil.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/SessionUtil.java?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/SessionUtil.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/SessionUtil.java Tue Aug 26 18:17:06 2014
@@ -0,0 +1,216 @@
+/*
+ * 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.geronimo.mail.util;
+
+import javax.mail.Session;
+
+/**
+ * Simple utility class for managing session properties.
+ */
+public class SessionUtil {
+
+    /**
+     * Get a property associated with this mail session.  Returns
+     * the provided default if it doesn't exist.
+     *
+     * @param session The attached session.
+     * @param name    The name of the property.
+     *
+     * @return The property value (returns null if the property has not been set).
+     */
+    static public String getProperty(final Session session, final String name) {
+        // occasionally, we get called with a null session if an object is not attached to
+        // a session.  In that case, treat this like an unknown parameter.
+        if (session == null) {
+            return null;
+        }
+
+        return session.getProperty(name);
+    }
+
+
+    /**
+     * Get a property associated with this mail session.  Returns
+     * the provided default if it doesn't exist.
+     *
+     * @param session The attached session.
+     * @param name    The name of the property.
+     * @param defaultValue
+     *                The default value to return if the property doesn't exist.
+     *
+     * @return The property value (returns defaultValue if the property has not been set).
+     */
+    static public String getProperty(final Session session, final String name, final String defaultValue) {
+        final String result = getProperty(session, name);
+        if (result == null) {
+            return defaultValue;
+        }
+        return result;
+    }
+
+
+    /**
+     * Process a session property as a boolean value, returning
+     * either true or false.
+     *
+     * @param session The source session.
+     * @param name
+     *
+     * @return True if the property value is "true".  Returns false for any
+     *         other value (including null).
+     */
+    static public boolean isPropertyTrue(final Session session, final String name) {
+        final String property = getProperty(session, name);
+        if (property != null) {
+            return property.equals("true");
+        }
+        return false;
+    }
+
+    /**
+     * Process a session property as a boolean value, returning
+     * either true or false.
+     *
+     * @param session The source session.
+     * @param name
+     *
+     * @return True if the property value is "false".  Returns false for
+     *         other value (including null).
+     */
+    static public boolean isPropertyFalse(final Session session, final String name) {
+        final String property = getProperty(session, name);
+        if (property != null) {
+            return property.equals("false");
+        }
+        return false;
+    }
+
+    /**
+     * Get a property associated with this mail session as an integer value.  Returns
+     * the default value if the property doesn't exist or it doesn't have a valid int value.
+     *
+     * @param session The source session.
+     * @param name    The name of the property.
+     * @param defaultValue
+     *                The default value to return if the property doesn't exist.
+     *
+     * @return The property value converted to an int.
+     */
+    static public int getIntProperty(final Session session, final String name, final int defaultValue) {
+        final String result = getProperty(session, name);
+        if (result != null) {
+            try {
+                // convert into an int value.
+                return Integer.parseInt(result);
+            } catch (final NumberFormatException e) {
+            }
+        }
+        // return default value if it doesn't exist is isn't convertable.
+        return defaultValue;
+    }
+
+
+    /**
+     * Get a property associated with this mail session as a boolean value.  Returns
+     * the default value if the property doesn't exist or it doesn't have a valid boolean value.
+     *
+     * @param session The source session.
+     * @param name    The name of the property.
+     * @param defaultValue
+     *                The default value to return if the property doesn't exist.
+     *
+     * @return The property value converted to a boolean.
+     */
+    static public boolean getBooleanProperty(final Session session, final String name, final boolean defaultValue) {
+        final String result = getProperty(session, name);
+        if (result != null) {
+            return Boolean.valueOf(result).booleanValue();
+        }
+        // return default value if it doesn't exist is isn't convertable.
+        return defaultValue;
+    }
+
+
+    /**
+     * Get a system property associated with this mail session as a boolean value.  Returns
+     * the default value if the property doesn't exist or it doesn't have a valid boolean value.
+     *
+     * @param name    The name of the property.
+     * @param defaultValue
+     *                The default value to return if the property doesn't exist.
+     *
+     * @return The property value converted to a boolean.
+     */
+    static public boolean getBooleanProperty(final String name, final boolean defaultValue) {
+        try {
+            final String result = System.getProperty(name);
+            if (result != null) {
+                return Boolean.valueOf(result).booleanValue();
+            }
+        } catch (final SecurityException e) {
+            // we can't access the property, so for all intents, it doesn't exist.
+        }
+        // return default value if it doesn't exist is isn't convertable.
+        return defaultValue;
+    }
+
+
+    /**
+     * Get a system property associated with this mail session as a boolean value.  Returns
+     * the default value if the property doesn't exist.
+     *
+     * @param name    The name of the property.
+     * @param defaultValue
+     *                The default value to return if the property doesn't exist.
+     *
+     * @return The property value
+     */
+    static public String getProperty(final String name, final String defaultValue) {
+        try {
+            final String result = System.getProperty(name);
+            if (result != null) {
+                return result;
+            }
+        } catch (final SecurityException e) {
+            // we can't access the property, so for all intents, it doesn't exist.
+        }
+        // return default value if it doesn't exist is isn't convertable.
+        return defaultValue;
+    }
+
+
+    /**
+     * Get a system property associated with this mail session as a boolean value.  Returns
+     * the default value if the property doesn't exist.
+     *
+     * @param name    The name of the property.
+     *
+     * @return The property value
+     */
+    static public String getProperty(final String name) {
+        try {
+            return System.getProperty(name);
+        } catch (final SecurityException e) {
+            // we can't access the property, so for all intents, it doesn't exist.
+        }
+        // return null if we got an exception.
+        return null;
+    }
+}

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/StringBufferOutputStream.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/StringBufferOutputStream.java?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/StringBufferOutputStream.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/StringBufferOutputStream.java Tue Aug 26 18:17:06 2014
@@ -0,0 +1,56 @@
+/*
+ * 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.geronimo.mail.util;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * An implementation of an OutputStream that writes the data directly
+ * out to a StringBuffer object.  Useful for applications where an
+ * intermediate ByteArrayOutputStream is required to append generated
+ * characters to a StringBuffer;
+ */
+public class StringBufferOutputStream extends OutputStream {
+
+    // the target buffer
+    protected StringBuffer buffer;
+
+    /**
+     * Create an output stream that writes to the target StringBuffer
+     *
+     * @param out    The wrapped output stream.
+     */
+    public StringBufferOutputStream(final StringBuffer out) {
+        buffer = out;
+    }
+
+
+    // in order for this to work, we only need override the single character form, as the others
+    // funnel through this one by default.
+    @Override
+    public void write(final int ch) throws IOException {
+        // just append the character
+        buffer.append((char)ch);
+    }
+}
+
+
+

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/UUDecoderStream.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/UUDecoderStream.java?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/UUDecoderStream.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/UUDecoderStream.java Tue Aug 26 18:17:06 2014
@@ -0,0 +1,281 @@
+/*
+ * 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.geronimo.mail.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * An implementation of a FilterOutputStream that decodes the
+ * stream data in UU encoding format.  This version does the
+ * decoding "on the fly" rather than decoding a single block of
+ * data.  Since this version is intended for use by the MimeUtilty class,
+ * it also handles line breaks in the encoded data.
+ */
+public class UUDecoderStream extends FilterInputStream {
+    // maximum number of chars that can appear in a single line
+    protected static final int MAX_CHARS_PER_LINE = 45;
+
+    // our decoder for processing the data
+    protected UUEncoder decoder = new UUEncoder();
+
+    // a buffer for one decoding unit's worth of data (45 bytes).
+    protected byte[] decodedChars;
+    // count of characters in the buffer
+    protected int decodedCount = 0;
+    // index of the next decoded character
+    protected int decodedIndex = 0;
+
+    // indicates whether we've already processed the "begin" prefix.
+    protected boolean beginRead = false;
+
+
+    public UUDecoderStream(final InputStream in) {
+        super(in);
+    }
+
+
+    /**
+     * Test for the existance of decoded characters in our buffer
+     * of decoded data.
+     *
+     * @return True if we currently have buffered characters.
+     */
+    private boolean dataAvailable() {
+        return decodedCount != 0;
+    }
+
+    /**
+     * Get the next buffered decoded character.
+     *
+     * @return The next decoded character in the buffer.
+     */
+    private byte getBufferedChar() {
+        decodedCount--;
+        return decodedChars[decodedIndex++];
+    }
+
+    /**
+     * Decode a requested number of bytes of data into a buffer.
+     *
+     * @return true if we were able to obtain more data, false otherwise.
+     */
+    private boolean decodeStreamData() throws IOException {
+        decodedIndex = 0;
+
+        // fill up a data buffer with input data
+        return fillEncodedBuffer() != -1;
+    }
+
+
+    /**
+     * Retrieve a single byte from the decoded characters buffer.
+     *
+     * @return The decoded character or -1 if there was an EOF condition.
+     */
+    private int getByte() throws IOException {
+        if (!dataAvailable()) {
+            if (!decodeStreamData()) {
+                return -1;
+            }
+        }
+        decodedCount--;
+        return decodedChars[decodedIndex++];
+    }
+
+    private int getBytes(final byte[] data, int offset, int length) throws IOException {
+
+        int readCharacters = 0;
+        while (length > 0) {
+            // need data?  Try to get some
+            if (!dataAvailable()) {
+                // if we can't get this, return a count of how much we did get (which may be -1).
+                if (!decodeStreamData()) {
+                    return readCharacters > 0 ? readCharacters : -1;
+                }
+            }
+
+            // now copy some of the data from the decoded buffer to the target buffer
+            final int copyCount = Math.min(decodedCount, length);
+            System.arraycopy(decodedChars, decodedIndex, data, offset, copyCount);
+            decodedIndex += copyCount;
+            decodedCount -= copyCount;
+            offset += copyCount;
+            length -= copyCount;
+            readCharacters += copyCount;
+        }
+        return readCharacters;
+    }
+
+    /**
+     * Verify that the first line of the buffer is a valid begin
+     * marker.
+     *
+     * @exception IOException
+     */
+    private void checkBegin() throws IOException {
+        // we only do this the first time we're requested to read from the stream.
+        if (beginRead) {
+            return;
+        }
+
+        // we might have to skip over lines to reach the marker.  If we hit the EOF without finding
+        // the begin, that's an error.
+        while (true) {
+            final String line = readLine();
+            if (line == null) {
+                throw new IOException("Missing UUEncode begin command");
+            }
+
+            // is this our begin?
+            if (line.regionMatches(true, 0, "begin ", 0, 6)) {
+                // This is the droid we're looking for.....
+                beginRead = true;
+                return;
+            }
+        }
+    }
+
+
+    /**
+     * Read a line of data.  Returns null if there is an EOF.
+     *
+     * @return The next line read from the stream.  Returns null if we
+     *         hit the end of the stream.
+     * @exception IOException
+     */
+    protected String readLine() throws IOException {
+        decodedIndex = 0;
+        // get an accumulator for the data
+        final StringBuffer buffer = new StringBuffer();
+
+        // now process a character at a time.
+        int ch = in.read();
+        while (ch != -1) {
+            // a naked new line completes the line.
+            if (ch == '\n') {
+                break;
+            }
+            // a carriage return by itself is ignored...we're going to assume that this is followed
+            // by a new line because we really don't have the capability of pushing this back .
+            else if (ch == '\r') {
+                ;
+            }
+            else {
+                // add this to our buffer
+                buffer.append((char)ch);
+            }
+            ch = in.read();
+        }
+
+        // if we didn't get any data at all, return nothing
+        if (ch == -1 && buffer.length() == 0) {
+            return null;
+        }
+        // convert this into a string.
+        return buffer.toString();
+    }
+
+
+    /**
+     * Fill our buffer of input characters for decoding from the
+     * stream.  This will attempt read a full buffer, but will
+     * terminate on an EOF or read error.  This will filter out
+     * non-Base64 encoding chars and will only return a valid
+     * multiple of 4 number of bytes.
+     *
+     * @return The count of characters read.
+     */
+    private int fillEncodedBuffer() throws IOException
+    {
+        checkBegin();
+        // reset the buffer position
+        decodedIndex = 0;
+
+        while (true) {
+
+            // we read these as character lines.  We need to be looking for the "end" marker for the
+            // end of the data.
+            final String line = readLine();
+
+            // this should NOT be happening....
+            if (line == null) {
+                throw new IOException("Missing end in UUEncoded data");
+            }
+
+            // Is this the end marker?  EOF baby, EOF!
+            if (line.equalsIgnoreCase("end")) {
+                // this indicates we got nuttin' more to do.
+                return -1;
+            }
+
+            final ByteArrayOutputStream out = new ByteArrayOutputStream(MAX_CHARS_PER_LINE);
+
+            byte [] lineBytes;
+            try {
+                lineBytes = line.getBytes("US-ASCII");
+            } catch (final UnsupportedEncodingException e) {
+                throw new IOException("Invalid UUEncoding");
+            }
+
+            // decode this line
+            decodedCount = decoder.decode(lineBytes, 0, lineBytes.length, out);
+
+            // not just a zero-length line?
+            if (decodedCount != 0) {
+                // get the resulting byte array
+                decodedChars = out.toByteArray();
+                return decodedCount;
+            }
+        }
+    }
+
+
+    // in order to function as a filter, these streams need to override the different
+    // read() signature.
+
+    @Override
+    public int read() throws IOException
+    {
+        return getByte();
+    }
+
+
+    @Override
+    public int read(final byte [] buffer, final int offset, final int length) throws IOException {
+        return getBytes(buffer, offset, length);
+    }
+
+
+    @Override
+    public boolean markSupported() {
+        return false;
+    }
+
+
+    @Override
+    public int available() throws IOException {
+        return ((in.available() / 4) * 3) + decodedCount;
+    }
+}
+

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/UUEncode.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/UUEncode.java?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/UUEncode.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/UUEncode.java Tue Aug 26 18:17:06 2014
@@ -0,0 +1,149 @@
+/*
+ * 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.geronimo.mail.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class UUEncode {
+    private static final Encoder encoder = new UUEncoder();
+
+    /**
+     * encode the input data producing a UUEncoded byte array.
+     *
+     * @return a byte array containing the UUEncoded data.
+     */
+    public static byte[] encode(
+        final byte[]    data)
+    {
+        return encode(data, 0, data.length);
+    }
+
+    /**
+     * encode the input data producing a UUEncoded byte array.
+     *
+     * @return a byte array containing the UUEncoded data.
+     */
+    public static byte[] encode(
+        final byte[]    data,
+        final int       off,
+        final int       length)
+    {
+        final ByteArrayOutputStream    bOut = new ByteArrayOutputStream();
+
+        try
+        {
+            encoder.encode(data, off, length, bOut);
+        }
+        catch (final IOException e)
+        {
+            throw new RuntimeException("exception encoding UUEncoded string: " + e);
+        }
+
+        return bOut.toByteArray();
+    }
+
+    /**
+     * UUEncode the byte data writing it to the given output stream.
+     *
+     * @return the number of bytes produced.
+     */
+    public static int encode(
+        final byte[]         data,
+        final OutputStream   out)
+        throws IOException
+    {
+        return encoder.encode(data, 0, data.length, out);
+    }
+
+    /**
+     * UUEncode the byte data writing it to the given output stream.
+     *
+     * @return the number of bytes produced.
+     */
+    public static int encode(
+        final byte[]         data,
+        final int            off,
+        final int            length,
+        final OutputStream   out)
+        throws IOException
+    {
+        return encoder.encode(data, 0, data.length, out);
+    }
+
+    /**
+     * decode the UUEncoded input data. It is assumed the input data is valid.
+     *
+     * @return a byte array representing the decoded data.
+     */
+    public static byte[] decode(
+        final byte[]    data)
+    {
+        final ByteArrayOutputStream    bOut = new ByteArrayOutputStream();
+
+        try
+        {
+            encoder.decode(data, 0, data.length, bOut);
+        }
+        catch (final IOException e)
+        {
+            throw new RuntimeException("exception decoding UUEncoded string: " + e);
+        }
+
+        return bOut.toByteArray();
+    }
+
+    /**
+     * decode the UUEncided String data.
+     *
+     * @return a byte array representing the decoded data.
+     */
+    public static byte[] decode(
+        final String    data)
+    {
+        final ByteArrayOutputStream    bOut = new ByteArrayOutputStream();
+
+        try
+        {
+            encoder.decode(data, bOut);
+        }
+        catch (final IOException e)
+        {
+            throw new RuntimeException("exception decoding UUEncoded string: " + e);
+        }
+
+        return bOut.toByteArray();
+    }
+
+    /**
+     * decode the UUEncoded encoded String data writing it to the given output stream.
+     *
+     * @return the number of bytes produced.
+     */
+    public static int decode(
+        final String          data,
+        final OutputStream    out)
+        throws IOException
+    {
+        return encoder.decode(data, out);
+    }
+}
+

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/UUEncoder.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/UUEncoder.java?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/UUEncoder.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/UUEncoder.java Tue Aug 26 18:17:06 2014
@@ -0,0 +1,243 @@
+/*
+ * 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.geronimo.mail.util;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+public class UUEncoder implements Encoder {
+
+    // this is the maximum number of chars allowed per line, since we have to include a uuencoded length at
+    // the start of each line.
+    static private final int MAX_CHARS_PER_LINE = 45;
+
+
+    public UUEncoder()
+    {
+    }
+
+    /**
+     * encode the input data producing a UUEncoded output stream.
+     *
+     * @param data   The array of byte data.
+     * @param off    The starting offset within the data.
+     * @param length Length of the data to encode.
+     * @param out    The output stream the encoded data is written to.
+     *
+     * @return the number of bytes produced.
+     */
+    public int encode(final byte[] data, int off, int length, final OutputStream out) throws IOException
+    {
+        int byteCount = 0;
+
+        while (true) {
+            // keep writing complete lines until we've exhausted the data.
+            if (length > MAX_CHARS_PER_LINE) {
+                // encode another line and adjust the length and position
+                byteCount += encodeLine(data, off, MAX_CHARS_PER_LINE, out);
+                length -= MAX_CHARS_PER_LINE;
+                off += MAX_CHARS_PER_LINE;
+            }
+            else {
+                // last line.  Encode the partial and quit
+                byteCount += encodeLine(data, off, MAX_CHARS_PER_LINE, out);
+                break;
+            }
+        }
+        return byteCount;
+    }
+
+
+    /**
+     * Encode a single line of data (less than or equal to 45 characters).
+     *
+     * @param data   The array of byte data.
+     * @param off    The starting offset within the data.
+     * @param length Length of the data to encode.
+     * @param out    The output stream the encoded data is written to.
+     *
+     * @return The number of bytes written to the output stream.
+     * @exception IOException
+     */
+    private int encodeLine(final byte[] data, final int offset, final int length, final OutputStream out) throws IOException {
+        // write out the number of characters encoded in this line.
+        out.write((byte)((length & 0x3F) + ' '));
+        byte a;
+        byte b;
+        byte c;
+
+        // count the bytes written...we add 2, one for the length and 1 for the linend terminator.
+        int bytesWritten = 2;
+
+        for (int i = 0; i < length;) {
+            // set the padding defauls
+            b = 1;
+            c = 1;
+            // get the next 3 bytes (if we have them)
+            a = data[offset + i++];
+            if (i < length) {
+                b = data[offset + i++];
+                if (i < length) {
+                    c = data[offset + i++];
+                }
+            }
+
+            final byte d1 = (byte)(((a >>> 2) & 0x3F) + ' ');
+            final byte d2 = (byte)(((( a << 4) & 0x30) | ((b >>> 4) & 0x0F)) + ' ');
+            final byte d3 = (byte)((((b << 2) & 0x3C) | ((c >>> 6) & 0x3)) + ' ');
+            final byte d4 = (byte)((c & 0x3F) + ' ');
+
+            out.write(d1);
+            out.write(d2);
+            out.write(d3);
+            out.write(d4);
+
+            bytesWritten += 4;
+        }
+
+        // terminate with a linefeed alone
+        out.write('\n');
+
+        return bytesWritten;
+    }
+
+
+    /**
+     * decode the uuencoded byte data writing it to the given output stream
+     *
+     * @param data   The array of byte data to decode.
+     * @param off    Starting offset within the array.
+     * @param length The length of data to encode.
+     * @param out    The output stream used to return the decoded data.
+     *
+     * @return the number of bytes produced.
+     * @exception IOException
+     */
+    public int decode(final byte[] data, int off, int length, final OutputStream out) throws IOException
+    {
+        int bytesWritten = 0;
+
+        while (length > 0) {
+            final int lineOffset = off;
+
+            // scan forward looking for a EOL terminator for the next line of data.
+            while (length > 0 && data[off] != '\n') {
+                off++;
+                length--;
+            }
+
+            // go decode this line of data
+            bytesWritten += decodeLine(data, lineOffset, off - lineOffset, out);
+
+            // the offset was left pointing at the EOL character, so step over that one before
+            // scanning again.
+            off++;
+            length--;
+        }
+        return bytesWritten;
+    }
+
+
+    /**
+     * decode a single line of uuencoded byte data writing it to the given output stream
+     *
+     * @param data   The array of byte data to decode.
+     * @param off    Starting offset within the array.
+     * @param length The length of data to decode (length does NOT include the terminating new line).
+     * @param out    The output stream used to return the decoded data.
+     *
+     * @return the number of bytes produced.
+     * @exception IOException
+     */
+    private int decodeLine(final byte[] data, int off, final int length, final OutputStream out) throws IOException {
+        int count = data[off++];
+
+        // obtain and validate the count
+        if (count < ' ') {
+            throw new IOException("Invalid UUEncode line length");
+        }
+
+        count = (count - ' ') & 0x3F;
+
+        // get the rounded count of characters that should have been used to encode this.  The + 1 is for the
+        // length encoded at the beginning
+        final int requiredLength = (((count * 8) + 5) / 6) + 1;
+        if (length < requiredLength) {
+            throw new IOException("UUEncoded data and length do not match");
+        }
+
+        int bytesWritten = 0;
+        // now decode the bytes.
+        while (bytesWritten < count) {
+            // even one byte of data requires two bytes to encode, so we should have that.
+            final byte a = (byte)((data[off++] - ' ') & 0x3F);
+            final byte b = (byte)((data[off++] - ' ') & 0x3F);
+            byte c = 0;
+            byte d = 0;
+
+            // do the first byte
+            final byte first = (byte)(((a << 2) & 0xFC) | ((b >>> 4) & 3));
+            out.write(first);
+            bytesWritten++;
+
+            // still have more bytes to decode? do the second byte of the second.  That requires
+            // a third byte from the data.
+            if (bytesWritten < count) {
+                c = (byte)((data[off++] - ' ') & 0x3F);
+                final byte second = (byte)(((b << 4) & 0xF0) | ((c >>> 2) & 0x0F));
+                out.write(second);
+                bytesWritten++;
+
+                // need the third one?
+                if (bytesWritten < count) {
+                    d = (byte)((data[off++] - ' ') & 0x3F);
+                    final byte third = (byte)(((c << 6) & 0xC0) | (d & 0x3F));
+                    out.write(third);
+                    bytesWritten++;
+                }
+            }
+        }
+        return bytesWritten;
+    }
+
+
+    /**
+     * decode the UUEncoded String data writing it to the given output stream.
+     *
+     * @param data   The String data to decode.
+     * @param out    The output stream to write the decoded data to.
+     *
+     * @return the number of bytes produced.
+     * @exception IOException
+     */
+    public int decode(final String data, final OutputStream out) throws IOException
+    {
+        try {
+            // just get the byte data and decode.
+            final byte[] bytes = data.getBytes("US-ASCII");
+            return decode(bytes, 0, bytes.length, out);
+        } catch (final UnsupportedEncodingException e) {
+            throw new IOException("Invalid UUEncoding");
+        }
+    }
+}
+
+

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/UUEncoderStream.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/UUEncoderStream.java?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/UUEncoderStream.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/UUEncoderStream.java Tue Aug 26 18:17:06 2014
@@ -0,0 +1,208 @@
+/*
+ * 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.geronimo.mail.util;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+/**
+ * An implementation of a FilterOutputStream that encodes the
+ * stream data in UUencoding format.  This version does the
+ * encoding "on the fly" rather than encoding a single block of
+ * data.  Since this version is intended for use by the MimeUtilty class,
+ * it also handles line breaks in the encoded data.
+ */
+public class UUEncoderStream extends FilterOutputStream {
+
+    // default values included on the "begin" prefix of the data stream.
+    protected static final int DEFAULT_MODE = 644;
+    protected static final String DEFAULT_NAME = "encoder.buf";
+
+    protected static final int MAX_CHARS_PER_LINE = 45;
+
+    // the configured name on the "begin" command.
+    protected String name;
+    // the configured mode for the "begin" command.
+    protected int mode;
+
+    // since this is a filtering stream, we need to wait until we have the first byte written for encoding
+    // to write out the "begin" marker.  A real pain, but necessary.
+    protected boolean beginWritten = false;
+
+
+    // our encoder utility class.
+    protected UUEncoder encoder = new UUEncoder();
+
+    // Data is generally written out in 45 character lines, so we're going to buffer that amount before
+    // asking the encoder to process this.
+
+    // the buffered byte count
+    protected int bufferedBytes = 0;
+
+    // we'll encode this part once it is filled up.
+    protected byte[] buffer = new byte[45];
+
+    /**
+     * Create a Base64 encoder stream that wraps a specifed stream
+     * using the default line break size.
+     *
+     * @param out    The wrapped output stream.
+     */
+    public UUEncoderStream(final OutputStream out) {
+        this(out, DEFAULT_NAME, DEFAULT_MODE);
+    }
+
+
+    /**
+     * Create a Base64 encoder stream that wraps a specifed stream
+     * using the default line break size.
+     *
+     * @param out    The wrapped output stream.
+     * @param name   The filename placed on the "begin" command.
+     */
+    public UUEncoderStream(final OutputStream out, final String name) {
+        this(out, name, DEFAULT_MODE);
+    }
+
+
+    public UUEncoderStream(final OutputStream out, final String name, final int mode) {
+        super(out);
+        // fill in the name and mode information.
+        this.name = name;
+        this.mode = mode;
+    }
+
+
+    private void checkBegin() throws IOException {
+        if (!beginWritten) {
+            // grumble...OutputStream doesn't directly support writing String data.  We'll wrap this in
+            // a PrintStream() to accomplish the task of writing the begin command.
+
+            final PrintStream writer = new PrintStream(out);
+            // write out the stream with a CRLF marker
+            writer.print("begin " + mode + " " + name + "\r\n");
+            writer.flush();
+            beginWritten = true;
+        }
+    }
+
+    private void writeEnd() throws IOException {
+        final PrintStream writer = new PrintStream(out);
+        // write out the stream with a CRLF marker
+        writer.print("\nend\r\n");
+        writer.flush();
+    }
+
+    private void flushBuffer() throws IOException {
+        // make sure we've written the begin marker first
+        checkBegin();
+        // ask the encoder to encode and write this out.
+        if (bufferedBytes != 0) {
+            encoder.encode(buffer, 0, bufferedBytes, out);
+            // reset the buffer count
+            bufferedBytes = 0;
+        }
+    }
+
+    private int bufferSpace() {
+        return MAX_CHARS_PER_LINE - bufferedBytes;
+    }
+
+    private boolean isBufferFull() {
+        return bufferedBytes >= MAX_CHARS_PER_LINE;
+    }
+
+
+    // in order for this to work, we need to override the 3 different signatures for write
+
+    @Override
+    public void write(final int ch) throws IOException {
+        // store this in the buffer.
+        buffer[bufferedBytes++] = (byte)ch;
+
+        // if we filled this up, time to encode and write to the output stream.
+        if (isBufferFull()) {
+            flushBuffer();
+        }
+    }
+
+    @Override
+    public void write(final byte [] data) throws IOException {
+        write(data, 0, data.length);
+    }
+
+    @Override
+    public void write(final byte [] data, int offset, int length) throws IOException {
+        // first check to see how much space we have left in the buffer, and copy that over
+        final int copyBytes = Math.min(bufferSpace(), length);
+
+        System.arraycopy(buffer, bufferedBytes, data, offset, copyBytes);
+        bufferedBytes += copyBytes;
+        offset += copyBytes;
+        length -= copyBytes;
+
+        // if we filled this up, time to encode and write to the output stream.
+        if (isBufferFull()) {
+            flushBuffer();
+        }
+
+        // we've flushed the leading part up to the line break.  Now if we have complete lines
+        // of data left, we can have the encoder process all of these lines directly.
+        if (length >= MAX_CHARS_PER_LINE) {
+            final int fullLinesLength = (length / MAX_CHARS_PER_LINE) * MAX_CHARS_PER_LINE;
+            // ask the encoder to encode and write this out.
+            encoder.encode(data, offset, fullLinesLength, out);
+            offset += fullLinesLength;
+            length -= fullLinesLength;
+        }
+
+        // ok, now we're down to a potential trailing bit we need to move into the
+        // buffer for later processing.
+
+        if (length > 0) {
+            System.arraycopy(buffer, 0, data, offset, length);
+            bufferedBytes += length;
+            offset += length;
+            length -= length;
+        }
+    }
+
+    @Override
+    public void flush() throws IOException {
+        // flush any unencoded characters we're holding.
+        flushBuffer();
+        // write out the data end marker
+        writeEnd();
+        // and flush the output stream too so that this data is available.
+        out.flush();
+    }
+
+    @Override
+    public void close() throws IOException {
+        // flush all of the streams and close the target output stream.
+        flush();
+        out.close();
+    }
+
+}
+
+

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/XText.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/XText.java?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/XText.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/XText.java Tue Aug 26 18:17:06 2014
@@ -0,0 +1,166 @@
+/*
+ * 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.geronimo.mail.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Encoder for RFC1891 xtext.
+ *
+ * xtext strings are defined as
+ *
+ *    xtext = *( xchar / hexchar )
+ *
+ * where
+ *
+ *    xchar is any ASCII character in the range 33-126, EXCEPT
+ *    the characters "+" and "=".
+ *
+ *    hexchar is an ASCII "+" followed by two upper case
+ *    hexadecimal digits.
+ */
+public class XText
+{
+    private static final Encoder encoder = new XTextEncoder();
+
+    /**
+     * encode the input data producing an xtext  encoded byte array.
+     *
+     * @return a byte array containing the xtext encoded data.
+     */
+    public static byte[] encode(
+        final byte[]    data)
+    {
+        return encode(data, 0, data.length);
+    }
+
+    /**
+     * encode the input data producing an xtext encoded byte array.
+     *
+     * @return a byte array containing the xtext encoded data.
+     */
+    public static byte[] encode(
+        final byte[]    data,
+        final int       off,
+        final int       length)
+    {
+        final ByteArrayOutputStream    bOut = new ByteArrayOutputStream();
+
+        try
+        {
+            encoder.encode(data, off, length, bOut);
+        }
+        catch (final IOException e)
+        {
+            throw new RuntimeException("exception encoding xtext string: " + e);
+        }
+
+        return bOut.toByteArray();
+    }
+
+    /**
+     * xtext encode the byte data writing it to the given output stream.
+     *
+     * @return the number of bytes produced.
+     */
+    public static int encode(
+        final byte[]         data,
+        final OutputStream   out)
+        throws IOException
+    {
+        return encoder.encode(data, 0, data.length, out);
+    }
+
+    /**
+     * extext encode the byte data writing it to the given output stream.
+     *
+     * @return the number of bytes produced.
+     */
+    public static int encode(
+        final byte[]         data,
+        final int            off,
+        final int            length,
+        final OutputStream   out)
+        throws IOException
+    {
+        return encoder.encode(data, 0, data.length, out);
+    }
+
+    /**
+     * decode the xtext encoded input data. It is assumed the input data is valid.
+     *
+     * @return a byte array representing the decoded data.
+     */
+    public static byte[] decode(
+        final byte[]    data)
+    {
+        final ByteArrayOutputStream    bOut = new ByteArrayOutputStream();
+
+        try
+        {
+            encoder.decode(data, 0, data.length, bOut);
+        }
+        catch (final IOException e)
+        {
+            throw new RuntimeException("exception decoding xtext string: " + e);
+        }
+
+        return bOut.toByteArray();
+    }
+
+    /**
+     * decode the xtext encoded String data - whitespace will be ignored.
+     *
+     * @return a byte array representing the decoded data.
+     */
+    public static byte[] decode(
+        final String    data)
+    {
+        final ByteArrayOutputStream    bOut = new ByteArrayOutputStream();
+
+        try
+        {
+            encoder.decode(data, bOut);
+        }
+        catch (final IOException e)
+        {
+            throw new RuntimeException("exception decoding xtext string: " + e);
+        }
+
+        return bOut.toByteArray();
+    }
+
+    /**
+     * decode the xtext encoded String data writing it to the given output stream,
+     * whitespace characters will be ignored.
+     *
+     * @return the number of bytes produced.
+     */
+    public static int decode(
+        final String          data,
+        final OutputStream    out)
+        throws IOException
+    {
+        return encoder.decode(data, out);
+    }
+}
+

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/XTextEncoder.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/XTextEncoder.java?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/XTextEncoder.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/java/org/apache/geronimo/mail/util/XTextEncoder.java Tue Aug 26 18:17:06 2014
@@ -0,0 +1,159 @@
+/*
+ * 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.geronimo.mail.util;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class XTextEncoder
+    implements Encoder
+{
+    protected final byte[] encodingTable =
+        {
+            (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
+            (byte)'8', (byte)'9', (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F'
+        };
+
+    /*
+     * set up the decoding table.
+     */
+    protected final byte[] decodingTable = new byte[128];
+
+    protected void initialiseDecodingTable()
+    {
+        for (int i = 0; i < encodingTable.length; i++)
+        {
+            decodingTable[encodingTable[i]] = (byte)i;
+        }
+    }
+
+    public XTextEncoder()
+    {
+        initialiseDecodingTable();
+    }
+
+    /**
+     * encode the input data producing an XText output stream.
+     *
+     * @return the number of bytes produced.
+     */
+    public int encode(
+        final byte[]                data,
+        final int                    off,
+        final int                    length,
+        final OutputStream    out)
+        throws IOException
+    {
+        int bytesWritten = 0;
+
+        for (int i = off; i < (off + length); i++)
+        {
+            final int    v = data[i] & 0xff;
+            // character tha must be encoded?  Prefix with a '+' and encode in hex.
+            if (v < 33 || v > 126 || v == '+' || v == '+') {
+                out.write((byte)'+');
+                out.write(encodingTable[(v >>> 4)]);
+                out.write(encodingTable[v & 0xf]);
+                bytesWritten += 3;
+            }
+            else {
+                // add unchanged.
+                out.write((byte)v);
+                bytesWritten++;
+            }
+        }
+
+        return bytesWritten;
+    }
+
+
+    /**
+     * decode the xtext encoded byte data writing it to the given output stream
+     *
+     * @return the number of bytes produced.
+     */
+    public int decode(
+        final byte[]                data,
+        final int                    off,
+        final int                    length,
+        final OutputStream    out)
+        throws IOException
+    {
+        byte    b1, b2;
+        int        outLen = 0;
+
+        final int        end = off + length;
+
+        int i = off;
+        while (i < end)
+        {
+            final byte v = data[i++];
+            // a plus is a hex character marker, need to decode a hex value.
+            if (v == '+') {
+                b1 = decodingTable[data[i++]];
+                b2 = decodingTable[data[i++]];
+                out.write((b1 << 4) | b2);
+            }
+            else {
+                // copied over unchanged.
+                out.write(v);
+            }
+            // always just one byte added
+            outLen++;
+        }
+
+        return outLen;
+    }
+
+    /**
+     * decode the xtext encoded String data writing it to the given output stream.
+     *
+     * @return the number of bytes produced.
+     */
+    public int decode(
+        final String                data,
+        final OutputStream    out)
+        throws IOException
+    {
+        byte    b1, b2;
+        int        length = 0;
+
+        final int        end = data.length();
+
+        int i = 0;
+        while (i < end)
+        {
+            final char v = data.charAt(i++);
+            if (v == '+') {
+                b1 = decodingTable[data.charAt(i++)];
+                b2 = decodingTable[data.charAt(i++)];
+
+                out.write((b1 << 4) | b2);
+            }
+            else {
+                out.write((byte)v);
+            }
+            length++;
+        }
+
+        return length;
+    }
+}
+

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/META-INF/default.address.map
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/META-INF/default.address.map?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/META-INF/default.address.map (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/META-INF/default.address.map Tue Aug 26 18:17:06 2014
@@ -0,0 +1,27 @@
+##
+## 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.
+##
+
+##
+## $Rev: 438769 $ $Date: 2006-08-30 21:03:44 -0700 (Wed, 30 Aug 2006) $
+##
+
+# only the single mapping for smtp is defined.
+rfc822=smtp
+
+

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/META-INF/javamail.charset.map
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/META-INF/javamail.charset.map?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/META-INF/javamail.charset.map (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/META-INF/javamail.charset.map Tue Aug 26 18:17:06 2014
@@ -0,0 +1,87 @@
+##
+## 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.
+##
+
+##
+## $Rev: 438769 $ $Date: 2006-08-30 21:03:44 -0700 (Wed, 30 Aug 2006) $
+##
+
+### Character set mapping table loaded and used by the javax.mail.internet.MimeUtility class.
+
+### java character sets to MIME character set map.  This must be the first table.
+
+8859_1		ISO-8859-1
+iso8859_1	ISO-8859-1
+ISO8859_1	ISO-8859-1
+
+8859_2		ISO-8859-2
+iso8859_2	ISO-8859-2
+ISO8859_2	ISO-8859-2
+
+8859_3		ISO-8859-3
+iso8859_3	ISO-8859-3
+ISO8859_3	ISO-8859-3
+
+8859_4		ISO-8859-4
+iso8859_4	ISO-8859-4
+ISO8859_4	ISO-8859-4
+
+8859_5		ISO-8859-5
+iso8859_5	ISO-8859-5
+ISO8859_5	ISO-8859-5
+
+8859_6		ISO-8859-6
+iso8859_6	ISO-8859-6
+ISO8859_6	ISO-8859-6
+
+8859_7		ISO-8859-7
+iso8859_7	ISO-8859-7
+ISO8859_7	ISO-8859-7
+
+8859_8		ISO-8859-8
+iso8859_8	ISO-8859-8
+ISO8859_8	ISO-8859-8
+
+8859_9		ISO-8859-9
+iso8859_9	ISO-8859-9
+ISO8859_9	ISO-8859-9
+
+SJIS		Shift_JIS
+MS932		Shift_JIS
+JIS		ISO-2022-JP
+ISO2022JP	ISO-2022-JP
+EUC_JP		euc-jp
+KOI8_R		koi8-r
+EUC_CN		euc-cn
+EUC_TW		euc-tw
+EUC_KR		euc-kr
+
+--Table terminator.  The "--" at the beginning and end are required --
+
+#### MIME to java character set map
+
+iso-2022-cn     ISO2022CN
+iso-2022-kr     ISO2022KR
+utf-8           UTF8
+utf8		UTF8
+ja_jp.iso2022-7 ISO2022JP
+ja_jp.eucjp     EUCJIS
+euc-kr          KSC5601
+euckr           KSC5601
+us-ascii        ISO-8859-1
+x-us-ascii      ISO-8859-1

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/META-INF/mailcap
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/META-INF/mailcap?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/META-INF/mailcap (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/META-INF/mailcap Tue Aug 26 18:17:06 2014
@@ -0,0 +1,28 @@
+##
+## 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.
+##
+
+##
+## $Rev: 438769 $ $Date: 2006-08-30 21:03:44 -0700 (Wed, 30 Aug 2006) $
+##
+
+text/plain;;		x-java-content-handler=org.apache.geronimo.mail.handlers.TextHandler
+text/xml;;		x-java-content-handler=org.apache.geronimo.mail.handlers.XMLHandler
+text/html;;		x-java-content-handler=org.apache.geronimo.mail.handlers.HtmlHandler
+message/rfc822;;	x-java-content-handler=org.apache.geronimo.mail.handlers.MessageHandler
+multipart/*;;		x-java-content-handler=org.apache.geronimo.mail.handlers.MultipartHandler; x-java-fallback-entry=true

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.HtmlHandler
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.HtmlHandler?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.HtmlHandler (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.HtmlHandler Tue Aug 26 18:17:06 2014
@@ -0,0 +1,17 @@
+# 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.
+org.apache.geronimo.mail.handlers.HtmlHandler   # This is directly mapped back to the same class name

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.MessageHandler
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.MessageHandler?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.MessageHandler (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.MessageHandler Tue Aug 26 18:17:06 2014
@@ -0,0 +1,17 @@
+# 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.
+org.apache.geronimo.mail.handlers.MessageHandler   # This is directly mapped back to the same class name

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.MultipartHandler
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.MultipartHandler?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.MultipartHandler (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.MultipartHandler Tue Aug 26 18:17:06 2014
@@ -0,0 +1,17 @@
+# 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.
+org.apache.geronimo.mail.handlers.MessageHandler   # This is directly mapped back to the same class name

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.TextHandler
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.TextHandler?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.TextHandler (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.TextHandler Tue Aug 26 18:17:06 2014
@@ -0,0 +1,17 @@
+# 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.
+org.apache.geronimo.mail.handlers.TextHandler   # This is directly mapped back to the same class name

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.XMLHandler
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.XMLHandler?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.XMLHandler (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/main/resources/OSGI-INF/providers/org.apache.mail.handlers.XMLHandler Tue Aug 26 18:17:06 2014
@@ -0,0 +1,17 @@
+# 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.
+org.apache.geronimo.mail.handlers.XMLHandler   # This is directly mapped back to the same class name

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/test/java/javax/mail/AllTests.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/test/java/javax/mail/AllTests.java?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/test/java/javax/mail/AllTests.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/test/java/javax/mail/AllTests.java Tue Aug 26 18:17:06 2014
@@ -0,0 +1,45 @@
+/*
+ * 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 javax.mail;
+
+import javax.mail.event.AllEventTests;
+import javax.mail.internet.AllInternetTests;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * @version $Revision $ $Date$
+ */
+public class AllTests {
+    public static Test suite() {
+        final TestSuite suite = new TestSuite("Test for javax.mail");
+        //$JUnit-BEGIN$
+        suite.addTest(new TestSuite(FlagsTest.class));
+        suite.addTest(new TestSuite(HeaderTest.class));
+        suite.addTest(new TestSuite(MessagingExceptionTest.class));
+        suite.addTest(new TestSuite(URLNameTest.class));
+        suite.addTest(new TestSuite(PasswordAuthenticationTest.class));
+        suite.addTest(AllEventTests.suite());
+        suite.addTest(AllInternetTests.suite());
+        //$JUnit-END$
+        return suite;
+    }
+}

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/test/java/javax/mail/EventQueueTest.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/test/java/javax/mail/EventQueueTest.java?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/test/java/javax/mail/EventQueueTest.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/test/java/javax/mail/EventQueueTest.java Tue Aug 26 18:17:06 2014
@@ -0,0 +1,98 @@
+/*
+ * 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 javax.mail;
+
+import java.util.Vector;
+
+import javax.mail.event.FolderEvent;
+import javax.mail.event.FolderListener;
+
+import junit.framework.TestCase;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class EventQueueTest extends TestCase {
+    protected EventQueue queue; 
+    
+    @Override
+    public void setUp() throws Exception {
+        queue = new EventQueue();
+    }
+    
+    @Override
+    public void tearDown() throws Exception {
+        queue.stop(); 
+    }
+    
+    public void testEvent() {
+        doEventTests(FolderEvent.CREATED);
+        doEventTests(FolderEvent.RENAMED);
+        doEventTests(FolderEvent.DELETED);
+    }
+    
+    private void doEventTests(final int type) {
+        
+        // These tests are essentially the same as the 
+        // folder event tests, but done using the asynchronous 
+        // event queue.  
+        final FolderEvent event = new FolderEvent(this, null, type);
+        assertEquals(this, event.getSource());
+        assertEquals(type, event.getType());
+        final FolderListenerTest listener = new FolderListenerTest();
+        final Vector listeners = new Vector(); 
+        listeners.add(listener); 
+        queue.queueEvent(event, listeners);
+        // we need to make sure the queue thread has a chance to dispatch 
+        // this before we check. 
+        try {
+            Thread.currentThread();
+            Thread.sleep(1000); 
+        } catch (final InterruptedException e ) {
+        }
+        assertEquals("Unexpcted method dispatched", type, listener.getState());
+    }
+    
+    public static class FolderListenerTest implements FolderListener {
+        private int state = 0;
+        public void folderCreated(final FolderEvent event) {
+            if (state != 0) {
+                fail("Recycled Listener");
+            }
+            state = FolderEvent.CREATED;
+        }
+        public void folderDeleted(final FolderEvent event) {
+            if (state != 0) {
+                fail("Recycled Listener");
+            }
+            state = FolderEvent.DELETED;
+        }
+        public void folderRenamed(final FolderEvent event) {
+            if (state != 0) {
+                fail("Recycled Listener");
+            }
+            state = FolderEvent.RENAMED;
+        }
+        public int getState() {
+            return state;
+        }
+    }
+}
+

Added: geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/test/java/javax/mail/FlagsTest.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/test/java/javax/mail/FlagsTest.java?rev=1620683&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/test/java/javax/mail/FlagsTest.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.5_spec/src/test/java/javax/mail/FlagsTest.java Tue Aug 26 18:17:06 2014
@@ -0,0 +1,156 @@
+/*
+ * 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 javax.mail;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class FlagsTest extends TestCase {
+    private List flagtypes;
+    private Flags flags;
+    /**
+     * Constructor for FlagsTest.
+     * @param arg0
+     */
+    public FlagsTest(final String name) {
+        super(name);
+    }
+    /*
+     * @see TestCase#setUp()
+     */
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        flags = new Flags();
+        flagtypes = new LinkedList();
+        flagtypes.add(Flags.Flag.ANSWERED);
+        flagtypes.add(Flags.Flag.DELETED);
+        flagtypes.add(Flags.Flag.DRAFT);
+        flagtypes.add(Flags.Flag.FLAGGED);
+        flagtypes.add(Flags.Flag.RECENT);
+        flagtypes.add(Flags.Flag.SEEN);
+        Collections.shuffle(flagtypes);
+    }
+    public void testHashCode() {
+        final int before = flags.hashCode();
+        flags.add("Test");
+        assertTrue(
+            "Before: " + before + ", now " + flags.hashCode(),
+            flags.hashCode() != before);
+        assertTrue(flags.hashCode() != 0);
+    }
+    /*
+     * Test for void add(Flag)
+     */
+    public void testAddAndRemoveFlag() {
+        Iterator it = flagtypes.iterator();
+        while (it.hasNext()) {
+            final Flags.Flag flag = (Flags.Flag) it.next();
+            assertFalse(flags.contains(flag));
+            flags.add(flag);
+            assertTrue(flags.contains(flag));
+        }
+        it = flagtypes.iterator();
+        while (it.hasNext()) {
+            final Flags.Flag flag = (Flags.Flag) it.next();
+            flags.remove(flag);
+            assertFalse(flags.contains(flag));
+        }
+    }
+    /*
+     * Test for void add(String)
+     */
+    public void testAddString() {
+        assertFalse(flags.contains("Frog"));
+        flags.add("Frog");
+        assertTrue(flags.contains("Frog"));
+        flags.remove("Frog");
+        assertFalse(flags.contains("Frog"));
+    }
+    /*
+     * Test for void add(Flags)
+     */
+    public void testAddFlags() {
+        final Flags other = new Flags();
+        other.add("Stuff");
+        other.add(Flags.Flag.RECENT);
+        flags.add(other);
+        assertTrue(flags.contains("Stuff"));
+        assertTrue(flags.contains(Flags.Flag.RECENT));
+        assertTrue(flags.contains(other));
+        assertTrue(flags.contains(flags));
+        flags.add("Thing");
+        assertTrue(flags.contains("Thing"));
+        flags.remove(other);
+        assertFalse(flags.contains("Stuff"));
+        assertFalse(flags.contains(Flags.Flag.RECENT));
+        assertFalse(flags.contains(other));
+        assertTrue(flags.contains("Thing"));
+    }
+    /*
+     * Test for boolean equals(Object)
+     */
+    public void testEqualsObject() {
+        final Flags other = new Flags();
+        other.add("Stuff");
+        other.add(Flags.Flag.RECENT);
+        flags.add(other);
+        assertEquals(flags, other);
+    }
+    public void testGetSystemFlags() {
+        flags.add("Stuff");
+        flags.add("Another");
+        flags.add(Flags.Flag.FLAGGED);
+        flags.add(Flags.Flag.RECENT);
+        final Flags.Flag[] array = flags.getSystemFlags();
+        assertEquals(2, array.length);
+        assertTrue(
+            (array[0] == Flags.Flag.FLAGGED && array[1] == Flags.Flag.RECENT)
+                || (array[0] == Flags.Flag.RECENT
+                    && array[1] == Flags.Flag.FLAGGED));
+    }
+    public void testGetUserFlags() {
+        final String stuff = "Stuff";
+        final String another = "Another";
+        flags.add(stuff);
+        flags.add(another);
+        flags.add(Flags.Flag.FLAGGED);
+        flags.add(Flags.Flag.RECENT);
+        final String[] array = flags.getUserFlags();
+        assertEquals(2, array.length);
+        assertTrue(
+            (array[0] == stuff && array[1] == another)
+                || (array[0] == another && array[1] == stuff));
+    }
+    public void testClone() throws CloneNotSupportedException {
+        flags.add("Thing");
+        flags.add(Flags.Flag.RECENT);
+        final Flags other = (Flags) flags.clone();
+        assertTrue(other != flags);
+        assertEquals(other, flags);
+    }
+}