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