• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/MultihomePlainSocketFactory.java $
3  * $Revision: 653041 $
4  * $Date: 2008-05-03 03:39:28 -0700 (Sat, 03 May 2008) $
5  *
6  * ====================================================================
7  * Licensed to the Apache Software Foundation (ASF) under one
8  * or more contributor license agreements.  See the NOTICE file
9  * distributed with this work for additional information
10  * regarding copyright ownership.  The ASF licenses this file
11  * to you under the Apache License, Version 2.0 (the
12  * "License"); you may not use this file except in compliance
13  * with the License.  You may obtain a copy of the License at
14  *
15  *   http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing,
18  * software distributed under the License is distributed on an
19  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20  * KIND, either express or implied.  See the License for the
21  * specific language governing permissions and limitations
22  * under the License.
23  * ====================================================================
24  *
25  * This software consists of voluntary contributions made by many
26  * individuals on behalf of the Apache Software Foundation.  For more
27  * information on the Apache Software Foundation, please see
28  * <http://www.apache.org/>.
29  *
30  */
31 
32 package org.apache.http.conn;
33 
34 import java.io.IOException;
35 import java.net.InetAddress;
36 import java.net.InetSocketAddress;
37 import java.net.Socket;
38 import java.net.SocketTimeoutException;
39 import java.util.ArrayList;
40 import java.util.Collections;
41 import java.util.List;
42 import java.util.Arrays;
43 
44 import org.apache.http.conn.scheme.PlainSocketFactory;
45 import org.apache.http.conn.scheme.SocketFactory;
46 import org.apache.http.params.HttpConnectionParams;
47 import org.apache.http.params.HttpParams;
48 
49 /**
50  * Socket factory that implements a simple multi-home fail-over on connect failure,
51  * provided the same hostname resolves to multiple {@link InetAddress}es. Please note
52  * the {@link #connectSocket(Socket, String, int, InetAddress, int, HttpParams)}
53  * method cannot be reliably interrupted by closing the socket returned by the
54  * {@link #createSocket()} method.
55  *
56  * @deprecated Please use {@link java.net.URL#openConnection} instead.
57  *     Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
58  *     for further details.
59  */
60 @Deprecated
61 public final class MultihomePlainSocketFactory implements SocketFactory {
62 
63     /**
64      * The factory singleton.
65      */
66     private static final
67     MultihomePlainSocketFactory DEFAULT_FACTORY = new MultihomePlainSocketFactory();
68 
69     /**
70      * Gets the singleton instance of this class.
71      * @return the one and only plain socket factory
72      */
getSocketFactory()73     public static MultihomePlainSocketFactory getSocketFactory() {
74         return DEFAULT_FACTORY;
75     }
76 
77     /**
78      * Restricted default constructor.
79      */
MultihomePlainSocketFactory()80     private MultihomePlainSocketFactory() {
81         super();
82     }
83 
84 
85     // non-javadoc, see interface org.apache.http.conn.SocketFactory
createSocket()86     public Socket createSocket() {
87         return new Socket();
88     }
89 
90     /**
91      * Attempts to connects the socket to any of the {@link InetAddress}es the
92      * given host name resolves to. If connection to all addresses fail, the
93      * last I/O exception is propagated to the caller.
94      *
95      * @param sock socket to connect to any of the given addresses
96      * @param host Host name to connect to
97      * @param port the port to connect to
98      * @param localAddress local address
99      * @param localPort local port
100      * @param params HTTP parameters
101      *
102      * @throws  IOException if an error occurs during the connection
103      * @throws  SocketTimeoutException if timeout expires before connecting
104      */
connectSocket(Socket sock, String host, int port, InetAddress localAddress, int localPort, HttpParams params)105     public Socket connectSocket(Socket sock, String host, int port,
106                                 InetAddress localAddress, int localPort,
107                                 HttpParams params)
108         throws IOException {
109 
110         if (host == null) {
111             throw new IllegalArgumentException("Target host may not be null.");
112         }
113         if (params == null) {
114             throw new IllegalArgumentException("Parameters may not be null.");
115         }
116 
117         if (sock == null)
118             sock = createSocket();
119 
120         if ((localAddress != null) || (localPort > 0)) {
121 
122             // we need to bind explicitly
123             if (localPort < 0)
124                 localPort = 0; // indicates "any"
125 
126             InetSocketAddress isa =
127                 new InetSocketAddress(localAddress, localPort);
128             sock.bind(isa);
129         }
130 
131         int timeout = HttpConnectionParams.getConnectionTimeout(params);
132 
133         InetAddress[] inetadrs = InetAddress.getAllByName(host);
134         List<InetAddress> addresses = new ArrayList<InetAddress>(inetadrs.length);
135         addresses.addAll(Arrays.asList(inetadrs));
136         Collections.shuffle(addresses);
137 
138         IOException lastEx = null;
139         for (InetAddress address: addresses) {
140             try {
141                 sock.connect(new InetSocketAddress(address, port), timeout);
142                 break;
143             } catch (SocketTimeoutException ex) {
144                 throw ex;
145             } catch (IOException ex) {
146                 // create new socket
147                 sock = new Socket();
148                 // keep the last exception and retry
149                 lastEx = ex;
150             }
151         }
152         if (lastEx != null) {
153             throw lastEx;
154         }
155         return sock;
156     } // connectSocket
157 
158 
159     /**
160      * Checks whether a socket connection is secure.
161      * This factory creates plain socket connections
162      * which are not considered secure.
163      *
164      * @param sock      the connected socket
165      *
166      * @return  <code>false</code>
167      *
168      * @throws IllegalArgumentException if the argument is invalid
169      */
isSecure(Socket sock)170     public final boolean isSecure(Socket sock)
171         throws IllegalArgumentException {
172 
173         if (sock == null) {
174             throw new IllegalArgumentException("Socket may not be null.");
175         }
176         // This class check assumes that createSocket() calls the constructor
177         // directly. If it was using javax.net.SocketFactory, we couldn't make
178         // an assumption about the socket class here.
179         if (sock.getClass() != Socket.class) {
180             throw new IllegalArgumentException
181                 ("Socket not created by this factory.");
182         }
183         // This check is performed last since it calls a method implemented
184         // by the argument object. getClass() is final in java.lang.Object.
185         if (sock.isClosed()) {
186             throw new IllegalArgumentException("Socket is closed.");
187         }
188 
189         return false;
190 
191     } // isSecure
192 
193 
194     /**
195      * Compares this factory with an object.
196      * There is only one instance of this class.
197      *
198      * @param obj       the object to compare with
199      *
200      * @return  iff the argument is this object
201      */
202     @Override
equals(Object obj)203     public boolean equals(Object obj) {
204         return (obj == this);
205     }
206 
207     /**
208      * Obtains a hash code for this object.
209      * All instances of this class have the same hash code.
210      * There is only one instance of this class.
211      */
212     @Override
hashCode()213     public int hashCode() {
214         return PlainSocketFactory.class.hashCode();
215     }
216 
217 }
218