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.Immutable;
41  import org.apache.http.conn.scheme.SocketFactory;
42  import org.apache.http.params.HttpConnectionParams;
43  import org.apache.http.params.HttpParams;
44  import org.apache.http.util.Args;
45  import org.apache.http.util.Asserts;
46  
47  /**
48   * Socket factory that implements a simple multi-home fail-over on connect failure,
49   * provided the same hostname resolves to multiple {@link InetAddress}es. Please note
50   * the {@link #connectSocket(Socket, String, int, InetAddress, int, HttpParams)}
51   * method cannot be reliably interrupted by closing the socket returned by the
52   * {@link #createSocket()} method.
53   *
54   * @since 4.0
55   *
56   * @deprecated (4.1)  Do not use. For multihome support socket factories must implement
57   * {@link org.apache.http.conn.scheme.SchemeSocketFactory} interface.
58   */
59  @Deprecated
60  @Immutable
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       */
73      public static MultihomePlainSocketFactory getSocketFactory() {
74          return DEFAULT_FACTORY;
75      }
76  
77      /**
78       * Restricted default constructor.
79       */
80      private MultihomePlainSocketFactory() {
81          super();
82      }
83  
84  
85      // non-javadoc, see interface org.apache.http.conn.SocketFactory
86      @Override
87      public Socket createSocket() {
88          return new Socket();
89      }
90  
91      /**
92       * Attempts to connects the socket to any of the {@link InetAddress}es the
93       * given host name resolves to. If connection to all addresses fail, the
94       * last I/O exception is propagated to the caller.
95       *
96       * @param socket socket to connect to any of the given addresses
97       * @param host Host name to connect to
98       * @param port the port to connect to
99       * @param localAddress local address
100      * @param localPort local port
101      * @param params HTTP parameters
102      *
103      * @throws  IOException if an error occurs during the connection
104      * @throws  SocketTimeoutException if timeout expires before connecting
105      */
106     @Override
107     public Socket connectSocket(final Socket socket, final String host, final int port,
108                                 final InetAddress localAddress, final int localPort,
109                                 final HttpParams params)
110         throws IOException {
111         Args.notNull(host, "Target host");
112         Args.notNull(params, "HTTP parameters");
113 
114         Socket sock = socket;
115         if (sock == null) {
116             sock = createSocket();
117         }
118 
119         if ((localAddress != null) || (localPort > 0)) {
120             final InetSocketAddress isa = new InetSocketAddress(localAddress,
121                     localPort > 0 ? localPort : 0);
122             sock.bind(isa);
123         }
124 
125         final int timeout = HttpConnectionParams.getConnectionTimeout(params);
126 
127         final InetAddress[] inetadrs = InetAddress.getAllByName(host);
128         final List<InetAddress> addresses = new ArrayList<InetAddress>(inetadrs.length);
129         addresses.addAll(Arrays.asList(inetadrs));
130         Collections.shuffle(addresses);
131 
132         IOException lastEx = null;
133         for (final InetAddress remoteAddress: addresses) {
134             try {
135                 sock.connect(new InetSocketAddress(remoteAddress, port), timeout);
136                 break;
137             } catch (final SocketTimeoutException ex) {
138                 throw new ConnectTimeoutException("Connect to " + remoteAddress + " timed out");
139             } catch (final IOException ex) {
140                 // create new socket
141                 sock = new Socket();
142                 // keep the last exception and retry
143                 lastEx = ex;
144             }
145         }
146         if (lastEx != null) {
147             throw lastEx;
148         }
149         return sock;
150     } // connectSocket
151 
152 
153     /**
154      * Checks whether a socket connection is secure.
155      * This factory creates plain socket connections
156      * which are not considered secure.
157      *
158      * @param sock      the connected socket
159      *
160      * @return  {@code false}
161      *
162      * @throws IllegalArgumentException if the argument is invalid
163      */
164     @Override
165     public final boolean isSecure(final Socket sock)
166         throws IllegalArgumentException {
167 
168         Args.notNull(sock, "Socket");
169         // This check is performed last since it calls a method implemented
170         // by the argument object. getClass() is final in java.lang.Object.
171         Asserts.check(!sock.isClosed(), "Socket is closed");
172         return false;
173 
174     } // isSecure
175 
176 }