in geronimo-mail_2.1/geronimo-mail_2.1_provider/src/main/java/org/apache/geronimo/mail/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;
}