1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2004-2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: SocketManagedConnection.java,v 1.5 2006/12/16 12:37:17 tanderson Exp $
44 */
45 package org.exolab.jms.net.socket;
46
47 import java.io.IOException;
48 import java.net.Socket;
49 import java.security.Principal;
50
51 import org.apache.commons.logging.Log;
52 import org.apache.commons.logging.LogFactory;
53
54 import org.exolab.jms.net.connector.Authenticator;
55 import org.exolab.jms.net.connector.ConnectException;
56 import org.exolab.jms.net.connector.ResourceException;
57 import org.exolab.jms.net.multiplexer.Endpoint;
58 import org.exolab.jms.net.multiplexer.MultiplexedManagedConnection;
59 import org.exolab.jms.net.uri.InvalidURIException;
60 import org.exolab.jms.net.uri.URI;
61 import org.exolab.jms.net.uri.URIHelper;
62
63
64 /***
65 * <code>SocketManagedConnection</code> manages multiple <code>Connection</code>
66 * instances over a single socket.
67 *
68 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
69 * @version $Revision: 1.5 $ $Date: 2006/12/16 12:37:17 $
70 */
71 public abstract class SocketManagedConnection
72 extends MultiplexedManagedConnection {
73
74 /***
75 * The underlying socket.
76 */
77 private Socket _socket;
78
79 /***
80 * The remote address to which this is connected.
81 */
82 private URI _remoteURI;
83
84 /***
85 * The the local address that this connection is bound to.
86 */
87 private URI _localURI;
88
89 /***
90 * The alternative URI that the remote address is known as.
91 */
92 private URI _alternativeURI;
93
94 /***
95 * The logger.
96 */
97 protected static final Log _log =
98 LogFactory.getLog(SocketManagedConnection.class);
99
100 /***
101 * Construct a new client <code>SocketManagedConnection</code>.
102 *
103 * @param principal the security principal
104 * @param info the connection request info
105 * @throws ResourceException if a socket cannot be created
106 */
107 public SocketManagedConnection(Principal principal,
108 SocketRequestInfo info)
109 throws ResourceException {
110 super(principal);
111 if (info == null) {
112 throw new IllegalArgumentException("Argument 'info' is null");
113 }
114 Socket socket = createSocket(info);
115 init(info.getURI(), socket);
116 }
117
118 /***
119 * Construct a new server <code>SocketManagedConnection</code>.
120 *
121 * @param uri the URI the acceptor was listening on
122 * @param socket the socket
123 * @param authenticator the connection authenticator
124 * @throws ResourceException if an error occurs accessing the socket
125 */
126 public SocketManagedConnection(URI uri, Socket socket,
127 Authenticator authenticator)
128 throws ResourceException {
129 super(authenticator);
130 if (uri == null) {
131 throw new IllegalArgumentException("Argument 'uri' is null");
132 }
133 if (socket == null) {
134 throw new IllegalArgumentException("Argument 'socket' is null");
135 }
136 if (authenticator == null) {
137 throw new IllegalArgumentException(
138 "Argument 'authenticator' is null");
139 }
140 init(uri, socket);
141 }
142
143 /***
144 * Returns the remote address to which this is connected.
145 *
146 * @return the remote address to which this is connected
147 */
148 public URI getRemoteURI() {
149 return _remoteURI;
150 }
151
152 /***
153 * Returns the local address that this connection is bound to.
154 *
155 * @return the local address that this connection is bound to
156 */
157 public URI getLocalURI() {
158 return _localURI;
159 }
160
161 /***
162 * The alternative URI that the remote address is known as.
163 *
164 * @return alternative URI that the remote address is known as.
165 * May be <code>null</code>.
166 */
167 public URI getAlternativeURI() {
168 return _alternativeURI;
169 }
170
171 /***
172 * Creates a new socket.
173 *
174 * @param info the connection request info
175 * @return a new socket
176 * @throws ResourceException if a socket can't be created
177 */
178 protected Socket createSocket(SocketRequestInfo info)
179 throws ResourceException {
180 Socket result;
181 try {
182 result = createSocketProtected(info.getHost(), info.getPort());
183 _alternativeURI = info.getAlternativeURI();
184 } catch (ResourceException exception) {
185 _alternativeURI = info.getURI();
186 URI uri = info.getAlternativeURI();
187 if (uri == null) {
188 throw exception;
189 }
190 if (_log.isDebugEnabled()) {
191 _log.debug("Failed to connect using URI=" + info.getURI()
192 + ", attempting URI=" + uri);
193 }
194 result = createSocketProtected(uri.getHost(), uri.getPort());
195 }
196 return result;
197 }
198
199 /***
200 * Creates a new socket.
201 *
202 * @param host the host to connect to
203 * @param port the port to connect to
204 * @return a new socket
205 * @throws IOException for any I/O error
206 * @throws SecurityException if permission is denied
207 */
208 protected Socket createSocket(String host, int port) throws IOException {
209 Socket socket = new Socket(host, port);
210 socket.setTcpNoDelay(true);
211 return socket;
212 }
213
214 /***
215 * Returns the endpoint to multiplex data over.
216 *
217 * @return the endpoint to multiplex data over
218 * @throws IOException for any I/O error
219 */
220 protected Endpoint createEndpoint() throws IOException {
221 return new SocketEndpoint(_remoteURI.getScheme(), _socket);
222 }
223
224 /***
225 * Initialises this connection.
226 *
227 * @param uri the URI representing this connection
228 * @param socket the socket
229 * @throws ResourceException for any error
230 */
231 protected void init(URI uri, Socket socket) throws ResourceException {
232 _socket = socket;
233 try {
234 String localHost = socket.getLocalAddress().getHostAddress();
235 int localPort = socket.getLocalPort();
236 _localURI = URIHelper.create(uri.getScheme(), localHost, localPort);
237
238 String remoteHost = socket.getInetAddress().getHostAddress();
239 int remotePort = socket.getPort();
240 _remoteURI = URIHelper.create(uri.getScheme(), remoteHost,
241 remotePort);
242 } catch (InvalidURIException exception) {
243 throw new ResourceException("Failed to create URI", exception);
244 }
245 }
246
247 /***
248 * Creates a new socket, adapting exceptions to instances of
249 * ResourceException.
250 * <p/>
251 * This adapts java.net.ConnectException to ConnectException and
252 * all other exceptions (including SecurityExceptions) to
253 * to an instance of ResourceException.
254 *
255 * @param host the host to connect to
256 * @param port the port to connect to
257 * @return a new socket
258 * @throws ResourceException if the socket can't be created
259 */
260 private Socket createSocketProtected(String host, int port)
261 throws ResourceException {
262 try {
263 return createSocket(host, port);
264 } catch (Exception exception) {
265 String msg = "Failed to connect to " + host + ":" + port;
266 _log.debug(msg, exception);
267 if (exception instanceof java.net.ConnectException) {
268 throw new ConnectException(msg, exception);
269 }
270 throw new ResourceException(msg, exception);
271 }
272 }
273
274
275 }