View Javadoc
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 2000-2004 (C) Exoffice Technologies Inc. All Rights Reserved. 42 * 43 * $Id: IpcJmsServerStub.java,v 1.19 2004/01/20 14:11:36 tanderson Exp $ 44 */ 45 46 package org.exolab.jms.client.mipc; 47 48 import java.io.IOException; 49 import java.util.HashSet; 50 import java.util.Hashtable; 51 import java.util.Vector; 52 53 import javax.jms.ExceptionListener; 54 import javax.jms.JMSException; 55 import javax.jms.JMSSecurityException; 56 57 import org.apache.commons.logging.Log; 58 import org.apache.commons.logging.LogFactory; 59 60 import org.exolab.core.ipc.IpcIfc; 61 import org.exolab.core.mipc.DisconnectionEventListener; 62 import org.exolab.core.mipc.MultiplexConnection; 63 import org.exolab.core.mipc.MultiplexConnectionIfc; 64 import org.exolab.core.mipc.ObjectChannel; 65 import org.exolab.core.mipc.TcpConstants; 66 import org.exolab.jms.client.JmsConnectionStubIfc; 67 import org.exolab.jms.client.JmsErrorCodes; 68 import org.exolab.jms.client.JmsServerStubIfc; 69 70 71 /*** 72 * This class is repsonsible for opening an ipc connection to the server 73 * and creating IpcJmsConnections. 74 * 75 * @version $Revision: 1.19 $ $Date: 2004/01/20 14:11:36 $ 76 * @author <a href="mailto:mourikis@exolab.org">Jim Mourikis</a> 77 * @see org.exolab.jms.client.mipc.IpcJmsConnectionStub 78 * @see org.exolab.core.mipc.DisconnectionEventListener 79 **/ 80 public class IpcJmsServerStub 81 implements JmsServerStubIfc, DisconnectionEventListener { 82 83 /*** 84 * The multiplex connection to the server 85 */ 86 private MultiplexConnectionIfc _mc = null; 87 88 /*** 89 * The server channel 90 */ 91 private IpcIfc _connection = null; 92 93 /*** 94 * The server host address 95 */ 96 private String _serverAddress = TcpConstants.LOCAL_HOST; 97 98 /*** 99 * The internal server host address if OpenJMS server is serving both 100 * internet connections behind a NAT router and internal connections. 101 */ 102 private String _internalServerAddress = null; 103 104 /*** 105 * The port number the server is listening to 106 */ 107 private int _port = TcpConstants.DEFAULT_PORT; 108 109 /*** 110 * The set of open IpcJmsConnectionStub instances 111 */ 112 private HashSet _connections = new HashSet(); 113 114 /*** 115 * The message dispatcher 116 */ 117 private IpcJmsMessageListener _listener; 118 119 /*** 120 * The exception listener is used to communicate server connection 121 * problems 122 */ 123 private ExceptionListener _exceptionListener = null; 124 125 /*** 126 * The logger 127 */ 128 private static final Log _log = LogFactory.getLog(IpcJmsServerStub.class); 129 130 131 /*** 132 * Default constructor for serialization 133 */ 134 public IpcJmsServerStub() { 135 } 136 137 /*** 138 * The constructor has a collection of environment variables 139 * which it uses to construct a connection to the remote 140 * server 141 * 142 * @param env 143 */ 144 public IpcJmsServerStub(Hashtable env) { 145 if (env.containsKey(IpcJmsConstants.IPC_SERVER_HOST)) { 146 _serverAddress = (String) env.get(IpcJmsConstants.IPC_SERVER_HOST); 147 } 148 if (env.containsKey(IpcJmsConstants.IPC_INTERNAL_SERVER_HOST)) { 149 _internalServerAddress = (String) env.get 150 (IpcJmsConstants.IPC_INTERNAL_SERVER_HOST); 151 } 152 153 if (env.containsKey(IpcJmsConstants.IPC_SERVER_PORT)) { 154 try { 155 _port = Integer.parseInt((String) env.get( 156 IpcJmsConstants.IPC_SERVER_PORT)); 157 } catch (NumberFormatException exception) { 158 // failure to convert exception use the 159 // default port 160 _log.warn("Server port is not a valid format." 161 + " Defaulting to " + _port); 162 } 163 } 164 } 165 166 /*** 167 * Instantiate an instance of this stub with the specified host and 168 * port numbers 169 * 170 * @param host server host address 171 * @param port server port number 172 */ 173 public IpcJmsServerStub(String host, int port) { 174 if ((host != null) && 175 (host.length() > 0)) { 176 _serverAddress = host; 177 } 178 179 _port = port; 180 } 181 182 /*** 183 * Create a connection to the JMS Server. A new connectionId will be 184 * returned if the connection is successful. Create a new IpcJmsConnection 185 * object with the given id's. 186 * 187 * @param clientId the identity of client 188 * @param username the client username 189 * @param password the client password 190 * @throws JMSException 191 */ 192 public synchronized JmsConnectionStubIfc createConnection( 193 String clientId, String username, String password) 194 throws JMSException { 195 JmsConnectionStubIfc stub = null; 196 197 openConnection(); 198 try { 199 String connectionId; 200 Vector v = pack("createConnection", clientId, username, password); 201 synchronized (_connection) { 202 _connection.send(v); 203 connectionId = (String) checkReply("createConnection"); 204 } 205 206 stub = new IpcJmsConnectionStub( 207 this, _connection, clientId, connectionId, _listener); 208 _connections.add(stub); 209 } catch (JMSException exception) { 210 throw exception; 211 } catch (Exception exception) { 212 JMSException error = new JMSException( 213 "Failed to create connection"); 214 error.setLinkedException(exception); 215 throw error; 216 } 217 return stub; 218 } 219 220 /*** 221 * Set the server host. This is the host that the server runs on 222 * 223 * @param host the name of the host 224 */ 225 public void setServerAddress(String host) { 226 _serverAddress = host; 227 } 228 229 /*** 230 * Returns the server host 231 * 232 * @return the server host 233 */ 234 public String getServerAddress() { 235 return _serverAddress; 236 } 237 238 /*** 239 * Set the server port. This is the port that the server runs on 240 * 241 * @param port the server port number 242 */ 243 public void setServerPort(int port) { 244 _port = port; 245 } 246 247 /*** 248 * Returns the server port 249 * 250 * @return the server port 251 */ 252 public int getServerPort() { 253 return _port; 254 } 255 256 // implementation of DisconnectionEventListener.disconnected 257 public void disconnected(MultiplexConnectionIfc connection) { 258 close(); 259 260 // notify the exception listener if one is registered 261 if (_exceptionListener != null) { 262 JMSException exception = new JMSException( 263 "Connection to server terminated", 264 JmsErrorCodes.CONNECTION_TO_SERVER_DROPPED); 265 _exceptionListener.onException(exception); 266 } 267 } 268 269 // implementation of JmsServerStubIfc.setExceptionListener 270 public void setExceptionListener(ExceptionListener listener) { 271 _exceptionListener = listener; 272 } 273 274 public synchronized void close() { 275 // local clean up 276 try { 277 if (_connection != null) { 278 _connection.close(); 279 _listener.stop(); 280 _mc.finish(); 281 } 282 } catch (Exception exception) { 283 // just swallow :-) 284 } finally { 285 _mc = null; 286 _connection = null; 287 _listener = null; 288 } 289 } 290 291 public synchronized void closed(IpcJmsConnectionStub connection) { 292 _connections.remove(connection); 293 if (_connections.isEmpty()) { 294 close(); 295 } 296 } 297 298 /*** 299 * Create a multiplexed connection to the server 300 * 301 * @param serverAddress the address of the server 302 * @param internalServerAddress internal server address. May be null. 303 * @param port the port number to use 304 * @return the connection to the server 305 * @throws IOException if the connection cannot be established 306 */ 307 protected MultiplexConnectionIfc createClientConnection( 308 String serverAddress, String internalServerAddress, int port) 309 throws Exception { 310 311 MultiplexConnectionIfc result = null; 312 313 try { 314 result = new MultiplexConnection(serverAddress, port); 315 } catch (IOException exception) { 316 if (internalServerAddress != null) { 317 result = new MultiplexConnection(internalServerAddress, port); 318 } else { 319 // just rethrow it. 320 throw exception; 321 } 322 } 323 return result; 324 } 325 326 /*** 327 * Check to see if an ipc connection has been created. If not, connect with 328 * the given hostname and port number. 329 * 330 * @throws JMSException if a connection cannot be established 331 */ 332 private synchronized void openConnection() throws JMSException { 333 if (_mc == null) { 334 try { 335 _mc = createClientConnection( 336 _serverAddress, _internalServerAddress, _port); 337 } catch (Exception exception) { 338 throw new JMSException( 339 "Failed to create connection: " + exception); 340 } 341 342 _mc.setDisconnectionEventListener(this); 343 ((Thread) _mc).start(); 344 345 _connection = new ObjectChannel("server", _mc); 346 _listener = new IpcJmsMessageListener(_mc); 347 } 348 } 349 350 /*** 351 * A convenience method to check the success of operations which return 352 * a true on sucess. 353 * 354 * @param method The requested server function. 355 * @return the result of the call, or <code>null</code> if the call 356 * didn't return a result 357 * @throws JMSException for any failure. 358 */ 359 private Object checkReply(String method) throws JMSException { 360 Object result = null; 361 Vector v = null; 362 try { 363 v = (Vector) _connection.receive(); 364 } catch (Exception err) { 365 // rethrow as a JMSException 366 throw new JMSException("Operation " + method + " failed: " + err); 367 } 368 369 if (v != null) { 370 Boolean b = (Boolean) v.get(0); 371 if (!b.booleanValue()) { 372 if (v.get(1) instanceof JMSException) { 373 throw (JMSException) v.get(1); 374 } else { 375 throw new JMSException("Operation " + method + 376 " failed:\n" + v.get(1)); 377 } 378 } 379 result = v.get(1); 380 } else { 381 throw new JMSException("Unknown connection error for " + method); 382 } 383 384 return result; 385 } 386 387 /*** 388 * Pack all the data that is required by the server in a vector. 389 * Set the size of the vector to be exactly the right size for efficiency. 390 * 391 * @param method the function to invoke on the server. 392 * @param id the unique client id. 393 * @param username the client username 394 * @param password the client password 395 * @return Vector The vector containing all the data. 396 */ 397 private Vector pack(String method, String id, String username, 398 String password) { 399 Vector v = new Vector(5); 400 v.add("org.exolab.jms.server.mipc.IpcJmsServerConnection"); 401 v.add(method); 402 v.add(id); 403 v.add(username); 404 v.add(password); 405 return v; 406 } 407 408 }

This page was automatically generated by Maven