View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.http.conn;
29  
30  import java.io.IOException;
31  import java.net.InetAddress;
32  import java.net.InetSocketAddress;
33  import java.net.Socket;
34  import java.net.SocketTimeoutException;
35  import java.util.ArrayList;
36  import java.util.Arrays;
37  import java.util.Collections;
38  import java.util.List;
39  
40  import org.apache.http.annotation.Contract;
41  import org.apache.http.annotation.ThreadingBehavior;
42  import org.apache.http.conn.scheme.SocketFactory;
43  import org.apache.http.params.HttpConnectionParams;
44  import org.apache.http.params.HttpParams;
45  import org.apache.http.util.Args;
46  import org.apache.http.util.Asserts;
47  
48  /**
49   * Socket factory that implements a simple multi-home fail-over on connect failure,
50   * provided the same hostname resolves to multiple {@link InetAddress}es. Please note
51   * the {@link #connectSocket(Socket, String, int, InetAddress, int, HttpParams)}
52   * method cannot be reliably interrupted by closing the socket returned by the
53   * {@link #createSocket()} method.
54   *
55   * @since 4.0
56   *
57   * @deprecated (4.1)  Do not use. For multihome support socket factories must implement
58   * {@link org.apache.http.conn.scheme.SchemeSocketFactory} interface.
59   */
60  @Deprecated
61  @Contract(threading = ThreadingBehavior.IMMUTABLE)
62  public final class MultihomePlainSocketFactory implements SocketFactory {
63  
64      /**
65       * The factory singleton.
66       */
67      private static final
68      MultihomePlainSocketFactory DEFAULT_FACTORY = new MultihomePlainSocketFactory();
69  
70      /**
71       * Gets the singleton instance of this class.
72       * @return the one and only plain socket factory
73       */
74      public static MultihomePlainSocketFactory getSocketFactory() {
75          return DEFAULT_FACTORY;
76      }
77  
78      /**
79       * Restricted default constructor.
80       */
81      private MultihomePlainSocketFactory() {
82          super();
83      }
84  
85  
86      // non-javadoc, see interface org.apache.http.conn.SocketFactory
87      @Override
88      public Socket createSocket() {
89          return new Socket();
90      }
91  
92      /**
93       * Attempts to connects the socket to any of the {@link InetAddress}es the
94       * given host name resolves to. If connection to all addresses fail, the
95       * last I/O exception is propagated to the caller.
96       *
97       * @param socket socket to connect to any of the given addresses
98       * @param host Host name to connect to
99       * @param port the port to connect to
100      * @param localAddress local address
101      * @param localPort local port
102      * @param params HTTP parameters
103      *
104      * @throws  IOException if an error occurs during the connection
105      * @throws  SocketTimeoutException if timeout expires before connecting
106      */
107     @Override
108     public Socket connectSocket(final Socket socket, final String host, final int port,
109                                 final InetAddress localAddress, final int localPort,
110                                 final HttpParams params)
111         throws IOException {
112         Args.notNull(host, "Target host");
113         Args.notNull(params, "HTTP parameters");
114 
115         Socket sock = socket;
116         if (sock == null) {
117             sock = createSocket();
118         }
119 
120         if ((localAddress != null) || (localPort > 0)) {
121             final InetSocketAddress isa = new InetSocketAddress(localAddress,
122                     localPort > 0 ? localPort : 0);
123             sock.bind(isa);
124         }
125 
126         final int timeout = HttpConnectionParams.getConnectionTimeout(params);
127 
128         final InetAddress[] inetadrs = InetAddress.getAllByName(host);
129         final List<InetAddress> addresses = new ArrayList<InetAddress>(inetadrs.length);
130         addresses.addAll(Arrays.asList(inetadrs));
131         Collections.shuffle(addresses);
132 
133         IOException lastEx = null;
134         for (final InetAddress remoteAddress: addresses) {
135             try {
136                 sock.connect(new InetSocketAddress(remoteAddress, port), timeout);
137                 break;
138             } catch (final SocketTimeoutException ex) {
139                 throw new ConnectTimeoutException("Connect to " + remoteAddress + " timed out");
140             } catch (final IOException ex) {
141                 // create new socket
142                 sock = new Socket();
143                 // keep the last exception and retry
144                 lastEx = ex;
145             }
146         }
147         if (lastEx != null) {
148             throw lastEx;
149         }
150         return sock;
151     } // connectSocket
152 
153 
154     /**
155      * Checks whether a socket connection is secure.
156      * This factory creates plain socket connections
157      * which are not considered secure.
158      *
159      * @param sock      the connected socket
160      *
161      * @return  {@code false}
162      *
163      * @throws IllegalArgumentException if the argument is invalid
164      */
165     @Override
166     public final boolean isSecure(final Socket sock)
167         throws IllegalArgumentException {
168 
169         Args.notNull(sock, "Socket");
170         // This check is performed last since it calls a method implemented
171         // by the argument object. getClass() is final in java.lang.Object.
172         Asserts.check(!sock.isClosed(), "Socket is closed");
173         return false;
174 
175     } // isSecure
176 
177 }