/* */ package org.jboss.remoting.transport.bisocket;
/* */
/* */ import EDU.oswego.cs.dl.util.concurrent.Semaphore;
/* */ import java.io.IOException;
/* */ import java.io.OutputStream;
/* */ import java.net.Socket;
/* */ import java.util.Collections;
/* */ import java.util.HashMap;
/* */ import java.util.HashSet;
/* */ import java.util.Iterator;
/* */ import java.util.LinkedList;
/* */ import java.util.Map;
/* */ import java.util.Set;
/* */ import java.util.Timer;
/* */ import java.util.TimerTask;
/* */ import org.jboss.logging.Logger;
/* */ import org.jboss.remoting.ConnectionFailedException;
/* */ import org.jboss.remoting.InvocationRequest;
/* */ import org.jboss.remoting.InvokerLocator;
/* */ import org.jboss.remoting.invocation.InternalInvocation;
/* */ import org.jboss.remoting.marshal.Marshaller;
/* */ import org.jboss.remoting.marshal.UnMarshaller;
/* */ import org.jboss.remoting.transport.BidirectionalClientInvoker;
/* */ import org.jboss.remoting.transport.socket.SocketClientInvoker;
/* */ import org.jboss.remoting.transport.socket.SocketWrapper;
/* */
/* */ public class BisocketClientInvoker extends SocketClientInvoker
/* */ implements BidirectionalClientInvoker
/* */ {
/* 73 */ private static final Logger log = Logger.getLogger(BisocketClientInvoker.class);
/* 74 */ private static Map listenerIdToClientInvokerMap = Collections.synchronizedMap(new HashMap());
/* 75 */ private static Map listenerIdToCallbackClientInvokerMap = Collections.synchronizedMap(new HashMap());
/* 76 */ private static Map listenerIdToSocketsMap = new HashMap();
/* 77 */ private static Map listenerIdToControlSocketsMap = new HashMap();
/* */ private static Timer timer;
/* 79 */ private static Object timerLock = new Object();
/* */ protected String listenerId;
/* 83 */ private int pingFrequency = 5000;
/* 84 */ private int maxRetries = 10;
/* */ private Socket controlSocket;
/* */ private OutputStream controlOutputStream;
/* 87 */ private Object controlLock = new Object();
/* */ private PingTimerTask pingTimerTask;
/* */ protected boolean isCallbackInvoker;
/* */
/* */ static BisocketClientInvoker getBisocketClientInvoker(String listenerId)
/* */ {
/* 98 */ return (BisocketClientInvoker)listenerIdToClientInvokerMap.get(listenerId);
/* */ }
/* */
/* */ static BisocketClientInvoker getBisocketCallbackClientInvoker(String listenerId)
/* */ {
/* 104 */ return (BisocketClientInvoker)listenerIdToCallbackClientInvokerMap.get(listenerId);
/* */ }
/* */
/* */ static void removeBisocketClientInvoker(String listenerId)
/* */ {
/* 110 */ listenerIdToClientInvokerMap.remove(listenerId);
/* */ }
/* */
/* */ static void transferSocket(String listenerId, Socket socket, boolean isControlSocket)
/* */ {
/* 116 */ Set sockets = null;
/* */
/* 118 */ if (isControlSocket)
/* */ {
/* 120 */ synchronized (listenerIdToControlSocketsMap)
/* */ {
/* 122 */ sockets = (Set)listenerIdToControlSocketsMap.get(listenerId);
/* 123 */ if (sockets == null)
/* */ {
/* 125 */ sockets = new HashSet();
/* 126 */ listenerIdToControlSocketsMap.put(listenerId, sockets);
/* */ }
/* */ }
/* */
/* */ }
/* */
/* 132 */ synchronized (listenerIdToSocketsMap)
/* */ {
/* 134 */ sockets = (Set)listenerIdToSocketsMap.get(listenerId);
/* 135 */ if (sockets == null)
/* */ {
/* 137 */ sockets = new HashSet();
/* 138 */ listenerIdToSocketsMap.put(listenerId, sockets);
/* */ }
/* */
/* */ }
/* */
/* 143 */ synchronized (sockets)
/* */ {
/* 145 */ sockets.add(socket);
/* 146 */ sockets.notify();
/* */ }
/* */ }
/* */
/* */ public BisocketClientInvoker(InvokerLocator locator)
/* */ throws IOException
/* */ {
/* 153 */ this(locator, null);
/* */ }
/* */
/* */ public BisocketClientInvoker(InvokerLocator locator, Map config)
/* */ throws IOException
/* */ {
/* 159 */ super(locator, config);
/* */
/* 161 */ if (this.configuration != null)
/* */ {
/* 163 */ this.listenerId = ((String)this.configuration.get("listenerId"));
/* 164 */ if (this.listenerId != null)
/* */ {
/* 166 */ this.isCallbackInvoker = true;
/* 167 */ listenerIdToCallbackClientInvokerMap.put(this.listenerId, this);
/* 168 */ log.debug(this + " :registered " + this.listenerId + " -> " + this);
/* */ }
/* */
/* 172 */ Object val = this.configuration.get("pingFrequency");
/* 173 */ if (val != null)
/* */ {
/* */ try
/* */ {
/* 177 */ int nVal = Integer.valueOf((String)val).intValue();
/* 178 */ this.pingFrequency = nVal;
/* 179 */ log.debug("Setting ping frequency to: " + this.pingFrequency);
/* */ }
/* */ catch (Exception e)
/* */ {
/* 183 */ log.warn("Could not convert pingFrequency value of " + val + " to an int value.");
/* */ }
/* */
/* */ }
/* */
/* 188 */ val = this.configuration.get("maxRetries");
/* 189 */ if (val != null)
/* */ {
/* */ try
/* */ {
/* 193 */ int nVal = Integer.valueOf((String)val).intValue();
/* 194 */ this.maxRetries = nVal;
/* 195 */ log.debug("Setting retry limit: " + this.maxRetries);
/* */ }
/* */ catch (Exception e)
/* */ {
/* 199 */ log.warn("Could not convert maxRetries value of " + val + " to an int value.");
/* */ }
/* */ }
/* */ }
/* */ }
/* */
/* */ public int getMaxRetries()
/* */ {
/* 208 */ return this.maxRetries;
/* */ }
/* */
/* */ public void setMaxRetries(int maxRetries)
/* */ {
/* 214 */ this.maxRetries = maxRetries;
/* */ }
/* */
/* */ public int getPingFrequency()
/* */ {
/* 220 */ return this.pingFrequency;
/* */ }
/* */
/* */ public void setPingFrequency(int pingFrequency)
/* */ {
/* 226 */ this.pingFrequency = pingFrequency;
/* */ }
/* */
/* */ protected void handleConnect()
/* */ throws ConnectionFailedException
/* */ {
/* 233 */ if (this.isCallbackInvoker)
/* */ {
/* 235 */ Set sockets = null;
/* */
/* 237 */ synchronized (listenerIdToControlSocketsMap)
/* */ {
/* 239 */ sockets = (Set)listenerIdToControlSocketsMap.get(this.listenerId);
/* 240 */ if (sockets == null)
/* */ {
/* 242 */ sockets = new HashSet();
/* 243 */ listenerIdToControlSocketsMap.put(this.listenerId, sockets);
/* */ }
/* */ }
/* */
/* 247 */ synchronized (sockets)
/* */ {
/* 249 */ if (sockets.isEmpty())
/* */ {
/* 251 */ long wait = this.timeout;
/* 252 */ long start = System.currentTimeMillis();
/* */
/* 254 */ while ((this.timeout == 0) || (wait > 0L))
/* */ {
/* */ try
/* */ {
/* 258 */ sockets.wait(wait);
/* */ }
/* */ catch (InterruptedException e)
/* */ {
/* 263 */ log.debug("unexpected interrupt");
/* 264 */ if (this.timeout > 0) {
/* 265 */ wait = this.timeout - (System.currentTimeMillis() - start);
/* */ }
/* */ }
/* */ }
/* */ }
/* 270 */ if (sockets.isEmpty()) {
/* 271 */ throw new ConnectionFailedException("Timed out trying to create control socket");
/* */ }
/* 273 */ Iterator it = sockets.iterator();
/* 274 */ this.controlSocket = ((Socket)it.next());
/* 275 */ it.remove();
/* */ try
/* */ {
/* 278 */ this.controlOutputStream = this.controlSocket.getOutputStream();
/* */ }
/* */ catch (IOException e1)
/* */ {
/* 282 */ throw new ConnectionFailedException("Unable to get control socket output stream");
/* */ }
/* 284 */ log.debug("got control socket( " + this.listenerId + "): " + this.controlSocket);
/* 285 */ this.pingTimerTask = new PingTimerTask(this);
/* */
/* 287 */ synchronized (timerLock)
/* */ {
/* 289 */ if (timer == null)
/* */ {
/* 291 */ timer = new Timer(true);
/* */ }
/* */ try
/* */ {
/* 295 */ timer.schedule(this.pingTimerTask, this.pingFrequency, this.pingFrequency);
/* */ }
/* */ catch (IllegalStateException e)
/* */ {
/* 299 */ log.debug("Unable to schedule TimerTask on existing Timer", e);
/* 300 */ timer = new Timer(true);
/* 301 */ timer.schedule(this.pingTimerTask, this.pingFrequency, this.pingFrequency);
/* */ }
/* */
/* */ }
/* */
/* */ }
/* */
/* 308 */ this.pool = new LinkedList();
/* 309 */ log.debug("Creating semaphore with size " + this.maxPoolSize);
/* 310 */ this.semaphore = new Semaphore(this.maxPoolSize);
/* 311 */ return;
/* */ }
/* */
/* 315 */ super.handleConnect();
/* */ }
/* */
/* */ protected void handleDisconnect()
/* */ {
/* 321 */ if (this.listenerId != null)
/* */ {
/* */ Iterator it;
/* 323 */ if (this.isCallbackInvoker)
/* */ {
/* 325 */ if (this.controlSocket != null)
/* */ {
/* */ try
/* */ {
/* 329 */ this.controlSocket.close();
/* */ }
/* */ catch (IOException e)
/* */ {
/* 333 */ log.debug("unable to close control socket: " + this.controlSocket);
/* */ }
/* */ }
/* */
/* 337 */ listenerIdToCallbackClientInvokerMap.remove(this.listenerId);
/* 338 */ for (it = this.pool.iterator(); it.hasNext(); )
/* */ {
/* 340 */ SocketWrapper socketWrapper = (SocketWrapper)it.next();
/* */ try
/* */ {
/* 343 */ socketWrapper.close();
/* */ }
/* */ catch (Exception ignored)
/* */ {
/* */ }
/* */ }
/* */ }
/* */ else
/* */ {
/* 352 */ listenerIdToClientInvokerMap.remove(this.listenerId);
/* 353 */ super.handleDisconnect();
/* */ }
/* */
/* 356 */ synchronized (listenerIdToControlSocketsMap)
/* */ {
/* 358 */ listenerIdToControlSocketsMap.remove(this.listenerId);
/* */ }
/* */
/* 361 */ Set sockets = null;
/* 362 */ synchronized (listenerIdToSocketsMap)
/* */ {
/* 364 */ sockets = (Set)listenerIdToSocketsMap.remove(this.listenerId);
/* */ }
/* */
/* 368 */ if (sockets != null)
/* */ {
/* 370 */ synchronized (sockets)
/* */ {
/* 372 */ sockets.notifyAll();
/* */ }
/* */ }
/* */
/* 376 */ if (this.pingTimerTask != null)
/* 377 */ this.pingTimerTask.shutDown();
/* */ }
/* */ else
/* */ {
/* 381 */ super.handleDisconnect();
/* */ }
/* */ }
/* */
/* */ protected Object transport(String sessionId, Object invocation, Map metadata, Marshaller marshaller, UnMarshaller unmarshaller)
/* */ throws IOException, ConnectionFailedException, ClassNotFoundException
/* */ {
/* 390 */ String listenerId = null;
/* 391 */ if ((invocation instanceof InvocationRequest))
/* */ {
/* 393 */ InvocationRequest ir = (InvocationRequest)invocation;
/* 394 */ Object o = ir.getParameter();
/* 395 */ if ((o instanceof InternalInvocation))
/* */ {
/* 397 */ InternalInvocation ii = (InternalInvocation)o;
/* 398 */ if (("addListener".equals(ii.getMethodName())) && (ir.getLocator() != null))
/* */ {
/* 401 */ Map requestPayload = ir.getRequestPayload();
/* 402 */ listenerId = (String)requestPayload.get("listenerId");
/* 403 */ listenerIdToClientInvokerMap.put(listenerId, this);
/* */
/* 405 */ BisocketServerInvoker callbackServerInvoker = BisocketServerInvoker.getBisocketServerInvoker(listenerId);
/* 406 */ callbackServerInvoker.createControlConnection(listenerId, true);
/* */ }
/* */
/* */ }
/* */
/* */ }
/* */
/* 417 */ return super.transport(sessionId, invocation, metadata, marshaller, unmarshaller);
/* */ }
/* */
/* */ protected Socket createSocket(String address, int port, int timeout)
/* */ throws IOException
/* */ {
/* 423 */ if (!this.isCallbackInvoker) {
/* 424 */ return super.createSocket(address, port, timeout);
/* */ }
/* 426 */ if (timeout < 0)
/* */ {
/* 428 */ timeout = getTimeout();
/* 429 */ if (timeout < 0) {
/* 430 */ timeout = 0;
/* */ }
/* */ }
/* 433 */ Set sockets = null;
/* */
/* 435 */ synchronized (listenerIdToSocketsMap)
/* */ {
/* 437 */ sockets = (Set)listenerIdToSocketsMap.get(this.listenerId);
/* */
/* 439 */ if (sockets == null)
/* */ {
/* 441 */ sockets = new HashSet();
/* 442 */ listenerIdToSocketsMap.put(this.listenerId, sockets);
/* */ }
/* */ }
/* */
/* 446 */ synchronized (this.controlLock)
/* */ {
/* 448 */ this.controlOutputStream.write(4);
/* */ }
/* */
/* 451 */ synchronized (sockets)
/* */ {
/* 453 */ if (!sockets.isEmpty())
/* */ {
/* 455 */ Iterator it = sockets.iterator();
/* 456 */ Socket socket = (Socket)it.next();
/* 457 */ it.remove();
/* 458 */ log.debug(this + " found socket (" + this.listenerId + "): " + socket);
/* 459 */ return socket;
/* */ }
/* */ }
/* */
/* 463 */ long timeRemaining = timeout;
/* 464 */ long start = System.currentTimeMillis();
/* */
/* 466 */ while ((isConnected()) && ((timeout == 0) || (timeRemaining > 0L)))
/* */ {
/* 468 */ synchronized (sockets)
/* */ {
/* */ try
/* */ {
/* 472 */ sockets.wait(1000L);
/* */ }
/* */ catch (InterruptedException e)
/* */ {
/* 476 */ log.debug("unexpected interrupt");
/* */ }
/* */
/* 479 */ if (!sockets.isEmpty())
/* */ {
/* 481 */ Iterator it = sockets.iterator();
/* 482 */ Socket socket = (Socket)it.next();
/* 483 */ it.remove();
/* 484 */ log.debug(this + " found socket (" + this.listenerId + "): " + socket);
/* 485 */ return socket;
/* */ }
/* */ }
/* */
/* 489 */ if (timeout > 0) {
/* 490 */ timeRemaining = timeout - (System.currentTimeMillis() - start);
/* */ }
/* */ }
/* 493 */ if (!isConnected())
/* */ {
/* 495 */ throw new IOException("Connection is closed");
/* */ }
/* */
/* 498 */ throw new IOException("Timed out trying to create socket");
/* */ }
/* */
/* */ void replaceControlSocket(Socket socket)
/* */ throws IOException
/* */ {
/* 504 */ synchronized (this.controlLock)
/* */ {
/* 506 */ if (this.controlSocket != null)
/* */ {
/* 508 */ this.controlSocket.close();
/* */ }
/* */
/* 511 */ log.debug(this + " replacing control socket: " + this.controlSocket);
/* 512 */ this.controlSocket = socket;
/* 513 */ log.debug(this + " control socket replaced by: " + socket);
/* 514 */ this.controlOutputStream = this.controlSocket.getOutputStream();
/* */ }
/* */
/* 517 */ if (this.pingTimerTask != null) {
/* 518 */ this.pingTimerTask.cancel();
/* */ }
/* 520 */ this.pingTimerTask = new PingTimerTask(this);
/* */
/* 522 */ synchronized (timerLock)
/* */ {
/* 524 */ if (timer == null)
/* */ {
/* 526 */ timer = new Timer(true);
/* */ }
/* */ try
/* */ {
/* 530 */ timer.schedule(this.pingTimerTask, this.pingFrequency, this.pingFrequency);
/* */ }
/* */ catch (IllegalStateException e)
/* */ {
/* 534 */ log.debug("Unable to schedule TimerTask on existing Timer", e);
/* 535 */ timer = new Timer(true);
/* 536 */ timer.schedule(this.pingTimerTask, this.pingFrequency, this.pingFrequency);
/* */ }
/* */ }
/* */ }
/* */
/* */ InvokerLocator getSecondaryLocator()
/* */ throws Throwable
/* */ {
/* 544 */ InternalInvocation ii = new InternalInvocation("getSecondaryInvokerLocator", null);
/* 545 */ InvocationRequest r = new InvocationRequest(null, null, ii, null, null, null);
/* 546 */ log.debug("getting secondary locator");
/* 547 */ Exception savedException = null;
/* */
/* 549 */ for (int i = 0; i < this.maxRetries; i++)
/* */ {
/* */ try
/* */ {
/* 553 */ Object o = invoke(r);
/* 554 */ log.debug("secondary locator: " + o);
/* 555 */ return (InvokerLocator)o;
/* */ }
/* */ catch (Exception e)
/* */ {
/* 559 */ savedException = e;
/* 560 */ log.debug("unable to get secondary locator: trying again");
/* */ }
/* */ }
/* */
/* 564 */ throw savedException;
/* */ }
/* */
/* */ public InvokerLocator getCallbackLocator(Map metadata)
/* */ {
/* 570 */ String transport = (String)metadata.get("callbackServerProtocol");
/* 571 */ String host = (String)metadata.get("callbackServerHost");
/* 572 */ String sPort = (String)metadata.get("callbackServerPort");
/* 573 */ int port = -1;
/* 574 */ if (sPort != null)
/* */ {
/* */ try
/* */ {
/* 578 */ port = Integer.parseInt(sPort);
/* */ }
/* */ catch (NumberFormatException e)
/* */ {
/* 582 */ throw new RuntimeException("Can not set internal callback server port as configuration value (" + sPort + " is not a number.");
/* */ }
/* */ }
/* */
/* 586 */ return new InvokerLocator(transport, host, port, "callback", metadata);
/* */ }
/* */ static class PingTimerTask extends TimerTask {
/* */ private Object controlLock;
/* */ private OutputStream controlOutputStream;
/* */ private int maxRetries;
/* */ private Exception savedException;
/* */ private boolean pingSent;
/* */
/* 600 */ PingTimerTask(BisocketClientInvoker invoker) { this.controlLock = invoker.controlLock;
/* 601 */ this.controlOutputStream = invoker.controlOutputStream;
/* 602 */ this.maxRetries = invoker.getMaxRetries();
/* */ }
/* */
/* */ public void shutDown()
/* */ {
/* 607 */ synchronized (this.controlLock)
/* */ {
/* 609 */ this.controlOutputStream = null;
/* */ }
/* 611 */ cancel();
/* */ }
/* */
/* */ public void run()
/* */ {
/* 616 */ this.pingSent = false;
/* */
/* 618 */ for (int i = 0; i < this.maxRetries; i++)
/* */ {
/* */ try
/* */ {
/* 622 */ synchronized (this.controlLock)
/* */ {
/* 624 */ if (this.controlOutputStream == null) {
/* 625 */ return;
/* */ }
/* 627 */ this.controlOutputStream.write(1);
/* */ }
/* 629 */ this.pingSent = true;
/* */ }
/* */ catch (Exception e)
/* */ {
/* 634 */ this.savedException = e;
/* 635 */ BisocketClientInvoker.log.debug("Unable to send ping: trying again");
/* */ }
/* */ }
/* */
/* 639 */ if (!this.pingSent)
/* */ {
/* 641 */ BisocketClientInvoker.log.warn("Unable to send ping: shutting down PingTimerTask", this.savedException);
/* 642 */ shutDown();
/* */ }
/* */ }
/* */ }
/* */ }
/* Location: /home/mnovotny/projects/EMBEDDED_JBOSS_BETA3_COMMUNITY/embedded/output/lib/embedded-jboss/lib/jboss-embedded-all.jar
* Qualified Name: org.jboss.remoting.transport.bisocket.BisocketClientInvoker
* JD-Core Version: 0.6.0
*/