Source code: com/mysql/jdbc/StandardSocketFactory.java
1 /*
2 Copyright (C) 2002-2004 MySQL AB
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of version 2 of the GNU General Public License as
6 published by the Free Software Foundation.
7
8
9 There are special exceptions to the terms and conditions of the GPL
10 as it is applied to this software. View the full text of the
11 exception exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
12 software distribution.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23 */
24 package com.mysql.jdbc;
25
26 import java.io.IOException;
27
28 import java.lang.reflect.Constructor;
29 import java.lang.reflect.Method;
30
31 import java.net.Socket;
32 import java.net.SocketException;
33
34 import java.util.Properties;
35
36
37 /**
38 * Socket factory for vanilla TCP/IP sockets (the standard)
39 *
40 * @author Mark Matthews
41 */
42 public class StandardSocketFactory implements SocketFactory {
43 /** The underlying TCP/IP socket to use */
44 protected Socket rawSocket = null;
45
46 /** The hostname to connect to */
47 protected String host = null;
48
49 /** The port number to connect to */
50 protected int port = 3306;
51
52 /**
53 * Called by the driver after issuing the MySQL protocol handshake and
54 * reading the results of the handshake.
55 *
56 * @return The socket to use after the handshake
57 *
58 * @throws SocketException if a socket error occurs
59 * @throws IOException if an I/O error occurs
60 */
61 public Socket afterHandshake() throws SocketException, IOException {
62 return rawSocket;
63 }
64
65 /**
66 * Called by the driver before issuing the MySQL protocol handshake. Should
67 * return the socket instance that should be used during the handshake.
68 *
69 * @return the socket to use before the handshake
70 *
71 * @throws SocketException if a socket error occurs
72 * @throws IOException if an I/O error occurs
73 */
74 public Socket beforeHandshake() throws SocketException, IOException {
75 return rawSocket;
76 }
77
78 /**
79 * @see com.mysql.jdbc.SocketFactory#createSocket(Properties)
80 */
81 public Socket connect(String host, int portNumber, Properties props)
82 throws SocketException, IOException {
83 if (props != null) {
84 this.host = host;
85
86 this.port = portNumber;
87
88 boolean hasConnectTimeoutMethod = false;
89
90 Method connectWithTimeoutMethod = null;
91
92 try {
93 // Have to do this with reflection, otherwise older JVMs croak
94 Class socketAddressClass = Class.forName(
95 "java.net.SocketAddress");
96
97 connectWithTimeoutMethod = Socket.class.getMethod("connect",
98 new Class[] { socketAddressClass, Integer.TYPE });
99
100 hasConnectTimeoutMethod = true;
101 } catch (NoClassDefFoundError noClassDefFound) {
102 hasConnectTimeoutMethod = false;
103 } catch (NoSuchMethodException noSuchMethodEx) {
104 hasConnectTimeoutMethod = false;
105 } catch (Throwable catchAll) {
106 hasConnectTimeoutMethod = false;
107 }
108
109 int connectTimeout = 0;
110
111 String connectTimeoutStr = props.getProperty("connectTimeout");
112
113 if (connectTimeoutStr != null) {
114 try {
115 connectTimeout = Integer.parseInt(connectTimeoutStr);
116 } catch (NumberFormatException nfe) {
117 throw new SocketException("Illegal value '"
118 + connectTimeoutStr + "' for connectTimeout");
119 }
120 }
121
122 if (this.host != null) {
123 if (!hasConnectTimeoutMethod || (connectTimeout == 0)) {
124 rawSocket = new Socket(this.host, port);
125 } else {
126 // must explicitly state this due to classloader issues
127 // when running on older JVMs :(
128 try {
129 Class inetSocketAddressClass = Class.forName(
130 "java.net.InetSocketAddress");
131 Constructor addrConstructor = inetSocketAddressClass
132 .getConstructor(new Class[] {
133 String.class, Integer.TYPE
134 });
135
136 Object sockAddr = addrConstructor.newInstance(new Object[] {
137 this.host, new Integer(port)
138 });
139
140 rawSocket = new Socket();
141 connectWithTimeoutMethod.invoke(rawSocket,
142 new Object[] { sockAddr, new Integer(connectTimeout) });
143 } catch (Throwable t) {
144 if (t != null) {
145 throw new SocketException(t.toString());
146 } else {
147 throw new SocketException(
148 "General Socket Exception");
149 }
150 }
151 }
152
153 try {
154 rawSocket.setTcpNoDelay(true);
155 } catch (Exception ex) {
156 /* Ignore */
157 }
158
159 return rawSocket;
160 }
161 }
162
163 throw new SocketException("Unable to create socket");
164 }
165 }