private boolean createSocketFromFactory()

in geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/MailConnection.java [331:417]


    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;
    }