You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by jl...@apache.org on 2020/10/07 15:58:41 UTC

svn commit: r1882306 [15/17] - in /geronimo/javamail/trunk/geronimo-javamail_1.6: ./ geronimo-javamail_1.6_mail/ geronimo-javamail_1.6_mail/src/ geronimo-javamail_1.6_mail/src/site/ geronimo-javamail_1.6_provider/ geronimo-javamail_1.6_provider/src/ ge...

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/MailConnection.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/MailConnection.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/MailConnection.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/MailConnection.java Wed Oct  7 15:58:39 2020
@@ -0,0 +1,961 @@
+/**
+ * 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.javamail.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.geronimo.javamail.authentication.ClientAuthenticator;
+import org.apache.geronimo.javamail.authentication.CramMD5Authenticator;
+import org.apache.geronimo.javamail.authentication.DigestMD5Authenticator;
+import org.apache.geronimo.javamail.authentication.LoginAuthenticator;
+import org.apache.geronimo.javamail.authentication.PlainAuthenticator;
+import org.apache.geronimo.javamail.authentication.SASLAuthenticator;
+
+/**
+ * Base class for all mail Store/Transport connection.  Centralizes management
+ * of a lot of common connection handling.  Actual protcol-specific 
+ * functions are handled at the subclass level. 
+ */
+public class MailConnection {
+    /**
+     * constants for EOL termination
+     */
+    protected static final char CR = '\r';
+    protected static final char LF = '\n';
+
+    /**
+     * property keys for protocol properties.
+     */
+    protected static final String MAIL_PORT = "port";
+    protected static final String MAIL_LOCALHOST = "localhost";
+    protected static final String MAIL_STARTTLS_ENABLE = "starttls.enable";
+    protected static final String MAIL_STARTTLS_REQUIRED = "starttls.required";
+    protected static final String MAIL_SSL_ENABLE = "ssl.enable";
+    protected static final String MAIL_TIMEOUT = "timeout";
+    protected static final String MAIL_SASL_ENABLE = "sasl.enable";
+    protected static final String MAIL_SASL_REALM = "sasl.realm";
+    protected static final String MAIL_AUTHORIZATIONID = "sasl.authorizationid"; 
+    protected static final String MAIL_SASL_MECHANISMS = "sasl.mechanisms";
+    protected static final String MAIL_PLAIN_DISABLE = "auth.plain.disable";
+    protected static final String MAIL_LOGIN_DISABLE = "auth.login.disable";
+    
+    protected static final String MAIL_FACTORY = "socketFactory"; //GERONIMO-5429
+    protected static final String MAIL_FACTORY_CLASS = "socketFactory.class";
+    protected static final String MAIL_FACTORY_FALLBACK = "socketFactory.fallback";
+    protected static final String MAIL_FACTORY_PORT = "socketFactory.port";
+
+    protected static final String MAIL_SSL_FACTORY = "ssl.socketFactory"; //GERONIMO-5429
+    protected static final String MAIL_SSL_FACTORY_CLASS = "ssl.socketFactory.class";
+    protected static final String MAIL_SSL_FACTORY_PORT = "ssl.socketFactory.port";
+    protected static final String MAIL_SSL_PROTOCOLS = "ssl.protocols";
+    protected static final String MAIL_SSL_CIPHERSUITES = "ssl.ciphersuites";
+    protected static final String MAIL_SSL_TRUST = "ssl.trust";
+
+    protected static final String MAIL_LOCALADDRESS = "localaddress";
+    protected static final String MAIL_LOCALPORT = "localport";
+    protected static final String MAIL_ENCODE_TRACE = "encodetrace";
+
+    protected static final int MIN_MILLIS = 1000 * 60;
+    protected static final int TIMEOUT = MIN_MILLIS * 5;
+    protected static final String DEFAULT_MAIL_HOST = "localhost";
+
+    protected static final String CAPABILITY_STARTTLS = "STARTTLS";
+
+    protected static final String AUTHENTICATION_PLAIN = "PLAIN";
+    protected static final String AUTHENTICATION_LOGIN = "LOGIN";
+    protected static final String AUTHENTICATION_CRAMMD5 = "CRAM-MD5";
+    protected static final String AUTHENTICATION_DIGESTMD5 = "DIGEST-MD5";
+    protected static final String AUTHENTICATION_XOAUTH2 = "XOAUTH2";
+    
+    // The mail Session we're associated with
+    protected Session session; 
+    // The protocol we're implementing 
+    protected String protocol; 
+    // There are usually SSL and non-SSL versions of these protocols.  This 
+    // indicates which version we're using.
+    protected boolean sslConnection; 
+    // This is the default port we should be using for making a connection.  Each 
+    // protocol (and each ssl version of the protocol) normally has a different default that 
+    // should be used. 
+    protected int defaultPort; 
+    
+    // a wrapper around our session to provide easier lookup of protocol 
+    // specific property values 
+    protected ProtocolProperties props; 
+    
+    // The target server host 
+    protected String serverHost;
+    // The target server port 
+    protected int serverPort; 
+    
+    // the connection socket...can be a plain socket or SSLSocket, if TLS is being used.
+    protected Socket socket;
+    
+    // our local host name
+    protected InetAddress localAddress;
+    // our local port value 
+    protected int localPort; 
+    // our local host name
+    protected String localHost;
+    
+    // our timeout value 
+    protected int timeout; 
+    
+    // our login username 
+    protected String username; 
+    // our login password 
+    protected String password; 
+    // our SASL security realm 
+    protected String realm; 
+    // our authorization id 
+    protected String authid; 
+    
+    // input stream used to read data.  If Sasl is in use, this might be other than the
+    // direct access to the socket input stream.
+    protected InputStream inputStream;
+    // the other end of the connection pipeline.
+    protected OutputStream outputStream;
+
+    // our session provided debug output stream.
+    protected PrintStream debugStream;
+    // our debug flag (passed from the hosting transport)
+    protected boolean debug;
+
+    // list of authentication mechanisms supported by the server
+    protected List authentications;
+    // map of server extension arguments
+    protected Map capabilities;        
+    // property list of authentication mechanisms
+    protected List mechanisms; 
+    
+    protected MailConnection(ProtocolProperties props) 
+    {
+        // this is our properties retriever utility, which will look up 
+        // properties based on the appropriate "mail.protocol." prefix. 
+        // this also holds other information we might need for access, such as 
+        // the protocol name and the Session; 
+        this.props = props; 
+        this.protocol = props.getProtocol(); 
+        this.session = props.getSession(); 
+        this.sslConnection = props.getSSLConnection(); 
+        this.defaultPort = props.getDefaultPort(); 
+        
+        // initialize our debug settings from the session 
+        debug = session.getDebug(); 
+        debugStream = session.getDebugOut();
+        
+        String mailSSLEnable = props.getProperty(MAIL_SSL_ENABLE);
+        if(mailSSLEnable != null) {
+            this.sslConnection = Boolean.valueOf(mailSSLEnable);
+        }
+    }
+    
+    
+    /**
+     * Connect to the server and do the initial handshaking.
+     * 
+     * @param host     The target host name.
+     * @param port     The target port
+     * @param username The connection username (can be null)
+     * @param password The authentication password (can be null).
+     * 
+     * @return true if we were able to obtain a connection and 
+     *         authenticate.
+     * @exception MessagingException
+     */
+    public boolean protocolConnect(String host, int port, String username, String password) throws MessagingException {
+        // NOTE:  We don't check for the username/password being null at this point.  It's possible that 
+        // the server will send back a PREAUTH response, which means we don't need to go through login 
+        // processing.  We'll need to check the capabilities response after we make the connection to decide 
+        // if logging in is necesssary. 
+        
+        // save this for subsequent connections.  All pool connections will use this info.
+        // if the port is defaulted, then see if we have something configured in the session.
+        // if not configured, we just use the default default.
+        if (port == -1) {
+            // check for a property and fall back on the default if it's not set.
+            port = props.getIntProperty(MAIL_PORT, props.getDefaultPort());
+            // it's possible that -1 might have been explicitly set, so one last check. 
+            if (port == -1) {
+                port = props.getDefaultPort(); 
+            }
+        }
+    	
+    	// Before we do anything, let's make sure that we successfully received a host
+    	if ( host == null ) {
+    		host = DEFAULT_MAIL_HOST;
+    	}
+        
+        this.serverHost = host;
+        this.serverPort = port;
+        this.username = username;
+        this.password = password;
+        
+        // make sure we have the realm information 
+        realm = props.getProperty(MAIL_SASL_REALM); 
+        // get an authzid value, if we have one.  The default is to use the username.
+        authid = props.getProperty(MAIL_AUTHORIZATIONID, username);
+        return true; 
+    }
+    
+    
+    /**
+     * Establish a connection using an existing socket. 
+     * 
+     * @param s      The socket to use.
+     */
+    public void connect(Socket s) {
+        // just save the socket connection 
+        this.socket = s; 
+    }
+    
+    
+    /**
+     * Create a transport connection object and connect it to the
+     * target server.
+     *
+     * @exception MessagingException
+     */
+    protected void getConnection() throws IOException, MessagingException
+    {
+        // We might have been passed a socket to connect with...if not, we need to create one of the correct type.
+        if (socket == null) {
+            // get the connection properties that control how we set this up. 
+            getConnectionProperties(); 
+            // if this is the SSL version of the protocol, we start with an SSLSocket
+            if (sslConnection) {
+                getConnectedSSLSocket();
+            }
+            else
+            {
+                getConnectedSocket();
+            }
+        }
+        // if we already have a socket, get some information from it and override what we've been passed.
+        else {
+            localPort = socket.getPort();
+            localAddress = socket.getInetAddress();
+        }
+        
+        // now set up the input/output streams.
+        getConnectionStreams(); 
+    }
+
+    /**
+     * Get common connection properties before creating a connection socket. 
+     */
+    protected void getConnectionProperties() {
+
+        // there are several protocol properties that can be set to tune the created socket.  We need to
+        // retrieve those bits before creating the socket.
+        timeout = props.getIntProperty(MAIL_TIMEOUT, -1);
+        localAddress = null;
+        // see if we have a local address override.
+        String localAddrProp = props.getProperty(MAIL_LOCALADDRESS);
+        if (localAddrProp != null) {
+            try {
+                localAddress = InetAddress.getByName(localAddrProp);
+            } catch (UnknownHostException e) {
+                // not much we can do if this fails. 
+            }
+        }
+
+        // check for a local port...default is to allow socket to choose.
+        localPort = props.getIntProperty(MAIL_LOCALPORT, 0);
+    }
+    
+
+    /**
+     * Creates a connected socket
+     *
+     * @exception MessagingException
+     */
+    protected void getConnectedSocket() throws IOException {
+        debugOut("Attempting plain socket connection to server " + serverHost + ":" + serverPort);
+
+        // make sure this is null 
+        socket = null;
+        
+        createSocket(false);
+        
+        // if we have a timeout value, set that before returning 
+        if (timeout >= 0) {
+            socket.setSoTimeout(timeout);
+        }
+    }
+    
+    private boolean createSocketFromFactory(boolean ssl, boolean layer) throws IOException {
+        
+        String socketFactoryClass = props.getProperty(ssl?MAIL_SSL_FACTORY_CLASS:MAIL_FACTORY_CLASS);
+        
+        if(socketFactoryClass == null) {
+            return false;
+        }
+        
+        // we'll try this with potentially two different factories if we're allowed to fall back.
+        boolean fallback = props.getBooleanProperty(MAIL_FACTORY_FALLBACK, false);
+        int socketFactoryPort = props.getIntProperty(ssl?MAIL_SSL_FACTORY_PORT:MAIL_FACTORY_PORT, -1);
+        Integer portArg = new Integer(socketFactoryPort == -1 ? serverPort : socketFactoryPort);
+        
+        debugOut("Creating "+(ssl?"":"non-")+"SSL socket using factory " + socketFactoryClass+ " listening on port "+portArg);
+
+        while (true) {
+            try {
+                
+                // use the current context loader to resolve this.
+                ClassLoader loader = Thread.currentThread().getContextClassLoader();
+                Class factoryClass = loader.loadClass(socketFactoryClass);
+
+                // done indirectly, we need to invoke the method using reflection.
+                // This retrieves a factory instance.
+                //Method getDefault = factoryClass.getMethod("getDefault", new Class[0]); //TODO check instantiation of socket factory
+                Object defFactory = factoryClass.newInstance();// getDefault.invoke(new Object(), new Object[0]);
+                // now that we have the factory, there are two different createSocket() calls we use,
+                // depending on whether we have a localAddress override.
+
+                if (localAddress != null && !layer) {
+                    // retrieve the createSocket(String, int, InetAddress, int) method.
+                    Class[] createSocketSig = new Class[] { String.class, Integer.TYPE, InetAddress.class, Integer.TYPE };
+                    Method createSocket = factoryClass.getMethod("createSocket", createSocketSig);
+
+                    Object[] createSocketArgs = new Object[] { serverHost, portArg, localAddress, new Integer(localPort) };
+                    socket = (Socket)createSocket.invoke(defFactory, createSocketArgs);
+                    break; 
+                }
+                else {
+                    if(layer) {
+                     // retrieve the createSocket(String, int) method.
+                        Class[] createSocketSig = new Class[] { Socket.class, String.class, Integer.TYPE, Boolean.TYPE };
+                        Method createSocket = factoryClass.getMethod("createSocket", createSocketSig);
+
+                        Object[] createSocketArgs = new Object[] { socket, serverHost, new Integer(serverPort), Boolean.TRUE };
+                        socket = (Socket)createSocket.invoke(defFactory, createSocketArgs);
+                        break; 
+                    } else {
+                     // retrieve the createSocket(String, int) method.
+                        Class[] createSocketSig = new Class[] { String.class, Integer.TYPE };
+                        Method createSocket = factoryClass.getMethod("createSocket", createSocketSig);
+
+                        Object[] createSocketArgs = new Object[] { serverHost, portArg };
+                        socket = (Socket)createSocket.invoke(defFactory, createSocketArgs);
+                        break; 
+                    }
+                    
+                    
+                }
+            } catch (Throwable e) {
+                // if we're allowed to fallback, then use the default factory and try this again.  We only
+                // allow this to happen once.
+                if (fallback) {
+                    debugOut("First attempt at creating "+(ssl?"":"non-")+"SSL socket failed, falling back to default factory");
+                    socketFactoryClass = ssl?"javax.net.ssl.SSLSocketFactory":"javax.net.SocketFactory";
+                    fallback = false;
+                    continue;
+                }
+                // we have an exception.  We're going to throw an IOException, which may require unwrapping
+                // or rewrapping the exception.
+                else {
+                    // we have an exception from the reflection, so unwrap the base exception
+                    if (e instanceof InvocationTargetException) {
+                        e = ((InvocationTargetException)e).getTargetException();
+                    }
+
+                    debugOut("Failure creating "+(ssl?"":"non-")+"SSL socket", e);
+                    // throw this as an IOException, with the original exception attached.
+                    IOException ioe = new IOException("Error connecting to " + serverHost + ", " + serverPort);
+                    ioe.initCause(e);
+                    throw ioe;
+                }
+            }
+        }
+        
+        return true;
+    }
+    
+    private void createSocketFromFactory(SocketFactory sf, boolean layer) throws IOException {
+        
+        if(sf instanceof SSLSocketFactory && layer) {
+            socket = ((SSLSocketFactory) sf).createSocket(socket, serverHost, serverPort, true);
+            return;
+        }
+        
+        if (localAddress != null) {
+            socket = sf.createSocket(serverHost, serverPort, localAddress, localPort);
+        } else
+        {
+            socket = sf.createSocket(serverHost, serverPort);
+        }
+    }
+    
+    private boolean createSocketFromConfiguredFactoryInstance(boolean ssl, boolean layer) throws IOException {
+        
+        
+        
+        if (ssl) {
+            Object sfProp = props.getPropertyAsObject(MAIL_SSL_FACTORY);
+            if (sfProp != null && sfProp instanceof SSLSocketFactory) {
+                createSocketFromFactory((SSLSocketFactory) sfProp, layer);
+                debugOut("Creating "+(ssl?"":"non-")+"SSL "+(layer?"layered":"non-layered")+" socket using a instance of factory " + sfProp.getClass()+ " listening");
+                return true;
+            }
+        } else {
+            Object sfProp = props.getPropertyAsObject(MAIL_FACTORY);
+            if (sfProp != null && sfProp instanceof SocketFactory) {
+                createSocketFromFactory((SocketFactory) sfProp, layer);
+                debugOut("Creating "+(ssl?"":"non-")+"SSL "+(layer?"layered":"non-layered")+" socket using a instance of factory " + sfProp.getClass()+ " listening");
+                return true;
+            }
+        }
+        
+        return false;
+    }
+    
+    private void createSSLSocketFromSSLContext(boolean layer) throws IOException{
+        
+        debugOut("Creating "+(layer?"layered ":"non-layered ")+"SSL socket using SSL Context");
+
+        
+        try {
+            SSLContext sslcontext = SSLContext.getInstance("TLS");
+            
+            String sslTrust = props.getProperty(MAIL_SSL_TRUST);
+            
+            TrustManager trustManager = null;
+            
+            if(sslTrust != null) {
+                if(sslTrust.equals("*")) {
+                    trustManager = new SSLTrustManager(null, true); //trust all
+                } else
+                {
+                   String[] trustedHosts = sslTrust.split("\\s+");
+                   trustManager = new SSLTrustManager(trustedHosts, false); //trust some
+                   
+                   if(serverHost == null || serverHost.isEmpty() || !Arrays.asList(trustedHosts).contains(serverHost)) {
+                       throw new IOException("Server is not trusted: " + serverHost);
+                   }
+                   
+                }
+            } else {
+                trustManager = new SSLTrustManager(null, false); //default
+                
+            }
+             
+            sslcontext.init(null, new TrustManager[]{trustManager}, null);
+            
+            createSocketFromFactory(sslcontext.getSocketFactory(), layer);
+        } catch (KeyManagementException e) {
+            //cannot happen
+            throw new IOException(e);
+        } catch (NoSuchAlgorithmException e) {
+            //cannot happen
+            throw new IOException(e);
+        }
+    }
+    
+    private void createSocket(boolean ssl) throws IOException {
+        
+        if(createSocketFromConfiguredFactoryInstance(ssl, false)) {
+            return;
+        }
+
+        if(createSocketFromFactory(ssl, false)) {
+            return;
+        }
+        
+        if(!ssl) {
+            createSocketFromFactory(SocketFactory.getDefault(), false);
+            return;
+        }
+        
+          
+        createSSLSocketFromSSLContext(false);
+    }
+
+
+    /**
+     * Creates a connected SSL socket for an initial SSL connection.
+     *
+     * @exception MessagingException
+     */
+    protected void getConnectedSSLSocket() throws IOException {
+        debugOut("Attempting SSL socket connection to server " + serverHost + ":" + serverPort);
+        // the socket factory can be specified via a protocol property, a session property, and if all else
+        // fails (which it usually does), we fall back to the standard factory class.
+
+        // make sure this is null 
+        socket = null;
+        
+        createSocket(true);
+
+        // and set the timeout value 
+        if (timeout >= 0) {
+            socket.setSoTimeout(timeout);
+        }
+        
+        // if there is a list of protocols specified, we need to break this down into 
+        // the individual names 
+        String protocols = props.getProperty(MAIL_SSL_PROTOCOLS); 
+        if (protocols != null) {
+            ArrayList list = new ArrayList(); 
+            StringTokenizer t = new StringTokenizer(protocols); 
+            
+            while (t.hasMoreTokens()) {
+                list.add(t.nextToken()); 
+            }
+            
+            ((SSLSocket)socket).setEnabledProtocols((String[])list.toArray(new String[list.size()])); 
+        }
+        
+        // and do the same for any cipher suites 
+        String suites = props.getProperty(MAIL_SSL_CIPHERSUITES); 
+        if (suites != null) {
+            ArrayList list = new ArrayList(); 
+            StringTokenizer t = new StringTokenizer(suites); 
+            
+            while (t.hasMoreTokens()) {
+                list.add(t.nextToken()); 
+            }
+            
+            ((SSLSocket)socket).setEnabledCipherSuites((String[])list.toArray(new String[list.size()])); 
+        }
+    }
+
+
+    /**
+     * Switch the connection to using TLS level security,
+     * switching to an SSL socket.
+     */
+    protected void getConnectedTLSSocket() throws MessagingException {
+     	// it worked, now switch the socket into TLS mode
+     	try {
+
+            // we use the same target and port as the current connection.
+            serverHost = socket.getInetAddress().getHostName();
+            serverPort = socket.getPort();
+
+            // the socket factory can be specified via a session property.  By default, we use
+            // the native SSL factory.
+            if(createSocketFromConfiguredFactoryInstance(true, true)) {
+                debugOut("TLS socket factory configured as instance"); 
+            } else if(createSocketFromFactory(true, true)) {
+                debugOut("TLS socket factory configured as class"); 
+            } else {
+                debugOut("TLS socket factory from SSLContext"); 
+                createSSLSocketFromSSLContext(true);
+            }
+
+            // if this is an instance of SSLSocket (very common), try setting the protocol to be
+            // "TLSv1".  If this is some other class because of a factory override, we'll just have to
+            // accept that things will work.
+            if (socket instanceof SSLSocket) {
+                String[] suites = ((SSLSocket)socket).getSupportedCipherSuites();
+                ((SSLSocket)socket).setEnabledCipherSuites(suites);
+                ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1"} );
+                ((SSLSocket)socket).setUseClientMode(true);
+                debugOut("Initiating STARTTLS handshake");
+                ((SSLSocket)socket).startHandshake();
+            } else {
+                throw new IOException("Socket is not an instance of SSLSocket, maybe wrong configured ssl factory?");
+            }
+
+            getConnectionStreams(); 
+            debugOut("TLS connection established"); 
+     	}
+        catch (Exception e) {
+            debugOut("Failure attempting to convert connection to TLS", e);
+     	    throw new MessagingException("Unable to convert connection to SSL", e);
+     	}
+    }
+    
+    
+    /**
+     * Set up the input and output streams for server communications once the 
+     * socket connection has been made. 
+     * 
+     * @exception MessagingException
+     */
+    protected void getConnectionStreams() throws MessagingException, IOException {
+        // and finally, as a last step, replace our input streams with the secure ones.
+        // now set up the input/output streams.
+        inputStream = new TraceInputStream(socket.getInputStream(), debugStream, debug, props.getBooleanProperty(
+                MAIL_ENCODE_TRACE, false));
+        outputStream = new TraceOutputStream(socket.getOutputStream(), debugStream, debug, props.getBooleanProperty(
+                MAIL_ENCODE_TRACE, false));
+    }
+    
+
+    /**
+     * Close the server connection at termination.
+     */
+    public void closeServerConnection()
+    {
+        try {
+            socket.close();
+        } catch (IOException ignored) {
+        }
+
+        socket = null;
+        inputStream = null;
+        outputStream = null;
+    }
+    
+    
+    /**
+     * Verify that we have a good connection before 
+     * attempting to send a command. 
+     * 
+     * @exception MessagingException
+     */
+    protected void checkConnected() throws MessagingException {
+        if (socket == null || !socket.isConnected()) {
+            throw new MessagingException("no connection");
+        }
+    }
+
+
+    /**
+     * Retrieve the SASL realm used for DIGEST-MD5 authentication.
+     * This will either be explicitly set, or retrieved using the
+     * mail.imap.sasl.realm session property.
+     *
+     * @return The current realm information (which can be null).
+     */
+    public String getSASLRealm() {
+        // if the realm is null, retrieve it using the realm session property.
+        if (realm == null) {
+            realm = props.getProperty(MAIL_SASL_REALM);
+        }
+        return realm;
+    }
+
+
+    /**
+     * Explicitly set the SASL realm used for DIGEST-MD5 authenticaiton.
+     *
+     * @param name   The new realm name.
+     */
+    public void setSASLRealm(String name) {
+        realm = name;
+    }
+
+
+    /**
+     * Get a list of the SASL mechanisms we're configured to accept.
+     *
+     * @return A list of mechanisms we're allowed to use.
+     */
+    protected List getSaslMechanisms() {
+        if (mechanisms == null) {
+            mechanisms = new ArrayList();
+            String mechList = props.getProperty(MAIL_SASL_MECHANISMS);
+            if (mechList != null) {
+                // the mechanisms are a blank or comma-separated list
+                StringTokenizer tokenizer = new StringTokenizer(mechList, " ,");
+
+                while (tokenizer.hasMoreTokens()) {
+                    String mech = tokenizer.nextToken().toUpperCase();
+                    mechanisms.add(mech);
+                }
+            }
+        }
+        return mechanisms;
+    }
+    
+    
+    /**
+     * Get the list of authentication mechanisms the server
+     * is supposed to support. 
+     * 
+     * @return A list of the server supported authentication 
+     *         mechanisms.
+     */
+    protected List getServerMechanisms() {
+        return authentications; 
+    }
+    
+    
+    /**
+     * Merge the configured SASL mechanisms with the capabilities that the 
+     * server has indicated it supports, returning a merged list that can 
+     * be used for selecting a mechanism. 
+     * 
+     * @return A List representing the intersection of the configured list and the 
+     *         capabilities list.
+     */
+    protected List selectSaslMechanisms() {
+        List configured = getSaslMechanisms(); 
+        List supported = getServerMechanisms();
+        
+        // if not restricted, then we'll select from anything supported. 
+        if (configured.isEmpty()) {
+            return supported; 
+        }
+        
+        List merged = new ArrayList(); 
+        
+        // we might need a subset of the supported ones 
+        for (int i = 0; i < configured.size(); i++) {
+            // if this is in both lists, add to the merged one. 
+            String mech = (String)configured.get(i); 
+            if (supported.contains(mech)) {
+                merged.add(mech); 
+            }
+        }
+        return merged; 
+    }
+
+
+    /**
+     * Process SASL-type authentication.
+     *
+     * @return An authenticator to process the login challenge/response handling.    
+     * @exception MessagingException
+     */
+    protected ClientAuthenticator getLoginAuthenticator() throws MessagingException {
+        
+        // get the list of mechanisms we're allowed to use. 
+        List mechs = selectSaslMechanisms(); 
+
+        try {
+            String[] mechArray = (String[])mechs.toArray(new String[0]); 
+            // create a SASLAuthenticator, if we can.  A failure likely indicates we're not 
+            // running on a Java 5 VM, and the Sasl API isn't available. 
+            return new SASLAuthenticator(mechArray, session.getProperties(), protocol, serverHost, getSASLRealm(), authid, username, password); 
+        } catch (Throwable e) {
+        }
+        
+
+        // now go through the progression of mechanisms we support, from the most secure to the
+        // least secure.
+
+        if (mechs.contains(AUTHENTICATION_DIGESTMD5)) {
+            return new DigestMD5Authenticator(serverHost, username, password, getSASLRealm());
+        }
+        else if (mechs.contains(AUTHENTICATION_CRAMMD5)) {
+            return new CramMD5Authenticator(username, password);
+        }
+        else if (mechs.contains(AUTHENTICATION_LOGIN)) {
+            return new LoginAuthenticator(username, password);
+        }
+        else if (mechs.contains(AUTHENTICATION_PLAIN)) {
+            return new PlainAuthenticator(authid, username, password);
+        }
+        else {
+            // can't find a mechanism we support in common
+            return null;  
+        }
+    }
+    
+    
+    /**
+     * Internal debug output routine.
+     *
+     * @param value  The string value to output.
+     */
+    protected void debugOut(String message) {
+        if (debug) {
+            debugStream.println(protocol + " DEBUG: " + message);
+        }
+    }
+
+    /**
+     * Internal debugging routine for reporting exceptions.
+     *
+     * @param message A message associated with the exception context.
+     * @param e       The received exception.
+     */
+    protected void debugOut(String message, Throwable e) {
+        if (debug) {
+            debugOut("Received exception -> " + message);
+            debugOut("Exception message -> " + e.getMessage());
+            e.printStackTrace(debugStream);
+        }
+    }
+    
+    
+    /**
+     * Test if this connection has a given capability. 
+     * 
+     * @param capability The capability name.
+     * 
+     * @return true if this capability is in the list, false for a mismatch. 
+     */
+    public boolean hasCapability(String capability) {
+        return capabilities.containsKey(capability); 
+    }
+    
+    /**
+     * Get the capabilities map. 
+     * 
+     * @return The capabilities map for the connection. 
+     */
+    public Map getCapabilities() {
+        return capabilities; 
+    }
+    
+    
+    /**
+     * Test if the server supports a given mechanism. 
+     * 
+     * @param mech   The mechanism name.
+     * 
+     * @return true if the server has asserted support for the named 
+     *         mechanism.
+     */
+    public boolean supportsMechanism(String mech) {
+        return authentications.contains(mech); 
+    }
+    
+    
+    /**
+     * Retrieve the connection host. 
+     * 
+     * @return The host name. 
+     */
+    public String getHost() {
+        return serverHost; 
+    }
+    
+
+    /**
+     * Retrieve the local client host name.
+     *
+     * @return The string version of the local host name.
+     * @exception SMTPTransportException
+     */
+    public String getLocalHost() throws MessagingException {
+        if (localHost == null) {
+
+            if (localHost == null) {
+                localHost = props.getProperty(MAIL_LOCALHOST);
+            }
+
+            if (localHost == null) {
+                localHost = props.getSessionProperty(MAIL_LOCALHOST);
+            }
+
+            if (localHost == null) {
+        	try {
+            	    localHost = InetAddress.getLocalHost().getHostName();
+                } catch (UnknownHostException e) {
+	            // fine, we're misconfigured - ignore
+    	        }
+	    }
+
+            if (localHost == null) {
+                throw new MessagingException("Can't get local hostname. "
+                        + " Please correctly configure JDK/DNS or set mail.smtp.localhost");
+            }
+        }
+
+        return localHost;
+    }
+
+    
+    /**
+     * Explicitly set the local host information.
+     *
+     * @param localHost
+     *            The new localHost name.
+     */
+    public void setLocalHost(String localHost) {
+        this.localHost = localHost;
+    }
+    
+    private class SSLTrustManager implements X509TrustManager {
+        
+        private final X509TrustManager defaultTrustManager;
+        
+        private final boolean trustAll;
+        private final String[] trustedHosts;
+
+        SSLTrustManager(String[] trustedHosts, boolean trustAll) throws IOException{
+            super();
+            this.trustAll = trustAll;
+            this.trustedHosts = trustedHosts;
+            
+            try {
+                TrustManagerFactory defaultTrustManagerFactory = TrustManagerFactory.getInstance("X509");
+                defaultTrustManagerFactory.init((KeyStore)null);
+                defaultTrustManager = (X509TrustManager) defaultTrustManagerFactory.getTrustManagers()[0];
+            } catch (NoSuchAlgorithmException e) {
+                //cannot happen
+                throw new IOException(e);
+            } catch (KeyStoreException e) {
+                //cannot happen
+                throw new IOException(e);
+            }
+            
+        }
+
+        /* (non-Javadoc)
+         * @see javax.net.ssl.X509TrustManager#checkClientTrusted(java.security.cert.X509Certificate[], java.lang.String)
+         */
+        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+            defaultTrustManager.checkClientTrusted(chain, authType);
+            
+        }
+
+        /* (non-Javadoc)
+         * @see javax.net.ssl.X509TrustManager#checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String)
+         */
+        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+            if (!trustAll || trustedHosts != null) {
+                defaultTrustManager.checkServerTrusted(chain, authType);
+            }
+            
+        }
+
+        /* (non-Javadoc)
+         * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
+         */
+        public X509Certificate[] getAcceptedIssuers() {
+            return defaultTrustManager.getAcceptedIssuers();
+        }
+        
+    }
+}

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/ProtocolProperties.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/ProtocolProperties.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/ProtocolProperties.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/ProtocolProperties.java Wed Oct  7 15:58:39 2020
@@ -0,0 +1,291 @@
+/**
+ * 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.javamail.util;
+ 
+import java.util.Properties;
+
+import javax.mail.Session;
+
+/**
+ * Interface for providing access to protocol specific properties to 
+ * utility classes. 
+ */
+public class ProtocolProperties {
+    // the protocol we're working with. 
+    protected String protocol; 
+    // a preconstructed prefix string to reduce concatenation operations.  
+    protected String protocolPrefix; 
+    // the Session that's the source of all of the properties 
+    protected Session session; 
+    // the sslConnection property.  This indicates this protocol is to use SSL for 
+    // all communications with the server. 
+    protected boolean sslConnection;
+    // the default port property.  The default port differs with the protocol 
+    // and the sslConnection property. 
+    protected int defaultPort; 
+    
+    
+    public ProtocolProperties(Session session, String protocol, boolean sslConnection, int defaultPort) {
+        this.session = session; 
+        this.protocol = protocol; 
+        this.sslConnection = sslConnection; 
+        this.defaultPort = defaultPort; 
+        // this helps avoid a lot of concatenates when retrieving properties. 
+        protocolPrefix = "mail." + protocol + ".";
+    }
+    
+    
+    /**
+     * Retrieve the Session associated with this property bundle instance.
+     * 
+     * @return A Session object that's the source of the accessed properties. 
+     */
+    public Session getSession() {
+        return session; 
+    }
+    
+    
+    /**
+     * Retrieve the name of the protocol used to access properties.
+     * 
+     * @return The protocol String name. 
+     */
+    public String getProtocol() {
+        return protocol; 
+    }
+    
+    
+    /**
+     * Retrieve the SSL Connection flag for this protocol; 
+     * 
+     * @return true if an SSL connection is required, false otherwise. 
+     */
+    public boolean getSSLConnection() {
+        return sslConnection; 
+    }
+    
+    
+    /**
+     * Return the default port to use with this connection.
+     * 
+     * @return The default port value. 
+     */
+    public int getDefaultPort() {
+        return defaultPort; 
+    }
+    
+    
+    /**
+     * Get a property associated with this mail protocol.
+     *
+     * @param name   The name of the property.
+     *
+     * @return The property value (returns null if the property has not been set).
+     */
+    public String getProperty(String name) {
+        // the name we're given is the least qualified part of the name.  
+        // We construct the full property name
+        // using the protocol
+        String fullName = protocolPrefix + name;
+        return session.getProperty(fullName);
+    }
+    
+    /**
+     * Get a property (as object) associated with this mail protocol.
+     *
+     * @param name   The name of the property.
+     *
+     * @return The property value (returns null if the property has not been set).
+     */
+    public Object getPropertyAsObject(String name) {
+        // the name we're given is the least qualified part of the name.  
+        // We construct the full property name
+        // using the protocol
+        String fullName = protocolPrefix + name;
+        return session.getProperties().get(fullName);
+    }
+
+    /**
+     * Get a property associated with this mail session.  Returns
+     * the provided default if it 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 (returns defaultValue if the property has not been set).
+     */
+    public String getProperty(String name, String defaultValue) {
+        // the name we're given is the least qualified part of the name.  
+        // We construct the full property name
+        // using the protocol
+        String fullName = protocolPrefix + name;
+        String value = session.getProperty(fullName);
+        if (value == null) {
+            value = defaultValue; 
+        }
+        return value; 
+    }
+
+
+    /**
+     * 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 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.
+     */
+    public int getIntProperty(String name, int defaultValue)
+    {
+        // retrieve the property 
+        String value = getProperty(name); 
+        // return the default value if not set. 
+        if (value == null) {
+            return defaultValue; 
+        }
+        return Integer.parseInt(value); 
+    }
+    
+
+    /**
+     * Get a property associated with this mail session as an boolean value.  Returns
+     * the default value if the property doesn't exist or it doesn't have a valid int 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
+     */
+    public boolean getBooleanProperty(String name, boolean defaultValue)
+    {
+        // retrieve the property 
+        String value = getProperty(name); 
+        // return the default value if not set. 
+        if (value == null) {
+            return defaultValue; 
+        }
+        // just do a single test for true. 
+        if ("true".equals(value)) {
+            return true; 
+        }
+        // return false for anything other than true
+        return false; 
+    }
+    
+    
+    /**
+     * Get a property associated with this mail session.  Session 
+     * properties all begin with "mail."
+     *
+     * @param name   The name of the property.
+     *
+     * @return The property value (returns null if the property has not been set).
+     */
+    public String getSessionProperty(String name) {
+        // the name we're given is the least qualified part of the name.  
+        // We construct the full property name
+        // using the protocol
+        String fullName = "mail." + name;
+        return session.getProperty(fullName);
+    }
+
+    /**
+     * Get a property associated with this mail session.  Returns
+     * the provided default if it 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 (returns defaultValue if the property has not been set).
+     */
+    public String getSessionProperty(String name, String defaultValue) {
+        // the name we're given is the least qualified part of the name.  
+        // We construct the full property name
+        // using the protocol
+        String fullName = "mail." + name;
+        String value = session.getProperty(fullName);
+        if (value == null) {
+            value = defaultValue; 
+        }
+        return value; 
+    }
+
+
+    /**
+     * 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 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.
+     */
+    public int getIntSessionProperty(String name, int defaultValue)
+    {
+        // retrieve the property 
+        String value = getSessionProperty(name); 
+        // return the default value if not set. 
+        if (value == null) {
+            return defaultValue; 
+        }
+        return Integer.parseInt(value); 
+    }
+    
+
+    /**
+     * Get a property associated with this mail session as an boolean value.  Returns
+     * the default value if the property doesn't exist or it doesn't have a valid int 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
+     */
+    public boolean getBooleanSessionProperty(String name, boolean defaultValue)
+    {
+        // retrieve the property 
+        String value = getSessionProperty(name); 
+        // return the default value if not set. 
+        if (value == null) {
+            return defaultValue; 
+        }
+        // just do a single test for true. 
+        if ("true".equals(value)) {
+            return true; 
+        }
+        // return false for anything other than true
+        return false; 
+    }
+    
+    /**
+     * Get the complete set of properties associated with this Session.
+     * 
+     * @return The Session properties bundle. 
+     */
+    public Properties getProperties() {
+        return session.getProperties(); 
+    }
+    
+}

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/ResponseFormatException.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/ResponseFormatException.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/ResponseFormatException.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/ResponseFormatException.java Wed Oct  7 15:58:39 2020
@@ -0,0 +1,34 @@
+/**
+ * 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.javamail.util;
+
+import javax.mail.MessagingException; 
+
+public class ResponseFormatException extends MessagingException {
+    public ResponseFormatException() {
+        super();
+    }
+
+    public ResponseFormatException(String message) {
+        super(message);
+    }
+
+    public ResponseFormatException(String message, Exception cause) {
+        super(message, cause);
+    }
+}

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/TraceInputStream.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/TraceInputStream.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/TraceInputStream.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/TraceInputStream.java Wed Oct  7 15:58:39 2020
@@ -0,0 +1,110 @@
+/*
+ * 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.javamail.util;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.geronimo.mail.james.mime4j.codec.QuotedPrintableOutputStream;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class TraceInputStream extends FilterInputStream {
+    // the current debug setting
+    protected boolean debug = false;
+
+    // the target trace output stream.
+    protected OutputStream traceStream;
+
+    /**
+     * Construct a debug trace stream.
+     * 
+     * @param in
+     *            The source input stream.
+     * @param traceStream
+     *            The side trace stream to which trace data gets written.
+     * @param encode
+     *            Indicates whether we wish the Trace data to be Q-P encoded.
+     */
+    public TraceInputStream(InputStream in, OutputStream traceStream, boolean debug, boolean encode) {
+        super(in);
+        this.debug = debug;
+        if (encode) {
+            this.traceStream = new QuotedPrintableOutputStream(traceStream, false);
+        } else {
+            this.traceStream = traceStream;
+        }
+    }
+
+    /**
+     * Set the current setting of the debug trace stream debug flag.
+     * 
+     * @param d
+     *            The new debug flag settings.
+     */
+    public void setDebug(boolean d) {
+        debug = d;
+    }
+
+    /**
+     * Reads up to len bytes of data from this input stream, placing them directly 
+     * into the provided byte array. 
+     * 
+     * @param b   the provided data buffer. 
+     * @param off the starting offset within the buffer for placing the data. 
+     * @param len the maximum number of bytes to read. 
+     * @return    that number of bytes that have been read and copied into the 
+     *            buffer or -1 if an end of stream occurs. 
+     * @exception IOException for any I/O errors. 
+     */
+    public int read(byte b[], int off, int len) throws IOException {
+        int count = in.read(b, off, len);
+        if (debug && count > 0) {
+            traceStream.write(b, off, count);
+        }
+        return count;
+    }
+
+    /**
+     * Read the next byte of data from the input stream, returning it as an 
+     * int value.  Returns -1 if the end of stream is detected. 
+     * 
+     * @return The next byte of data or -1 to indicate end-of-stream.      
+     * @exception IOException for any I/O errors
+     */
+    public int read() throws IOException {
+        int b = in.read();
+        if (debug) {
+            traceStream.write(b);
+        }
+        return b;
+    }
+
+    public int read(byte[] b) throws IOException {
+        final int read = in.read(b);
+        if (debug && read > 0) {
+            traceStream.write(b, 0, read);
+        }
+        return read;
+    }
+}

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/TraceOutputStream.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/TraceOutputStream.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/TraceOutputStream.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/TraceOutputStream.java Wed Oct  7 15:58:39 2020
@@ -0,0 +1,97 @@
+/*
+ * 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.javamail.util;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.geronimo.mail.james.mime4j.codec.QuotedPrintableOutputStream;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class TraceOutputStream extends FilterOutputStream {
+    // the current debug setting
+    protected boolean debug = false;
+
+    // the target trace output stream.
+    protected OutputStream traceStream;
+
+    /**
+     * Construct a debug trace stream.
+     *
+     * @param out
+     *            The target out put stream.
+     * @param traceStream
+     *            The side trace stream to which trace data gets written.
+     * @param encode
+     *            Indicates whether we wish the Trace data to be Q-P encoded.
+     */
+    public TraceOutputStream(OutputStream out, OutputStream traceStream, boolean debug, boolean encode) {
+        super(out);
+        this.debug = debug;
+        if (encode) {
+            this.traceStream = new QuotedPrintableOutputStream(traceStream, false);
+        } else {
+            this.traceStream = traceStream;
+        }
+    }
+
+    /**
+     * Set the current setting of the debug trace stream debug flag.
+     *
+     * @param d
+     *            The new debug flag settings.
+     */
+    public void setDebug(boolean d) {
+        debug = d;
+    }
+
+
+    /**
+     * Write a single byte to the output stream.
+     * 
+     * @param b      The byte to be written.
+     * 
+     * @exception IOException
+     *                   thrown for any I/O errors.
+     */
+    public void write(int b) throws IOException {
+        if (debug) {
+            traceStream.write(b);
+        }
+        super.write(b);
+    }
+
+    public void write(byte[] b, int off, int len) throws IOException {
+        if (this.debug) {
+            this.traceStream.write(b, off, len);
+        }
+        out.write(b, off, len);
+    }
+
+    public void write(byte[] b) throws IOException {
+        if (this.debug) {
+            this.traceStream.write(b);
+        }
+        out.write(b);
+    } 
+}

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/META-INF/javamail.default.address.map
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/META-INF/javamail.default.address.map?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/META-INF/javamail.default.address.map (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/META-INF/javamail.default.address.map Wed Oct  7 15:58:39 2020
@@ -0,0 +1,34 @@
+##
+## 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: 437934 $ $Date: 2006-08-28 20:27:42 -0700 (Mon, 28 Aug 2006) $
+##
+
+#
+# This file configures the default behaviour of JavaMail. DO NOT EDIT.
+# Create a new file /META-INF/javamail.address.map and put
+# the same format lines in there.
+#
+# Note that you can't override these defaults, merely add to them.
+#
+# $Rev: 351866 $ $Date: 2005-12-02 20:12:14 -0500 (Fri, 02 Dec 2005) $
+#
+rfc822=smtp
+news=nntp

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/META-INF/javamail.default.providers
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/META-INF/javamail.default.providers?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/META-INF/javamail.default.providers (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/META-INF/javamail.default.providers Wed Oct  7 15:58:39 2020
@@ -0,0 +1,43 @@
+##
+## 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: 437934 $ $Date: 2006-08-28 20:27:42 -0700 (Mon, 28 Aug 2006) $
+##
+
+#
+# This file configures the default behaviour of JavaMail. DO NOT EDIT.
+# Create a new file /META-INF/javamail.providers and put
+# the same format lines in there.
+#
+# Note that you can't override these defaults, merely add to them.
+#
+# $Rev: 398634 $ $Date: 2006-05-01 12:56:06 -0400 (Mon, 01 May 2006) $
+#
+protocol=smtp; type=transport; class=org.apache.geronimo.javamail.transport.smtp.SMTPTransport; vendor=Apache Software Foundation; version=1.0
+protocol=smtps; type=transport; class=org.apache.geronimo.javamail.transport.smtp.SMTPSTransport; vendor=Apache Software Foundation; version=1.0
+protocol=nntp-post; type=transport; class=org.apache.geronimo.javamail.transport.nntp.NNTPTransport; vendor=Apache Software Foundation; version=1.0
+protocol=nntp-posts; type=transport; class=org.apache.geronimo.javamail.transport.nntp.NNTPSSLTransport; vendor=Apache Software Foundation; version=1.0
+protocol=nntp; type=store; class=org.apache.geronimo.javamail.store.nntp.NNTPStore; vendor=Apache Software Foundation; version=1.0
+protocol=nntps; type=store; class=org.apache.geronimo.javamail.store.nntp.NNTPSSLStore; vendor=Apache Software Foundation; version=1.0
+protocol=pop3; type=store; class=org.apache.geronimo.javamail.store.pop3.POP3Store; vendor=Apache Software Foundation; version=1.0
+protocol=pop3s; type=store; class=org.apache.geronimo.javamail.store.pop3.POP3SSLStore; vendor=Apache Software Foundation; version=1.0
+protocol=imap; type=store; class=org.apache.geronimo.javamail.store.imap.IMAPStore; vendor=Apache Software Foundation; version=1.0
+protocol=imaps; type=store; class=org.apache.geronimo.javamail.store.imap.IMAPSSLStore; vendor=Apache Software Foundation; version=1.0
+

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/META-INF/mailcap
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/META-INF/mailcap?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/META-INF/mailcap (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/META-INF/mailcap Wed Oct  7 15:58:39 2020
@@ -0,0 +1,31 @@
+##
+## 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$ $Date$
+##
+
+text/plain;;    x-java-content-handler=org.apache.geronimo.javamail.handlers.TextPlainHandler
+text/html;;     x-java-content-handler=org.apache.geronimo.javamail.handlers.TextHtmlHandler
+text/xml;;      x-java-content-handler=org.apache.geronimo.javamail.handlers.TextXmlHandler
+
+## These are not implemented in the reference implementation because the required support                  
+## is not available on server JVMs. 
+## image/gif;;     x-java-content-handler=org.apache.geronimo.javamail.handlers.ImageGifHandler
+## image/jpeg;;    x-java-content-handler=org.apache.geronimo.javamail.handlers.ImageJpegHandler
+## image/jpg;;    x-java-content-handler=org.apache.geronimo.javamail.handlers.ImageJpegHandler
+
+multipart/*;;   x-java-content-handler=org.apache.geronimo.javamail.handlers.MultipartHandler
+message/rfc822;; x-java-content-handler=org.apache.geronimo.javamail.handlers.RFC822MessageHandler

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.ImageGifHandler
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.ImageGifHandler?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.ImageGifHandler (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.ImageGifHandler Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.handlers.ImageGifHandler   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.ImageJpegHandler
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.ImageJpegHandler?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.ImageJpegHandler (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.ImageJpegHandler Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.handlers.ImageJpegHandler   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.MultipartHandler
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.MultipartHandler?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.MultipartHandler (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.MultipartHandler Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.handlers.MultipartHandler   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.RFC822MessageHandler
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.RFC822MessageHandler?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.RFC822MessageHandler (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.RFC822MessageHandler Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.handlers.RFC822MessageHandler   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.TextHtmlHandler
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.TextHtmlHandler?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.TextHtmlHandler (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.TextHtmlHandler Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.handlers.TextHtmlHandler   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.TextPlainHandler
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.TextPlainHandler?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.TextPlainHandler (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.TextPlainHandler Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.handlers.TextPlainHandler   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.TextXmlHandler
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.TextXmlHandler?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.TextXmlHandler (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.handlers.TextXmlHandler Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.handlers.TextXmlHandler   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.imap.IMAPSSSLStore
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.imap.IMAPSSSLStore?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.imap.IMAPSSSLStore (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.imap.IMAPSSSLStore Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.store.imap.IMAPSSLStore   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.imap.IMAPStore
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.imap.IMAPStore?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.imap.IMAPStore (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.imap.IMAPStore Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.store.imap.IMAPStore   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.nntp.NNTPSSLStore
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.nntp.NNTPSSLStore?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.nntp.NNTPSSLStore (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.nntp.NNTPSSLStore Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.store.nntp.NNTPSSLStore   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.nntp.NNTPStore
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.nntp.NNTPStore?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.nntp.NNTPStore (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.nntp.NNTPStore Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.store.nntp.NNTPStore   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.pop3.POP3SSLStore
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.pop3.POP3SSLStore?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.pop3.POP3SSLStore (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.pop3.POP3SSLStore Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.store.pop3.POP3SSLStore   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.pop3.POP3Store
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.pop3.POP3Store?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.pop3.POP3Store (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.store.pop3.POP3Store Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.store.pop3.POP3Store   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.transport.nntp.NNTPSSLTransport
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.transport.nntp.NNTPSSLTransport?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.transport.nntp.NNTPSSLTransport (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.transport.nntp.NNTPSSLTransport Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.transport.nntp.NNTPSSLTransport   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.transport.nntp.NNTPTransport
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.transport.nntp.NNTPTransport?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.transport.nntp.NNTPTransport (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.transport.nntp.NNTPTransport Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.transport.nntp.NNTPTransport   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.transport.smtp.SMTPSSLTransport
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.transport.smtp.SMTPSSLTransport?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.transport.smtp.SMTPSSLTransport (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.transport.smtp.SMTPSSLTransport Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.transport.smtp.SMTPSTransport   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.transport.smtp.SMTPTransport
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.transport.smtp.SMTPTransport?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.transport.smtp.SMTPTransport (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/resources/OSGI-INF/providers/org.apache.javamail.transport.smtp.SMTPTransport Wed Oct  7 15:58:39 2020
@@ -0,0 +1 @@
+org.apache.geronimo.javamail.transport.smtp.SMTPTransport   # This is directly mapped back to the same class name

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/site/site.xml
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/site/site.xml?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/site/site.xml (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/site/site.xml Wed Oct  7 15:58:39 2020
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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$ $Date$ -->
+
+<project name="${project.name}">
+    
+    <body>
+        
+        ${parentProject}
+        
+        ${modules}
+        
+        ${reports}
+        
+    </body>
+
+</project>
+
+

Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/test/java/org/apache/geronimo/javamail/handlers/AbstractHandler.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/test/java/org/apache/geronimo/javamail/handlers/AbstractHandler.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/test/java/org/apache/geronimo/javamail/handlers/AbstractHandler.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/test/java/org/apache/geronimo/javamail/handlers/AbstractHandler.java Wed Oct  7 15:58:39 2020
@@ -0,0 +1,63 @@
+/**
+ *  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.javamail.handlers;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.ByteArrayOutputStream;
+import javax.activation.DataContentHandler;
+import javax.activation.DataSource;
+
+import junit.framework.TestCase;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractHandler extends TestCase {
+    protected DataContentHandler dch;
+    protected String mimeType;
+
+    public void testGetContent() throws Exception {
+        final byte[] bytes = "Hello World".getBytes();
+        DataSource ds = new DataSource() {
+            public InputStream getInputStream() {
+                return new ByteArrayInputStream(bytes);
+            }
+
+            public OutputStream getOutputStream() {
+                throw new UnsupportedOperationException();
+            }
+
+            public String getContentType() {
+                return mimeType; 
+            }
+
+            public String getName() {
+                throw new UnsupportedOperationException();
+            }
+        };
+        Object o = dch.getContent(ds);
+        assertEquals("Hello World", o);
+    }
+
+    public void testWriteTo() throws Exception {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        dch.writeTo("Hello World", mimeType, baos);
+        assertEquals("Hello World", baos.toString());
+    }
+}