protected void getConnectedSSLSocket()

in geronimo-javamail_1.3.1/geronimo-javamail_1.3.1_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPTransport.java [1182:1303]


    protected void getConnectedSSLSocket() throws IOException {
        if (debug) {
            debugOut("Attempting SSL socket connection to server " + host + ":" + port);
        }
        // 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.
        String socketFactory = getProtocolProperty(MAIL_SMTP_FACTORY_CLASS, getSessionProperty(MAIL_SSLFACTORY_CLASS,
                "javax.net.ssl.SSLSocketFactory"));

        // there are several protocol properties that can be set to tune the
        // created socket. We need to
        // retrieve those bits before creating the socket.
        int timeout = getIntProtocolProperty(MAIL_SMTP_TIMEOUT, -1);
        InetAddress localAddress = null;
        // see if we have a local address override.
        String localAddrProp = getProtocolProperty(MAIL_SMTP_LOCALADDRESS);
        if (localAddrProp != null) {
            localAddress = InetAddress.getByName(localAddrProp);
        }

        // check for a local port...default is to allow socket to choose.
        int localPort = getIntProtocolProperty(MAIL_SMTP_LOCALPORT, 0);

        socket = null;

        // if there is no socket factory defined (normal), we just create a
        // socket directly.
        if (socketFactory == null) {
            socket = new Socket(host, port, localAddress, localPort);
        }

        else {
            // we'll try this with potentially two different factories if we're
            // allowed to fall back.
            boolean fallback = isProtocolPropertyTrue(MAIL_SMTP_FACTORY_FALLBACK);

            while (true) {
                try {
                    if (debug) {
                        debugOut("Creating SSL socket using factory " + socketFactory);
                    }

                    int socketFactoryPort = getIntProtocolProperty(MAIL_SMTP_FACTORY_PORT, -1);

                    // we choose the port used by the socket based on overrides.
                    Integer portArg = new Integer(socketFactoryPort == -1 ? port : socketFactoryPort);

                    // use the current context loader to resolve this.
                    ClassLoader loader = Thread.currentThread().getContextClassLoader();
                    Class factoryClass = loader.loadClass(socketFactory);

                    // done indirectly, we need to invoke the method using
                    // reflection.
                    // This retrieves a factory instance.
                    Method getDefault = factoryClass.getMethod("getDefault", new Class[0]);
                    Object defFactory = 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) {
                        // 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[] { host, portArg, localAddress, new Integer(localPort) };
                        socket = (Socket) createSocket.invoke(defFactory, createSocketArgs);
                    } 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[] { host, portArg };
                        socket = (Socket) createSocket.invoke(defFactory, createSocketArgs);
                    }
                    // now break out and configure the socket.
                    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) {
                        if (debug) {
                            debugOut("First attempt at creating SSL socket failed, falling back to default factory");
                        }
                        socketFactory = "javax.net.ssl.SSLSocketFactory";
                        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();
                        }

                        if (debug) {
                            debugOut("Failure creating SSL socket", e);
                        }

                        // throw this as an IOException, with the original
                        // exception attached.
                        IOException ioe = new IOException("Error connecting to " + host + ", " + port);
                        ioe.initCause(e);
                        throw ioe;
                    }
                }
            }
        }

        if (timeout >= 0) {
            socket.setSoTimeout(timeout);
        }
    }