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-2003 (C) Exoffice Technologies Inc. All Rights Reserved. 42 * 43 * $Id: RmiJmsConnectionStub.java,v 1.20 2003/08/07 13:32:54 tanderson Exp $ 44 * 45 * Date Author Changes 46 * 04/12/2000 jima Created 47 */ 48 package org.exolab.jms.client.rmi; 49 50 import java.rmi.ConnectException; 51 import java.rmi.RemoteException; 52 53 import javax.jms.JMSException; 54 55 import org.apache.commons.logging.Log; 56 import org.apache.commons.logging.LogFactory; 57 58 import org.exolab.jms.client.JmsConnectionStubIfc; 59 import org.exolab.jms.client.JmsErrorCodes; 60 import org.exolab.jms.client.JmsSessionStubIfc; 61 import org.exolab.jms.server.rmi.RemoteJmsServerConnectionIfc; 62 import org.exolab.jms.server.rmi.RemoteJmsServerSessionIfc; 63 64 65 /*** 66 * This class is repsonsible for returning a reference to a remote JMS 67 * connection. If it cannot access get a remote connection then the constructor 68 * will fail with a JMSException 69 * 70 * @version $Revision: 1.20 $ $Date: 2003/08/07 13:32:54 $ 71 * @author <a href="mailto:jima@exoffice.com">Jim Alateras</a> 72 */ 73 public class RmiJmsConnectionStub 74 implements JmsConnectionStubIfc { 75 76 /*** 77 * This is a reference to the remote connection stub that is constructed 78 * during object initialisation. 79 */ 80 protected volatile RemoteJmsServerConnectionIfc _delegate = null; 81 82 /*** 83 * This is a reference to the server stub that created this connection 84 */ 85 protected RmiJmsServerStub _owner = null; 86 87 /*** 88 * Cache a reference to the pinging thread. This thread is used to 89 * determine whether the server is still active 90 */ 91 private PingThread _pinger = null; 92 93 /*** 94 * System property to override the max retries for failed rmi requests. 95 * The default is 10 96 */ 97 public final String MAX_RETRY_PROP = "org.exolab.jms.rmi.retryCount"; 98 99 /*** 100 * System property, which specifies the interval between successive 101 * retries. 102 * The value is specified in milliseconds and defaults to 100ms 103 */ 104 public final String RETRY_INTERVAL_PROP = 105 "org.exolab.jms.rmi.retryInterval"; 106 107 /*** 108 * The logger 109 */ 110 private static final Log _log = 111 LogFactory.getLog(RmiJmsConnectionStub.class); 112 113 114 /*** 115 * Instantiate an instance of this class with the specified remote object. 116 * This object is a delegate for all other requests. If a null connection 117 * is specified then throw a JMSException exception 118 * 119 * @param RemoteJmsServerConnectionIfc 120 * @param pingInterval interval between client pings 121 * @param server the server creating the connection 122 * @throws JMSException 123 */ 124 public RmiJmsConnectionStub(RemoteJmsServerConnectionIfc connection, 125 int pingInterval, RmiJmsServerStub server) 126 throws JMSException { 127 128 if (connection != null) { 129 _owner = server; 130 _delegate = connection; 131 132 // this is used to determine whether or not the server is 133 // active 134 if (pingInterval > 0) { 135 (_pinger = new PingThread(pingInterval)).start(); 136 } 137 } else { 138 throw new JMSException("Cannot instantiate with a null " + 139 "connection"); 140 } 141 } 142 143 // implementation of JmsConnectionStubIfc.createSession 144 public JmsSessionStubIfc createSession(int ackMode, boolean transacted) 145 throws JMSException { 146 RmiJmsSessionStub stub = null; 147 try { 148 RemoteJmsServerSessionIfc session = _delegate.createSession( 149 ackMode, transacted); 150 stub = new RmiJmsSessionStub(session); 151 session.setMessageListener(stub); 152 153 } catch (RemoteException exception) { 154 // rethrow as a JMSException 155 throw new JMSException("Failed to createSession " + exception); 156 } 157 158 return stub; 159 } 160 161 // implementation of JmsConnectionStubIfc.close 162 public void close() throws JMSException { 163 // stop the pinging thread 164 if (_pinger != null) { 165 _pinger.close(); 166 } 167 168 // close the delegate 169 try { 170 _delegate.close(); 171 _delegate = null; 172 } catch (RemoteException exception) { 173 // rethrow as a JMSException 174 throw new JMSException("Failed to close " + exception); 175 } 176 } 177 178 // implementation of JmsConnectionStubIfc.getConnectionId 179 public String getConnectionId() throws JMSException { 180 try { 181 return _delegate.getConnectionId(); 182 } catch (RemoteException exception) { 183 // rethrow as a JMSException 184 throw new JMSException("Failed to getConnectionId " + exception); 185 } 186 } 187 188 // implementation of JmsConnectionStubIfc.destroy 189 public void destroy() { 190 if (_pinger != null) { 191 _pinger.close(); 192 } 193 _delegate = null; 194 _owner = null; 195 } 196 197 /*** 198 * This thread is used to send ping requests to the server. The server uses 199 * these requests to determine whether a client has disconnected. 200 * The frequency of these requests is determined by the server. 201 */ 202 private class PingThread extends Thread { 203 204 /*** 205 * Maintains the interval at which ping requests are generated to the 206 * server. The value is in seconds 207 */ 208 private int _interval; 209 210 /*** 211 * The maximum no. of times to retry failed pings 212 */ 213 private int _retries; 214 215 /*** 216 * The interval between retrying failed pings 217 */ 218 private int _retryInterval; 219 220 /*** 221 * Determines if the thread should stop 222 */ 223 private volatile boolean _stop = false; 224 225 226 /*** 227 * Instantiate a daemon thread that will be used to periodically send 228 * ping requests to the server at the specified interval 229 * 230 * @param interval the interval between ping requests in seconds 231 */ 232 PingThread(int interval) { 233 _interval = interval; 234 setName("PingThread-" + Math.abs(hashCode())); 235 setDaemon(true); 236 237 _retries = getProperty(MAX_RETRY_PROP, 10, 1); 238 _retryInterval = getProperty(RETRY_INTERVAL_PROP, 100, 100); 239 } 240 241 /*** 242 * This will run forever generating ping requests to the clients 243 */ 244 public void run() { 245 while (!_stop) { 246 if (ping()) { 247 // sleep for the specified interval 248 try { 249 Thread.currentThread().sleep(_interval * 1000); 250 } catch (InterruptedException ignore) { 251 } 252 } else { 253 // the server is no longer available so notify the 254 // client 255 try { 256 JMSException error = new JMSException( 257 "Connection to server terminated", 258 JmsErrorCodes.CONNECTION_TO_SERVER_DROPPED); 259 _log.warn("Server is not responding. " 260 + "Generating onException", 261 error); 262 _owner.getExceptionListener().onException(error); 263 } catch (Throwable ignore) { 264 } 265 break; 266 } 267 } 268 } 269 270 public void close() { 271 _stop = true; 272 try { 273 interrupt(); 274 } catch (SecurityException ignore) { 275 } 276 } 277 278 private boolean ping() { 279 boolean successful = false; 280 281 // send the ping request. We need to wrap this up in a 282 // retry loop to cater for a ConnectException that happens 283 // when the server is busy or out of resources. 284 RemoteJmsServerConnectionIfc delegate = _delegate; 285 if (delegate != null) { 286 int count = 0; 287 while ((count < _retries) && !successful && !_stop) { 288 try { 289 delegate.ping(); 290 successful = true; 291 } catch (RemoteException exception) { 292 _log.warn("Failed to ping openjms server. " 293 + "Retry count=" + count, exception); 294 if ((exception.detail instanceof ConnectException) && 295 (count < _retries - 1)) { 296 // underlying exception is connection 297 // related...let's retry the request after sleeping 298 try { 299 Thread.sleep(_retryInterval); 300 } catch (InterruptedException ignore) { 301 } 302 } 303 } catch (Throwable exception) { 304 // print the exception but continue 305 _log.warn("Exception pinging server", exception); 306 } 307 ++count; 308 } 309 } 310 return successful; 311 } 312 313 private int getProperty(String name, int defaultValue, int minimum) { 314 int result = defaultValue; 315 String value = null; 316 try { 317 value = System.getProperty(name); 318 } catch (SecurityException ignore) { 319 } 320 321 if (value != null) { 322 try { 323 result = Integer.parseInt(value); 324 if (result <= minimum) { 325 result = minimum; 326 } 327 } catch (NumberFormatException ignore) { 328 // keep the default 329 } 330 } 331 return result; 332 } 333 334 } //-- PingThread 335 336 } //-- RmiJmsConnectionStub

This page was automatically generated by Maven