/*
 * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/protocol/ReflectionSocketFactory.java,v 1.4 2004/12/21 23:15:21 olegk Exp $
 * $Revision: 480424 $
 * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
 *
 * ====================================================================
 *
 *  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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 */

package org.apache.commons.httpclient.protocol;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import org.apache.commons.httpclient.ConnectTimeoutException;

This helper class uses refelction in order to execute Socket methods available in Java 1.4 and above
Author:Oleg Kalnichevski
Since:3.0
/** * This helper class uses refelction in order to execute Socket methods * available in Java 1.4 and above * * @author Oleg Kalnichevski * * @since 3.0 */
public final class ReflectionSocketFactory { private static boolean REFLECTION_FAILED = false; private static Constructor INETSOCKETADDRESS_CONSTRUCTOR = null; private static Method SOCKETCONNECT_METHOD = null; private static Method SOCKETBIND_METHOD = null; private static Class SOCKETTIMEOUTEXCEPTION_CLASS = null; private ReflectionSocketFactory() { super(); }
This method attempts to execute Socket method available since Java 1.4 using reflection. If the methods are not available or could not be executed null is returned
Params:
  • socketfactoryName – name of the socket factory class
  • host – the host name/IP
  • port – the port on the host
  • localAddress – the local host name/IP to bind the socket to
  • localPort – the port on the local machine
  • timeout – the timeout value to be used in milliseconds. If the socket cannot be completed within the given time limit, it will be abandoned
Throws:
Returns:a connected Socket
/** * This method attempts to execute Socket method available since Java 1.4 * using reflection. If the methods are not available or could not be executed * <tt>null</tt> is returned * * @param socketfactoryName name of the socket factory class * @param host the host name/IP * @param port the port on the host * @param localAddress the local host name/IP to bind the socket to * @param localPort the port on the local machine * @param timeout the timeout value to be used in milliseconds. If the socket cannot be * completed within the given time limit, it will be abandoned * * @return a connected Socket * * @throws IOException if an I/O error occurs while creating the socket * @throws UnknownHostException if the IP address of the host cannot be * determined * @throws ConnectTimeoutException if socket cannot be connected within the * given time limit * */
public static Socket createSocket( final String socketfactoryName, final String host, final int port, final InetAddress localAddress, final int localPort, int timeout) throws IOException, UnknownHostException, ConnectTimeoutException { if (REFLECTION_FAILED) { //This is known to have failed before. Do not try it again return null; } // This code uses reflection to essentially do the following: // // SocketFactory socketFactory = Class.forName(socketfactoryName).getDefault(); // Socket socket = socketFactory.createSocket(); // SocketAddress localaddr = new InetSocketAddress(localAddress, localPort); // SocketAddress remoteaddr = new InetSocketAddress(host, port); // socket.bind(localaddr); // socket.connect(remoteaddr, timeout); // return socket; try { Class socketfactoryClass = Class.forName(socketfactoryName); Method method = socketfactoryClass.getMethod("getDefault", new Class[] {}); Object socketfactory = method.invoke(null, new Object[] {}); method = socketfactoryClass.getMethod("createSocket", new Class[] {}); Socket socket = (Socket) method.invoke(socketfactory, new Object[] {}); if (INETSOCKETADDRESS_CONSTRUCTOR == null) { Class addressClass = Class.forName("java.net.InetSocketAddress"); INETSOCKETADDRESS_CONSTRUCTOR = addressClass.getConstructor( new Class[] { InetAddress.class, Integer.TYPE }); } Object remoteaddr = INETSOCKETADDRESS_CONSTRUCTOR.newInstance( new Object[] { InetAddress.getByName(host), new Integer(port)}); Object localaddr = INETSOCKETADDRESS_CONSTRUCTOR.newInstance( new Object[] { localAddress, new Integer(localPort)}); if (SOCKETCONNECT_METHOD == null) { SOCKETCONNECT_METHOD = Socket.class.getMethod("connect", new Class[] {Class.forName("java.net.SocketAddress"), Integer.TYPE}); } if (SOCKETBIND_METHOD == null) { SOCKETBIND_METHOD = Socket.class.getMethod("bind", new Class[] {Class.forName("java.net.SocketAddress")}); } SOCKETBIND_METHOD.invoke(socket, new Object[] { localaddr}); SOCKETCONNECT_METHOD.invoke(socket, new Object[] { remoteaddr, new Integer(timeout)}); return socket; } catch (InvocationTargetException e) { Throwable cause = e.getTargetException(); if (SOCKETTIMEOUTEXCEPTION_CLASS == null) { try { SOCKETTIMEOUTEXCEPTION_CLASS = Class.forName("java.net.SocketTimeoutException"); } catch (ClassNotFoundException ex) { // At this point this should never happen. Really. REFLECTION_FAILED = true; return null; } } if (SOCKETTIMEOUTEXCEPTION_CLASS.isInstance(cause)) { throw new ConnectTimeoutException( "The host did not accept the connection within timeout of " + timeout + " ms", cause); } if (cause instanceof IOException) { throw (IOException)cause; } return null; } catch (Exception e) { REFLECTION_FAILED = true; return null; } } }