/*
 * 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.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.InetAddress;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.WeakHashMap;


/**
 * OK, so we have a final class in the API with a heck of a lot of implementation required...
 * let's try and figure out what it is meant to do.
 * <p/>
 * It is supposed to collect together properties and defaults so that they can be
 * shared by multiple applications on a desktop; with process isolation and no
 * real concept of shared memory, this seems challenging. These properties and
 * defaults rely on system properties, making management in a app server harder,
 * and on resources loaded from "mail.jar" which may lead to skew between                    
 * differnet independent implementations of this API.
 *
 * @version $Rev$ $Date$
 */
public final class Session {
    private static final Class[] PARAM_TYPES = {Session.class, URLName.class};
    private static final WeakHashMap addressMapsByClassLoader = new WeakHashMap();
    private static Session DEFAULT_SESSION;

    private Map passwordAuthentications = new HashMap();

    private final Properties properties;
    private final Authenticator authenticator;
    private boolean debug;
    private PrintStream debugOut = System.out;

    private static final WeakHashMap providersByClassLoader = new WeakHashMap();

    /**
     * No public constrcutor allowed.
     */
    private Session(Properties properties, Authenticator authenticator) {
        this.properties = properties;
        this.authenticator = authenticator;
        debug = Boolean.valueOf(properties.getProperty("mail.debug")).booleanValue();
    }

    /**
     * Create a new session initialized with the supplied properties which uses the supplied authenticator.
     * Clients should ensure the properties listed in Appendix A of the JavaMail specification are
     * set as the defaults are unlikey to work in most scenarios; particular attention should be given
     * to:
     * <ul>
     * <li>mail.store.protocol</li>
     * <li>mail.transport.protocol</li>
     * <li>mail.host</li>
     * <li>mail.user</li>
     * <li>mail.from</li>
     * </ul>
     *
     * @param properties    the session properties
     * @param authenticator an authenticator for callbacks to the user
     * @return a new session
     */
    public static Session getInstance(Properties properties, Authenticator authenticator) {
        return new Session(new Properties(properties), authenticator);
    }

    /**
     * Create a new session initialized with the supplied properties with no authenticator.
     *
     * @param properties the session properties
     * @return a new session
     * @see #getInstance(java.util.Properties, Authenticator)
     */
    public static Session getInstance(Properties properties) {
        return getInstance(properties, null);
    }

    /**
     * Get the "default" instance assuming no authenticator is required.
     *
     * @param properties the session properties
     * @return if "default" session
     * @throws SecurityException if the does not have permission to access the default session
     */
    public synchronized static Session getDefaultInstance(Properties properties) {
        return getDefaultInstance(properties, null);
    }

    /**
     * Get the "default" session.
     * If there is not current "default", a new Session is created and installed as the default.
     *
     * @param properties
     * @param authenticator
     * @return if "default" session
     * @throws SecurityException if the does not have permission to access the default session
     */
    public synchronized static Session getDefaultInstance(Properties properties, Authenticator authenticator) {
        if (DEFAULT_SESSION == null) {
            DEFAULT_SESSION = getInstance(properties, authenticator);
        } else {
            if (authenticator != DEFAULT_SESSION.authenticator) {
                if (authenticator == null || DEFAULT_SESSION.authenticator == null || authenticator.getClass().getClassLoader() != DEFAULT_SESSION.authenticator.getClass().getClassLoader()) {
                    throw new SecurityException();
                }
            }
            // todo we should check with the SecurityManager here as well
        }
        return DEFAULT_SESSION;
    }

    /**
     * Enable debugging for this session.
     * Debugging can also be enabled by setting the "mail.debug" property to true when
     * the session is being created.
     *
     * @param debug the debug setting
     */
    public void setDebug(boolean debug) {
        this.debug = debug;
    }

    /**
     * Get the debug setting for this session.
     *
     * @return the debug setting
     */
    public boolean getDebug() {
        return debug;
    }

    /**
     * Set the output stream where debug information should be sent.
     * If set to null, System.out will be used.
     *
     * @param out the stream to write debug information to
     */
    public void setDebugOut(PrintStream out) {
        debugOut = out == null ? System.out : out;
    }

    /**
     * Return the debug output stream.
     *
     * @return the debug output stream
     */
    public PrintStream getDebugOut() {
        return debugOut;
    }

    /**
     * Return the list of providers available to this application.
     * This method searches for providers that are defined in the javamail.providers
     * and javamail.default.providers resources available through the current context
     * classloader, or if that is not available, the classloader that loaded this class.
     * <p/>
     * As searching for providers is potentially expensive, this implementation maintains
     * a WeakHashMap of providers indexed by ClassLoader.
     *
     * @return an array of providers
     */
    public Provider[] getProviders() {
        ProviderInfo info = getProviderInfo();
        return (Provider[]) info.all.toArray(new Provider[info.all.size()]);
    }

    /**
     * Return the provider for a specific protocol.
     * This implementation initially looks in the Session properties for an property with the name
     * "mail.<protocol>.class"; if found it attempts to create an instance of the class named in that
     * property throwing a NoSuchProviderException if the class cannot be loaded.
     * If this property is not found, it searches the providers returned by {@link #getProviders()}
     * for a entry for the specified protocol.
     *
     * @param protocol the protocol to get a provider for
     * @return a provider for that protocol
     * @throws NoSuchProviderException
     */
    public Provider getProvider(String protocol) throws NoSuchProviderException {
    	//If we are deployed into an OSGi environment, leverage it
        Class<? extends Provider> providerClass = org.apache.servicemix.specs.locator.OsgiLocator.locate(Provider.class, protocol);
        if (providerClass != null) {
            try {
				return (Provider) providerClass.newInstance();
			} catch (InstantiationException e) {
				throw new NoSuchProviderException(e.getMessage());
			} catch (IllegalAccessException e) {
				throw new NoSuchProviderException(e.getMessage());
			}
        }

        ProviderInfo info = getProviderInfo();
        Provider provider = null;
        String providerName = properties.getProperty("mail." + protocol + ".class");
        if (providerName != null) {
            provider = (Provider) info.byClassName.get(providerName);
            if (debug) {
                writeDebug("DEBUG: new provider loaded: " + provider.toString());
            }
        }

        // if not able to locate this by class name, just grab a registered protocol.
        if (provider == null) {
            provider = (Provider) info.byProtocol.get(protocol);
        }

        if (provider == null) {
            throw new NoSuchProviderException("Unable to locate provider for protocol: " + protocol);
        }
        if (debug) {
            writeDebug("DEBUG: getProvider() returning provider " + provider.toString());
        }
        return provider;
    }

    /**
     * Make the supplied Provider the default for its protocol.
     *
     * @param provider the new default Provider
     * @throws NoSuchProviderException
     */
    public void setProvider(Provider provider) throws NoSuchProviderException {
        ProviderInfo info = getProviderInfo();
        info.byProtocol.put(provider.getProtocol(), provider);
    }

    /**
     * Return a Store for the default protocol defined by the mail.store.protocol property.
     *
     * @return the store for the default protocol
     * @throws NoSuchProviderException
     */
    public Store getStore() throws NoSuchProviderException {
        String protocol = properties.getProperty("mail.store.protocol");
        if (protocol == null) {
            throw new NoSuchProviderException("mail.store.protocol property is not set");
        }
        return getStore(protocol);
    }

    /**
     * Return a Store for the specified protocol.
     *
     * @param protocol the protocol to get a Store for
     * @return a Store
     * @throws NoSuchProviderException if no provider is defined for the specified protocol
     */
    public Store getStore(String protocol) throws NoSuchProviderException {
        Provider provider = getProvider(protocol);
        return getStore(provider);
    }

    /**
     * Return a Store for the protocol specified in the given URL
     *
     * @param url the URL of the Store
     * @return a Store
     * @throws NoSuchProviderException if no provider is defined for the specified protocol
     */
    public Store getStore(URLName url) throws NoSuchProviderException {
        return (Store) getService(getProvider(url.getProtocol()), url);
    }

    /**
     * Return the Store specified by the given provider.
     *
     * @param provider the provider to create from
     * @return a Store
     * @throws NoSuchProviderException if there was a problem creating the Store
     */
    public Store getStore(Provider provider) throws NoSuchProviderException {
        if (Provider.Type.STORE != provider.getType()) {
            throw new NoSuchProviderException("Not a Store Provider: " + provider);
        }
        return (Store) getService(provider, null);
    }

    /**
     * Return a closed folder for the supplied URLName, or null if it cannot be obtained.
     * <p/>
     * The scheme portion of the URL is used to locate the Provider and create the Store;
     * the returned Store is then used to obtain the folder.
     *
     * @param name the location of the folder
     * @return the requested folder, or null if it is unavailable
     * @throws NoSuchProviderException if there is no provider
     * @throws MessagingException      if there was a problem accessing the Store
     */
    public Folder getFolder(URLName name) throws MessagingException {
        Store store = getStore(name);
        return store.getFolder(name);
    }

    /**
     * Return a Transport for the default protocol specified by the
     * <code>mail.transport.protocol</code> property.
     *
     * @return a Transport
     * @throws NoSuchProviderException
     */
    public Transport getTransport() throws NoSuchProviderException {
        String protocol = properties.getProperty("mail.transport.protocol");
        if (protocol == null) {
            throw new NoSuchProviderException("mail.transport.protocol property is not set");
        }
        return getTransport(protocol);
    }

    /**
     * Return a Transport for the specified protocol.
     *
     * @param protocol the protocol to use
     * @return a Transport
     * @throws NoSuchProviderException
     */
    public Transport getTransport(String protocol) throws NoSuchProviderException {
        Provider provider = getProvider(protocol);
        return getTransport(provider);
    }

    /**
     * Return a transport for the protocol specified in the URL.
     *
     * @param name the URL whose scheme specifies the protocol
     * @return a Transport
     * @throws NoSuchProviderException
     */
    public Transport getTransport(URLName name) throws NoSuchProviderException {
        return (Transport) getService(getProvider(name.getProtocol()), name);
    }

    /**
     * Return a transport for the protocol associated with the type of this address.
     *
     * @param address the address we are trying to deliver to
     * @return a Transport
     * @throws NoSuchProviderException
     */
    public Transport getTransport(Address address) throws NoSuchProviderException {
        String type = address.getType();
        // load the address map from the resource files.
        Map addressMap = getAddressMap();
        String protocolName = (String)addressMap.get(type);
        if (protocolName == null) {
            throw new NoSuchProviderException("No provider for address type " + type);
        }
        return getTransport(protocolName);
    }

    /**
     * Return the Transport specified by a Provider
     *
     * @param provider the defining Provider
     * @return a Transport
     * @throws NoSuchProviderException
     */
    public Transport getTransport(Provider provider) throws NoSuchProviderException {
        return (Transport) getService(provider, null);
    }

    /**
     * Set the password authentication associated with a URL.
     *
     * @param name          the url
     * @param authenticator the authenticator
     */
    public void setPasswordAuthentication(URLName name, PasswordAuthentication authenticator) {
        if (authenticator == null) {
            passwordAuthentications.remove(name);
        } else {
            passwordAuthentications.put(name, authenticator);
        }
    }

    /**
     * Get the password authentication associated with a URL
     *
     * @param name the URL
     * @return any authenticator for that url, or null if none
     */
    public PasswordAuthentication getPasswordAuthentication(URLName name) {
        return (PasswordAuthentication) passwordAuthentications.get(name);
    }

    /**
     * Call back to the application supplied authenticator to get the needed username add password.
     *
     * @param host            the host we are trying to connect to, may be null
     * @param port            the port on that host
     * @param protocol        the protocol trying to be used
     * @param prompt          a String to show as part of the prompt, may be null
     * @param defaultUserName the default username, may be null
     * @return the authentication information collected by the authenticator; may be null
     */
    public PasswordAuthentication requestPasswordAuthentication(InetAddress host, int port, String protocol, String prompt, String defaultUserName) {
        if (authenticator == null) {
            return null;
        }
        return authenticator.authenticate(host, port, protocol, prompt, defaultUserName);
    }

    /**
     * Return the properties object for this Session; this is a live collection.
     *
     * @return the properties for the Session
     */
    public Properties getProperties() {
        return properties;
    }

    /**
     * Return the specified property.
     *
     * @param property the property to get
     * @return its value, or null if not present
     */
    public String getProperty(String property) {
        return getProperties().getProperty(property);
    }


    /**
     * Add a provider to the Session managed provider list.
     *
     * @param provider The new provider to add.
     */
    public synchronized void addProvider(Provider provider) {
        ProviderInfo info = getProviderInfo();
        info.addProvider(provider);
    }



    /**
     * Add a mapping between an address type and a protocol used
     * to process that address type.
     *
     * @param addressType
     *                 The address type identifier.
     * @param protocol The protocol name mapping.
     */
    public void setProtocolForAddress(String addressType, String protocol) {
        Map addressMap = getAddressMap();

        // no protocol specified is a removal
        if (protocol == null) {
            addressMap.remove(addressType);
        }
        else {
            addressMap.put(addressType, protocol);
        }
    }


    private Service getService(Provider provider, URLName name) throws NoSuchProviderException {
        try {
            if (name == null) {
                name = new URLName(provider.getProtocol(), null, -1, null, null, null); 
            }
            
            //If we are deployed into an OSGi environment, leverage it
            Class<? extends Service> providerClass = org.apache.servicemix.specs.locator.OsgiLocator.locate(Service.class, provider.getClassName());
            if (providerClass != null) {
                try {
                	Constructor ctr = providerClass.getConstructor(PARAM_TYPES);
                    return (Service) ctr.newInstance(this, name);
    			} catch (InstantiationException e) {
    				throw new NoSuchProviderException(e.getMessage());
    			} catch (IllegalAccessException e) {
    				throw new NoSuchProviderException(e.getMessage());
    			}
            }
            
            ClassLoader cl = getClassLoader();
            Class clazz = cl.loadClass(provider.getClassName());
            Constructor ctr = clazz.getConstructor(PARAM_TYPES);
            return (Service) ctr.newInstance(this, name);
        } catch (ClassNotFoundException e) {
            throw (NoSuchProviderException) new NoSuchProviderException("Unable to load class for provider: " + provider).initCause(e);
        } catch (NoSuchMethodException e) {
            throw (NoSuchProviderException) new NoSuchProviderException("Provider class does not have a constructor(Session, URLName): " + provider).initCause(e);
        } catch (InstantiationException e) {
            throw (NoSuchProviderException) new NoSuchProviderException("Unable to instantiate provider class: " + provider).initCause(e);
        } catch (IllegalAccessException e) {
            throw (NoSuchProviderException) new NoSuchProviderException("Unable to instantiate provider class: " + provider).initCause(e);
        } catch (InvocationTargetException e) {
            throw (NoSuchProviderException) new NoSuchProviderException("Exception from constructor of provider class: " + provider).initCause(e.getCause());
        }
    }

    private ProviderInfo getProviderInfo() {
        ClassLoader cl = getClassLoader();
        ProviderInfo info = (ProviderInfo) providersByClassLoader.get(cl);
        if (info == null) {
            info = loadProviders(cl);
        }
        return info;
    }

    private Map getAddressMap() {
        ClassLoader cl = getClassLoader();
        Map addressMap = (Map)addressMapsByClassLoader.get(cl);
        if (addressMap == null) {
            addressMap = loadAddressMap(cl);
        }
        return addressMap;
    }


    /**
     * Resolve a class loader used to resolve context resources.  The
     * class loader used is either a current thread context class
     * loader (if set), the class loader used to load an authenticator
     * we've been initialized with, or the class loader used to load
     * this class instance (which may be a subclass of Session).
     *
     * @return The class loader used to load resources.
     */
    private ClassLoader getClassLoader() {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        if (cl == null) {
            if (authenticator != null) {
                cl = authenticator.getClass().getClassLoader();
            }
            else {
                cl = this.getClass().getClassLoader();
            }
        }
        return cl;
    }

    private ProviderInfo loadProviders(ClassLoader cl) {
        // we create a merged map from reading all of the potential address map entries.  The locations
        // searched are:
        //   1.   java.home/lib/javamail.address.map
        //   2. META-INF/javamail.address.map
        //   3. META-INF/javamail.default.address.map
        //
        ProviderInfo info = new ProviderInfo();

        // make sure this is added to the global map.
        providersByClassLoader.put(cl, info);


        // NOTE:  Unlike the addressMap, we process these in the defined order.  The loading routine
        // will not overwrite entries if they already exist in the map.

        try {
            File file = new File(System.getProperty("java.home"), "lib/javamail.providers");
            InputStream is = new FileInputStream(file);
            try {
                loadProviders(info, is);
                if (debug) {
                    writeDebug("Loaded lib/javamail.providers from " + file.toString());
                }
            } finally{
                is.close();
            }
        } catch (SecurityException e) {
            // ignore
        } catch (IOException e) {
            // ignore
        }

        try {
            Enumeration e = cl.getResources("META-INF/javamail.providers");
            while (e.hasMoreElements()) {
                URL url = (URL) e.nextElement();
                if (debug) {
                    writeDebug("Loading META-INF/javamail.providers from " + url.toString());
                }
                InputStream is = url.openStream();
                try {
                    loadProviders(info, is);
                } finally{
                    is.close();
                }
            }
        } catch (SecurityException e) {
            // ignore
        } catch (IOException e) {
            // ignore
        }

        try {
            Enumeration e = cl.getResources("META-INF/javamail.default.providers");
            while (e.hasMoreElements()) {
                URL url = (URL) e.nextElement();
                if (debug) {
                    writeDebug("Loading javamail.default.providers from " + url.toString());
                }

                InputStream is = url.openStream();
                try {
                    loadProviders(info, is);
                } finally{
                    is.close();
                }
            }
        } catch (SecurityException e) {
            // ignore
        } catch (IOException e) {
            // ignore
        }

        return info;
    }

    private void loadProviders(ProviderInfo info, InputStream is) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        String line;
        while ((line = reader.readLine()) != null) {
            // Lines beginning with "#" are just comments.  
            if (line.startsWith("#")) {
                continue; 
            }
            
            StringTokenizer tok = new StringTokenizer(line, ";");
            String protocol = null;
            Provider.Type type = null;
            String className = null;
            String vendor = null;
            String version = null;
            while (tok.hasMoreTokens()) {
                String property = tok.nextToken();
                int index = property.indexOf('=');
                if (index == -1) {
                    continue;
                }
                String key = property.substring(0, index).trim().toLowerCase();
                String value = property.substring(index+1).trim();
                if (protocol == null && "protocol".equals(key)) {
                    protocol = value;
                } else if (type == null && "type".equals(key)) {
                    if ("store".equals(value)) {
                        type = Provider.Type.STORE;
                    } else if ("transport".equals(value)) {
                        type = Provider.Type.TRANSPORT;
                    }
                } else if (className == null && "class".equals(key)) {
                    className = value;
                } else if ("vendor".equals(key)) {
                    vendor = value;
                } else if ("version".equals(key)) {
                    version = value;
                }
            }
            if (protocol == null || type == null || className == null) {
                //todo should we log a warning?
                continue;
            }

            if (debug) {
                writeDebug("DEBUG: loading new provider protocol=" + protocol + ", className=" + className + ", vendor=" + vendor + ", version=" + version);
            }
            Provider provider = new Provider(type, protocol, className, vendor, version);
            // add to the info list.
            info.addProvider(provider);
        }
    }

    /**
     * Load up an address map associated with a using class loader
     * instance.
     *
     * @param cl     The class loader used to resolve the address map.
     *
     * @return A map containing the entries associated with this classloader
     *         instance.
     */
    private static Map loadAddressMap(ClassLoader cl) {
        // we create a merged map from reading all of the potential address map entries.  The locations
        // searched are:
        //   1.   java.home/lib/javamail.address.map
        //   2. META-INF/javamail.address.map
        //   3. META-INF/javamail.default.address.map
        //
        // if all of the above searches fail, we just set up some "default" defaults.

        // the format of the address.map file is defined as a property file.  We can cheat and
        // just use Properties.load() to read in the files.
        Properties addressMap = new Properties();

        // add this to the tracking map.
        addressMapsByClassLoader.put(cl, addressMap);

        // NOTE:  We are reading these resources in reverse order of what's cited above.  This allows
        // user defined entries to overwrite default entries if there are similarly named items.

        try {
            Enumeration e = cl.getResources("META-INF/javamail.default.address.map");
            while (e.hasMoreElements()) {
                URL url = (URL) e.nextElement();
                InputStream is = url.openStream();
                try {
                    // load as a property file
                    addressMap.load(is);
                } finally{
                    is.close();
                }
            }
        } catch (SecurityException e) {
            // ignore
        } catch (IOException e) {
            // ignore
        }


        try {
            Enumeration e = cl.getResources("META-INF/javamail.address.map");
            while (e.hasMoreElements()) {
                URL url = (URL) e.nextElement();
                InputStream is = url.openStream();
                try {
                    // load as a property file
                    addressMap.load(is);
                } finally{
                    is.close();
                }
            }
        } catch (SecurityException e) {
            // ignore
        } catch (IOException e) {
            // ignore
        }


        try {
            File file = new File(System.getProperty("java.home"), "lib/javamail.address.map");
            InputStream is = new FileInputStream(file);
            try {
                // load as a property file
                addressMap.load(is);
            } finally{
                is.close();
            }
        } catch (SecurityException e) {
            // ignore
        } catch (IOException e) {
            // ignore
        }

        try {
            Enumeration e = cl.getResources("META-INF/javamail.address.map");
            while (e.hasMoreElements()) {
                URL url = (URL) e.nextElement();
                InputStream is = url.openStream();
                try {
                    // load as a property file
                    addressMap.load(is);
                } finally{
                    is.close();
                }
            }
        } catch (SecurityException e) {
            // ignore
        } catch (IOException e) {
            // ignore
        }


        // if unable to load anything, at least create the MimeMessage-smtp protocol mapping.
        if (addressMap.isEmpty()) {
            addressMap.put("rfc822", "smtp");
        }

        return addressMap;
    }

    /**
     * Private convenience routine for debug output.
     *
     * @param msg    The message to write out to the debug stream.
     */
    private void writeDebug(String msg) {
        debugOut.println(msg);
    }


    private static class ProviderInfo {
        private final Map byClassName = new HashMap();
        private final Map byProtocol = new HashMap();
        private final List all = new ArrayList();

        public void addProvider(Provider provider) {
            String className = provider.getClassName();

            if (!byClassName.containsKey(className)) {
                byClassName.put(className, provider);
            }

            String protocol = provider.getProtocol();
            if (!byProtocol.containsKey(protocol)) {
                byProtocol.put(protocol, provider);
            }
            all.add(provider);
        }
    }
}
