~ubuntu-branches/ubuntu/hardy/commons-httpclient/hardy

« back to all changes in this revision

Viewing changes to src/java/org/apache/commons/httpclient/protocol/ReflectionSocketFactory.java

  • Committer: Bazaar Package Importer
  • Author(s): Michael Meskes
  • Date: 2006-09-15 20:07:43 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060915200743-t2md4cgfsb07wgn7
Tags: 3.0.1-0.1
* Non-maintainer upload.
* Bump debhelper Build-Depends to (>= 4.1.0) as required by cdbs' 
  debhelper.mk
* Put the coppyright holders in debian/copyright
* Include the jar file in the package. (Closes: #381354)
* Only include one copy of the docs.
  done by James Westby <jw+debian@jameswestby.net>  Mon, 14 Aug 2006 02:29:47 +0100

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $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 $
 
3
 * $Revision: 155418 $
 
4
 * $Date: 2005-02-26 08:01:52 -0500 (Sat, 26 Feb 2005) $
 
5
 *
 
6
 * ====================================================================
 
7
 *
 
8
 *  Copyright 2002-2004 The Apache Software Foundation
 
9
 *
 
10
 *  Licensed under the Apache License, Version 2.0 (the "License");
 
11
 *  you may not use this file except in compliance with the License.
 
12
 *  You may obtain a copy of the License at
 
13
 *
 
14
 *      http://www.apache.org/licenses/LICENSE-2.0
 
15
 *
 
16
 *  Unless required by applicable law or agreed to in writing, software
 
17
 *  distributed under the License is distributed on an "AS IS" BASIS,
 
18
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
19
 *  See the License for the specific language governing permissions and
 
20
 *  limitations under the License.
 
21
 * ====================================================================
 
22
 *
 
23
 * This software consists of voluntary contributions made by many
 
24
 * individuals on behalf of the Apache Software Foundation.  For more
 
25
 * information on the Apache Software Foundation, please see
 
26
 * <http://www.apache.org/>.
 
27
 *
 
28
 */
 
29
 
 
30
package org.apache.commons.httpclient.protocol;
 
31
 
 
32
import java.io.IOException;
 
33
import java.lang.reflect.Constructor;
 
34
import java.lang.reflect.InvocationTargetException;
 
35
import java.lang.reflect.Method;
 
36
import java.net.InetAddress;
 
37
import java.net.Socket;
 
38
import java.net.UnknownHostException;
 
39
 
 
40
import org.apache.commons.httpclient.ConnectTimeoutException;
 
41
 
 
42
/**
 
43
 * This helper class uses refelction in order to execute Socket methods
 
44
 * available in Java 1.4 and above  
 
45
 * 
 
46
 * @author Oleg Kalnichevski
 
47
 * 
 
48
 * @since 3.0
 
49
 */
 
50
public final class ReflectionSocketFactory {
 
51
 
 
52
    private static boolean REFLECTION_FAILED = false;
 
53
    
 
54
    private static Constructor INETSOCKETADDRESS_CONSTRUCTOR = null;
 
55
    private static Method SOCKETCONNECT_METHOD = null;
 
56
    private static Method SOCKETBIND_METHOD = null;
 
57
    private static Class SOCKETTIMEOUTEXCEPTION_CLASS = null;
 
58
 
 
59
    private ReflectionSocketFactory() {
 
60
        super();
 
61
    }
 
62
 
 
63
    /**
 
64
     * This method attempts to execute Socket method available since Java 1.4
 
65
     * using reflection. If the methods are not available or could not be executed
 
66
     * <tt>null</tt> is returned
 
67
     *   
 
68
     * @param socketfactoryName name of the socket factory class
 
69
     * @param host the host name/IP
 
70
     * @param port the port on the host
 
71
     * @param localAddress the local host name/IP to bind the socket to
 
72
     * @param localPort the port on the local machine
 
73
     * @param timeout the timeout value to be used in milliseconds. If the socket cannot be
 
74
     *        completed within the given time limit, it will be abandoned
 
75
     * 
 
76
     * @return a connected Socket
 
77
     * 
 
78
     * @throws IOException if an I/O error occurs while creating the socket
 
79
     * @throws UnknownHostException if the IP address of the host cannot be
 
80
     * determined
 
81
     * @throws ConnectTimeoutException if socket cannot be connected within the
 
82
     *  given time limit
 
83
     * 
 
84
     */
 
85
    public static Socket createSocket(
 
86
        final String socketfactoryName, 
 
87
        final String host,
 
88
        final int port,
 
89
        final InetAddress localAddress,
 
90
        final int localPort,
 
91
        int timeout)
 
92
     throws IOException, UnknownHostException, ConnectTimeoutException
 
93
    {
 
94
        if (REFLECTION_FAILED) {
 
95
            //This is known to have failed before. Do not try it again
 
96
            return null;
 
97
        }
 
98
        // This code uses reflection to essentially do the following:
 
99
        //
 
100
        //  SocketFactory socketFactory = Class.forName(socketfactoryName).getDefault();
 
101
        //  Socket socket = socketFactory.createSocket();
 
102
        //  SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
 
103
        //  SocketAddress remoteaddr = new InetSocketAddress(host, port);
 
104
        //  socket.bind(localaddr);
 
105
        //  socket.connect(remoteaddr, timeout);
 
106
        //  return socket;
 
107
        try {
 
108
            Class socketfactoryClass = Class.forName(socketfactoryName);
 
109
            Method method = socketfactoryClass.getMethod("getDefault", 
 
110
                new Class[] {});
 
111
            Object socketfactory = method.invoke(null, 
 
112
                new Object[] {});
 
113
            method = socketfactoryClass.getMethod("createSocket", 
 
114
                new Class[] {});
 
115
            Socket socket = (Socket) method.invoke(socketfactory, new Object[] {});
 
116
            
 
117
            if (INETSOCKETADDRESS_CONSTRUCTOR == null) {
 
118
                Class addressClass = Class.forName("java.net.InetSocketAddress");
 
119
                INETSOCKETADDRESS_CONSTRUCTOR = addressClass.getConstructor(
 
120
                    new Class[] { InetAddress.class, Integer.TYPE });
 
121
            }
 
122
                
 
123
            Object remoteaddr = INETSOCKETADDRESS_CONSTRUCTOR.newInstance(
 
124
                new Object[] { InetAddress.getByName(host), new Integer(port)});
 
125
 
 
126
            Object localaddr = INETSOCKETADDRESS_CONSTRUCTOR.newInstance(
 
127
                    new Object[] { localAddress, new Integer(localPort)});
 
128
 
 
129
            if (SOCKETCONNECT_METHOD == null) {
 
130
                SOCKETCONNECT_METHOD = Socket.class.getMethod("connect", 
 
131
                    new Class[] {Class.forName("java.net.SocketAddress"), Integer.TYPE});
 
132
            }
 
133
 
 
134
            if (SOCKETBIND_METHOD == null) {
 
135
                SOCKETBIND_METHOD = Socket.class.getMethod("bind", 
 
136
                    new Class[] {Class.forName("java.net.SocketAddress")});
 
137
            }
 
138
            SOCKETBIND_METHOD.invoke(socket, new Object[] { localaddr});
 
139
            SOCKETCONNECT_METHOD.invoke(socket, new Object[] { remoteaddr, new Integer(timeout)});
 
140
            return socket;
 
141
        }
 
142
        catch (InvocationTargetException e) {
 
143
            Throwable cause = e.getTargetException(); 
 
144
            if (SOCKETTIMEOUTEXCEPTION_CLASS == null) {
 
145
                try {
 
146
                    SOCKETTIMEOUTEXCEPTION_CLASS = Class.forName("java.net.SocketTimeoutException");
 
147
                } catch (ClassNotFoundException ex) {
 
148
                    // At this point this should never happen. Really.
 
149
                    REFLECTION_FAILED = true;
 
150
                    return null;
 
151
                }
 
152
            }
 
153
            if (SOCKETTIMEOUTEXCEPTION_CLASS.isInstance(cause)) {
 
154
                throw new ConnectTimeoutException(
 
155
                    "The host did not accept the connection within timeout of " 
 
156
                    + timeout + " ms", cause);
 
157
            }
 
158
            if (cause instanceof IOException) {
 
159
                throw (IOException)cause;
 
160
            }
 
161
            return null;
 
162
        }
 
163
        catch (Exception e) {
 
164
            REFLECTION_FAILED = true;
 
165
            return null;
 
166
        }
 
167
    }
 
168
}