📄 requestmultiplexer.java
字号:
/* * JORAM: Java(TM) Open Reliable Asynchronous Messaging * Copyright (C) 2001 - 2006 ScalAgent Distributed Technologies * Copyright (C) 1996 - 2000 Dyade * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. * * Initial developer(s): ScalAgent Distributed Technologies */package org.objectweb.joram.client.jms.connection;import java.util.Enumeration;import java.util.Hashtable;import java.util.Timer;import java.util.TimerTask;import java.util.Vector;import javax.jms.IllegalStateException;import javax.jms.InvalidDestinationException;import javax.jms.JMSException;import javax.jms.JMSSecurityException;import org.objectweb.joram.client.jms.Connection;import org.objectweb.joram.client.jms.JoramTracing;import org.objectweb.joram.shared.client.AbstractJmsReply;import org.objectweb.joram.shared.client.AbstractJmsRequest;import org.objectweb.joram.shared.client.ConsumerMessages;import org.objectweb.joram.shared.client.JmsRequestGroup;import org.objectweb.joram.shared.client.MomExceptionReply;import org.objectweb.joram.shared.client.PingRequest;import org.objectweb.joram.shared.client.SessDenyRequest;import org.objectweb.joram.shared.excepts.AccessException;import org.objectweb.joram.shared.excepts.DestinationException;import org.objectweb.joram.shared.excepts.MomException;import org.objectweb.util.monolog.api.BasicLevel;public class RequestMultiplexer { private static class Status { public static final int OPEN = 0; public static final int CLOSE = 1; private static final String[] names = { "OPEN", "CLOSE"}; public static String toString(int status) { return names[status]; } } private Connection cnx; private volatile int status; private RequestChannel channel; public Hashtable requestsTable; private int requestCounter; private DemultiplexerDaemon demtpx; private Timer timer; /** * The task responsible for keeping * the connection alive. */ private HeartBeatTask heartBeatTask; private javax.jms.ExceptionListener exceptionListener; /** * The date of the last request */ private volatile long lastRequestDate; public RequestMultiplexer(Connection cnx, RequestChannel channel, long heartBeat) throws JMSException { this.channel = channel; this.cnx = cnx; requestsTable = new Hashtable(); requestCounter = 0; timer = new Timer(); channel.setTimer(timer); try { channel.connect(); } catch (Exception exc) { if (JoramTracing.dbgClient.isLoggable(BasicLevel.DEBUG)) JoramTracing.dbgClient.log(BasicLevel.DEBUG, "", exc); throw new JMSException(exc.toString()); } demtpx = new DemultiplexerDaemon(); demtpx.start(); setStatus(Status.OPEN); if (heartBeat > 0) { heartBeatTask = new HeartBeatTask(heartBeat); lastRequestDate = System.currentTimeMillis(); try { heartBeatTask.start(); } catch (Exception exc) { if (JoramTracing.dbgClient.isLoggable(BasicLevel.DEBUG)) JoramTracing.dbgClient.log(BasicLevel.DEBUG, "", exc); throw new JMSException(exc.toString()); } } } private void setStatus(int status) { if (JoramTracing.dbgClient.isLoggable(BasicLevel.DEBUG)) JoramTracing.dbgClient.log( BasicLevel.DEBUG, "RequestMultiplexer.setStatus(" + Status.toString(status) + ')'); this.status = status; } public boolean isClosed() { return status == Status.CLOSE; } public void setExceptionListener( javax.jms.ExceptionListener exceptionListener) { this.exceptionListener = exceptionListener; } public javax.jms.ExceptionListener getExceptionListener() { return exceptionListener; } public void sendRequest( AbstractJmsRequest request) throws JMSException { sendRequest(request, null); } public void sendRequest(AbstractJmsRequest request, ReplyListener listener) throws JMSException { synchronized (this) { if (status == Status.CLOSE) throw new IllegalStateException("Connection closed"); if (requestCounter == Integer.MAX_VALUE) { requestCounter = 0; } request.setRequestId(requestCounter++); if (listener != null) { requestsTable.put(new Integer(request.getRequestId()), listener); } if (heartBeatTask != null) { lastRequestDate = System.currentTimeMillis(); } } try { channel.send(request); } catch (Exception exc) { if (JoramTracing.dbgClient.isLoggable(BasicLevel.DEBUG)) JoramTracing.dbgClient.log(BasicLevel.DEBUG, "", exc); JMSException jmsExc = new JMSException(exc.toString()); jmsExc.setLinkedException(exc); throw jmsExc; } } public void setMultiThreadSync(int delay) { channel = new MultiThreadSyncChannel(channel, delay); } /** * Not synchronized because it would possibly * deadlock with some reply listeners * (actually requestors). */ public void close() { if (JoramTracing.dbgClient.isLoggable(BasicLevel.DEBUG)) JoramTracing.dbgClient.log( BasicLevel.DEBUG, "RequestMultiplexer.close()"); synchronized (this) { if (status == Status.CLOSE) return; // Immediately set the status as no error // can be thrown. This enables to release // the lock and avoid any dead lock // with the demultiplexer thread that // calls close() when interrupted. setStatus(Status.CLOSE); } if (heartBeatTask != null) heartBeatTask.cancel(); if (timer != null) timer.cancel(); channel.close(); demtpx.stop(); if (JoramTracing.dbgClient.isLoggable(BasicLevel.DEBUG)) JoramTracing.dbgClient.log( BasicLevel.DEBUG, " -> requestsTable=" + requestsTable); // The requests table can't be accessed // either by an external thread (status CLOSE) // or by the internal demultiplexer thread (stopped). Enumeration requestIds = requestsTable.keys(); Enumeration listeners = requestsTable.elements(); while (listeners.hasMoreElements()) { Integer requestId = (Integer)requestIds.nextElement(); ReplyListener rl = (ReplyListener)listeners.nextElement(); rl.replyAborted(requestId.intValue()); } requestsTable.clear(); } /** * Used by Connection clean up. * It's a very specific usage linked to * the connector layer. */ public void cleanup() { Enumeration requestIds = requestsTable.keys(); Enumeration listeners = requestsTable.elements(); while (listeners.hasMoreElements()) { Integer requestId = (Integer)requestIds.nextElement(); ReplyListener rl = (ReplyListener)listeners.nextElement(); rl.replyAborted(requestId.intValue()); } requestsTable.clear(); } /** * Not synchronized because it would possibly * deadlock with some reply listeners * (actually requestors). */ public void abortRequest(int requestId) { if (JoramTracing.dbgClient.isLoggable(BasicLevel.DEBUG)) JoramTracing.dbgClient.log( BasicLevel.DEBUG, "RequestMultiplexer.abortRequest(" + requestId + ')'); ReplyListener rl = doAbortRequest(requestId); if (rl != null) { rl.replyAborted(requestId); } } private synchronized ReplyListener doAbortRequest(int requestId) { if (JoramTracing.dbgClient.isLoggable(BasicLevel.DEBUG)) JoramTracing.dbgClient.log( BasicLevel.DEBUG, "RequestMultiplexer.doAbortRequest(" +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -