All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mq5.0-source.main.mq-admin.admin-cli.src.main.java.com.sun.messaging.jmq.admin.bkrutil.BrokerAdminConn Maven / Gradle / Ivy

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2000-2012 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

/*
 */ 

package com.sun.messaging.jmq.admin.bkrutil;

import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Properties;
import java.io.EOFException;
import java.net.MalformedURLException;
import javax.jms.*;

import com.sun.messaging.AdministeredObject;
import com.sun.messaging.ConnectionConfiguration;
import com.sun.messaging.QueueConnectionFactory;
import com.sun.messaging.jmq.ClientConstants;
import com.sun.messaging.jmq.io.MQAddress;
import com.sun.messaging.jmq.io.MQAddressList;

import com.sun.messaging.jmq.jmsclient.resources.ClientResources;
import com.sun.messaging.jmq.admin.event.AdminEvent;
import com.sun.messaging.jmq.admin.event.AdminEventListener;
import com.sun.messaging.jmq.admin.event.BrokerErrorEvent;
import com.sun.messaging.jmq.admin.event.CommonCmdStatusEvent;
import com.sun.messaging.jmq.admin.util.CommonGlobals;

/**
 * This class provides the common code for the administration connection
 * to the JMQ broker.  This class is extended by individual admin tools 
 * imqcmd (BrokerAdmin), imqadmin (BrokerAdmin) and imqbridgemgr (BridgeAdmin) 
 *
 * Any individual admin tool specific protocol or class references must be
 * placed in its corresponding subclass.
 *
 * 

* The information needed to create this object are: *

    *
  • connection factory attributes *
  • username/passwd *
  • timeout (for receiving replies) *
*/ public abstract class BrokerAdminConn implements ExceptionListener { public final static String DEFAULT_ADMIN_USERNAME = "admin"; public final static String DEFAULT_ADMIN_PASSWD = "admin"; public static long defaultTimeout = 10000; public static int defaultNumRetries = 5; /* * Reconnect attributes. * These are used for the restart command. */ public static final int RECONNECT_RETRIES = 5; public static final long RECONNECT_DELAY = 5000; private String key = null; private String username, passwd; private int numRetries; private QueueConnectionFactory qcf; private QueueConnection connection = null; private Queue requestQueue; /******************************************************** * Below variables are directly referenced by subclasses ********************************************************/ protected long timeout; protected static boolean debug = false; protected QueueSession session; protected TemporaryQueue replyQueue; protected QueueSender sender; protected QueueReceiver receiver; protected boolean isConnected = false; /********************************************************* * Above variables are directly referenced by subclasses *********************************************************/ private MQAddress address = null; private boolean checkShutdownReply = true; /* * List of properties that we currently care about i.e. that are * saved out if necessary. The reconnect stuff is currently * not used. This is used by getBrokerAttrs() which in turn is * used only by the admin console. */ private final static String savedQCFProperties[] = { ConnectionConfiguration.imqBrokerHostName, ConnectionConfiguration.imqBrokerHostPort }; private boolean adminKeyUsed = false; private boolean sslTransportUsed = false; private boolean isInitiator = false; private boolean isReconnect = false; private Vector eListeners = new Vector(); private MessageAckThread msgAckThread = null; private boolean busy = false; /* * Temporary convenient constructor. */ public BrokerAdminConn(String brokerHost, int brokerPort) throws BrokerAdminException { this(brokerHost, brokerPort, null, null, -1, false, -1, -1); } public BrokerAdminConn(String brokerHost, int brokerPort, String username, String passwd) throws BrokerAdminException { this(brokerHost, brokerPort, username, passwd, -1, false, -1, -1); } public BrokerAdminConn(String brokerHost, int brokerPort, String username, String passwd, int timeout) throws BrokerAdminException { this(brokerHost, brokerPort, username, passwd, timeout, false, -1, -1); } public BrokerAdminConn(String brokerAddress, String username, String passwd, int timeout, boolean useSSL) throws BrokerAdminException { this(brokerAddress, username, passwd, timeout, false, -1, -1, useSSL); } /** * Instantiates a BrokerAdminConn object. This is a wrapper for * this other constructor: * * public BrokerAdminConn(Properties, String, String, long) * * @param brokerHost host name of the broker to administer * @param brokerPort primary port for broker * @param username username used to authenticate * @param passwd password used to authenticate * @param timeout timeout value (in milliseconds) for receive; * 0 = never times out and the call blocks * indefinitely * @param reconnect true if reconnect is enabled; false otherwise * @param reconnectRetries number of reconnect retries * @param reconnectDelay interval of reconnect retries in milliseconds */ public BrokerAdminConn(String brokerHost, int brokerPort, String username, String passwd, long timeout, boolean reconnect, int reconnectRetries, long reconnectDelay) throws BrokerAdminException { Properties tmpProps = new Properties(); if (brokerHost != null) { tmpProps.setProperty(ConnectionConfiguration.imqBrokerHostName, brokerHost); } if (brokerPort > 0) { tmpProps.setProperty(ConnectionConfiguration.imqBrokerHostPort, String.valueOf(brokerPort)); } if (reconnect) { tmpProps.setProperty(ConnectionConfiguration.imqReconnectEnabled, String.valueOf(reconnect)); tmpProps.setProperty(ConnectionConfiguration.imqReconnectAttempts, String.valueOf(reconnectRetries)); tmpProps.setProperty(ConnectionConfiguration.imqReconnectInterval, String.valueOf(reconnectDelay)); } if (timeout >= 0) { this.timeout = timeout; } else { this.timeout = defaultTimeout; } this.numRetries = defaultNumRetries; this.username = username; this.passwd = passwd; createFactory(tmpProps); } /** * Instantiates a BrokerAdminConn object. This is a wrapper for * this other constructor: * * public BrokerAdminConn(Properties, String, String, long) * * @param brokerAddress address/url of broker * @param username username used to authenticate * @param passwd password used to authenticate * @param timeout timeout value (in milliseconds) for receive; * 0 = never times out and the call blocks * indefinitely * @param reconnect true if reconnect is enabled; false otherwise * @param reconnectRetries number of reconnect retries * @param reconnectDelay interval of reconnect retries in milliseconds * @param useSSL Use encrypted transport via SSL */ public BrokerAdminConn(String brokerAddress, String username, String passwd, long timeout, boolean reconnect, int reconnectRetries, long reconnectDelay, boolean useSSL) throws BrokerAdminException { Properties tmpProps = new Properties(); if (brokerAddress == null) { brokerAddress = ""; } try { if (useSSL) { address = (MQAddress)SSLAdminMQAddress.createAddress(brokerAddress); } else { address = (MQAddress)AdminMQAddress.createAddress(brokerAddress); } } catch (Exception e) { BrokerAdminException bae; bae = new BrokerAdminException(BrokerAdminException.BAD_ADDR_SPECIFIED); bae.setBrokerAddress(brokerAddress); bae.setLinkedException(e); throw bae; } tmpProps.setProperty(ConnectionConfiguration.imqAddressList, address.toString()); if (reconnect) { tmpProps.setProperty(ConnectionConfiguration.imqReconnectEnabled, String.valueOf(reconnect)); tmpProps.setProperty(ConnectionConfiguration.imqReconnectAttempts, String.valueOf(reconnectRetries)); tmpProps.setProperty(ConnectionConfiguration.imqReconnectInterval, String.valueOf(reconnectDelay)); } if (timeout >= 0) { this.timeout = timeout; } else { this.timeout = defaultTimeout; } this.numRetries = defaultNumRetries; this.username = username; this.passwd = passwd; createFactory(tmpProps); } /** * The constructor for the class. * * @param brokerAttrs Properties object containing * the broker attributes. This is * basically what is used to create * the connection factory. * @param username username used to authenticate * @param passwd password used to authenticate * @param timeout timeout value (in milliseconds) for receive; * 0 = never times out and the call blocks * indefinitely */ public BrokerAdminConn(Properties brokerAttrs, String username, String passwd, long timeout) throws BrokerAdminException { if (timeout >= 0) { this.timeout = timeout; } else { this.timeout = defaultTimeout; } this.numRetries = defaultNumRetries; this.username = username; this.passwd = passwd; createFactory(brokerAttrs); } public void setBrokerHost(String hostName) throws BrokerAdminException { try { setFactoryAttr(ConnectionConfiguration.imqBrokerHostName, hostName); } catch (JMSException jmse) { BrokerAdminException bae; bae = new BrokerAdminException(BrokerAdminException.BAD_HOSTNAME_SPECIFIED); bae.setBadValue(hostName); bae.setLinkedException(jmse); throw bae; } } public String getBrokerAddress() { if (address != null) { return (address.toString()); } return (getFactoryAttr(ConnectionConfiguration.imqAddressList)); } public String getBrokerHost() { if (address != null) { return (address.getHostName()); } return (getFactoryAttr(ConnectionConfiguration.imqBrokerHostName)); } public void setBrokerPort(String port) throws BrokerAdminException { try { setFactoryAttr(ConnectionConfiguration.imqBrokerHostPort, port); } catch (JMSException jmse) { BrokerAdminException bae; bae = new BrokerAdminException(BrokerAdminException.BAD_PORT_SPECIFIED); bae.setBadValue(port); bae.setLinkedException(jmse); throw bae; } } public String getBrokerPort() { if (address != null) { return ((new Integer(address.getPort())).toString()); } return (getFactoryAttr(ConnectionConfiguration.imqBrokerHostPort)); } public static void setDefaultTimeout(long defaultTimeout) { BrokerAdminConn.defaultTimeout = defaultTimeout; if (debug) { CommonGlobals.stdOutPrintln("BrokerAdminConn defaultTimeout set to: " + BrokerAdminConn.defaultTimeout); } } public static long getDefaultTimeout() { return (defaultTimeout); } public long getTimeout() { return (timeout); } public static void setDefaultNumRetries(int defaultNumRetries) { BrokerAdminConn.defaultNumRetries = defaultNumRetries; if (debug) { CommonGlobals.stdOutPrintln("BrokerAdminConn defaultNumRetries set to: " + BrokerAdminConn.defaultNumRetries); } } public static long getDefaultNumRetries() { return (defaultNumRetries); } public void setNumRetries(int numRetries) { this.numRetries = numRetries; if (debug) { CommonGlobals.stdOutPrintln("BrokerAdminConn num retries set to: " + this.numRetries); } } public int getNumRetries() { return this.numRetries; } public void setUserName(String userName) { this.username = userName; } public String getUserName() { return (username); } public void setPassword(String passwd) { this.passwd = passwd; } public String getPassword() { return (passwd); } protected void setBusy(boolean b) { busy = b; if (debug) { CommonGlobals.stdOutPrintln("***** BrokerAdminConn.setBusy(): " + b); } if (!b && (msgAckThread != null)) { /* * If we are going from busy -> not busy, * nullify the ack thread. */ msgAckThread = null; } } public boolean isBusy() { return(busy); } protected void checkIfBusy() throws BrokerAdminException { if (isBusy()) { BrokerAdminException bae; bae = new BrokerAdminException( BrokerAdminException.BUSY_WAIT_FOR_REPLY); bae.setBrokerAdminConn(this); throw bae; } } /* * Support for private "-adminkey" option. * This is used for authentication when shutting down the * broker via the NT service's "Stop" command. */ public void setAdminKeyUsed(boolean b) { this.adminKeyUsed = b; } public boolean getAdminKeyUsed() { return (adminKeyUsed); } /* * Sets a string that will be used to uniquely identify this * broker instance. */ public void setKey(String key) { this.key = key; } /** * Returns a unique key of this broker instance. * If the key field is not set, host:port is returned */ public String getKey() { if (key != null) { return (key); } return (getBrokerHost() + ":" + getBrokerPort()); } /* * Support for "-ssl" option. * This is used to indicate that SSL transport * will be used. */ public void setSSLTransportUsed(boolean b) { this.sslTransportUsed = b; } public boolean getSSLTransportUsed() { return (sslTransportUsed); } /* * Set when this BrokerAdminConn has initiated the * shutdown operation. */ public void setInitiator(boolean b) { this.isInitiator = b; } private boolean isInitiator() { return (isInitiator); } /* * Set this to false if the admin process does not * do shutdown operation of the broker */ public void setCheckShutdownReply(boolean b) { this.checkShutdownReply = b; } /* * Set when this BrokerAdminConn is restarted. */ public void setReconnect(boolean b) { this.isReconnect = b; } public boolean isReconnect() { return (isReconnect); } /* * Return a properties object containing the queue * connection configuration properties. * We restrict the props to those listed in the * savedQCFProperties array - otherwise we'll get * the whole load - most of which are defaults. */ public Properties getBrokerAttrs() { Properties tmpProps = new Properties(); if (qcf == null) { return (tmpProps); } for (int i = 0; i < savedQCFProperties.length; ++i) { String propName = savedQCFProperties[i], propVal = getFactoryAttr(propName); tmpProps.setProperty(propName, propVal); } return (tmpProps); } public void connect() throws BrokerAdminException { // We need a flag since username / password can be null. connect(null, null, false); } public void connect(String tempUsername, String tempPasswd) throws BrokerAdminException { // We need a flag since username / password can be null. connect(tempUsername, tempPasswd, true); } // REVISIT: should this be synchronized to make sure isConnected is properly set? private void connect(String tempUsername, String tempPasswd, boolean useTempValues) throws BrokerAdminException { BrokerAdminException bae; try { if (adminKeyUsed) { /* * turn on using password as special admin key */ qcf.setConnectionType(ClientConstants.CONNECTIONTYPE_ADMINKEY); } if (sslTransportUsed) { /* * Set connection transport to be SSL */ try { qcf.setProperty(ConnectionConfiguration.imqConnectionType, "SSL"); } catch (Exception e) { } try { setFactoryAttr(ConnectionConfiguration.imqConnectionType, "SSL"); } catch (JMSException jmse) { bae = new BrokerAdminException(BrokerAdminException.PROB_SETTING_SSL); bae.setBrokerHost(getBrokerHost()); bae.setBrokerPort(getBrokerPort()); bae.setLinkedException(jmse); throw bae; } } if (debug) { printObjProperties(qcf); } if (useTempValues) { connection = qcf.createQueueConnection(tempUsername, tempPasswd); } else { connection = qcf.createQueueConnection(username, passwd); } connection.setExceptionListener(this); connection.start(); if (debug) CommonGlobals.stdOutPrintln("***** Creating queue connection"); session = connection.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE); if (debug) CommonGlobals.stdOutPrintln ("***** Creating queue session: not transacted, auto ack"); requestQueue = session.createQueue(getAdminQueueDest()); if (debug) CommonGlobals.stdOutPrintln("***** Created requestQueue: " + requestQueue); replyQueue = session.createTemporaryQueue(); if (debug) CommonGlobals.stdOutPrintln("***** Created replyQueue: " + replyQueue); sender = session.createSender(requestQueue); // making the message delivery mode non-persistent sender.setDeliveryMode(DeliveryMode.NON_PERSISTENT); if (debug) CommonGlobals.stdOutPrintln("***** Created a sender: " + sender); receiver = session.createReceiver(replyQueue); if (debug) CommonGlobals.stdOutPrintln("***** Created a receiver: " + receiver); } catch (JMSException jmse) { if (jmse instanceof JMSSecurityException) { String errorCode = jmse.getErrorCode(); if ((AdministeredObject.cr.X_INVALID_LOGIN).equals(errorCode)) bae = new BrokerAdminException(BrokerAdminException.INVALID_LOGIN); else bae = new BrokerAdminException(BrokerAdminException.SECURITY_PROB); } else { bae = new BrokerAdminException(BrokerAdminException.CONNECT_ERROR); } bae.setBrokerHost(getBrokerHost()); bae.setBrokerPort(getBrokerPort()); bae.setLinkedException(jmse); throw bae; } catch (Exception e) { bae = new BrokerAdminException(BrokerAdminException.CONNECT_ERROR); bae.setLinkedException(e); bae.setBrokerHost(getBrokerHost()); bae.setBrokerPort(getBrokerPort()); throw bae; } } public abstract String getAdminQueueDest(); public abstract String getAdminMessagePropNameMessageType(); public abstract String getAdminMessagePropNameErrorString(); public abstract String getAdminMessagePropNameStatus(); public abstract int getAdminMessageStatusOK(); public abstract int getAdminMessageTypeSHUTDOWN_REPLY(); public abstract CommonCmdStatusEvent newCommonCmdStatusEvent(int type); public abstract CommonCmdStatusEvent getCurrentStatusEvent(); public abstract void clearStatusEvent(); private void printObjProperties(AdministeredObject obj) { CommonGlobals.stdOutPrintln("Connection Factory Object properties:"); /* * Print the properties of the object. */ Properties props = obj.getConfiguration(); for (Enumeration e = obj.enumeratePropertyNames(); e.hasMoreElements();) { String propName = (String)e.nextElement(); String value = props.getProperty(propName); String propLabel; try { propLabel = obj.getPropertyLabel(propName); } catch (Exception ex) { propLabel = "UNKNOWN"; } String printLabel = propName + " [" + propLabel + "]"; CommonGlobals.stdOutPrintln("\t" + printLabel + " = " + value); } CommonGlobals.stdOutPrintln(""); } /** * Returns true if this instance is connected to the broker. * Returns false otherwise. */ public boolean isConnected() { return (isConnected); } /** * Sets the value of isConnected value. */ public void setIsConnected(boolean b) { this.isConnected = b; } private String getErrorMessage(Message mesg) { String error = null; try { error = mesg.getStringProperty(getAdminMessagePropNameErrorString()); } catch (JMSException jmse) { if (debug) { CommonGlobals.stdErrPrint("Failed to retrieve the error message: "); CommonGlobals.stdErrPrintln(jmse.getMessage()); jmse.printStackTrace(); } } catch (Exception e) { if (debug) { CommonGlobals.stdErrPrintln("Exception caught: " + e.getMessage()); e.printStackTrace(); } } return error; } /** * This method is used to force the connection close when shutdown is * performed on the broker. This way the connection is closed immediately * and we rely on the client to do all the cleanup for us. This is * called immediately as to avoid any unnecessary reconnect retries. */ public void forceClose() { try { if (connection != null) { connection.close(); } isConnected = false; if (msgAckThread != null) { msgAckThread.stop(); msgAckThread = null; if (debug) CommonGlobals.stdOutPrintln("***** Stopped msgAckThread thread..."); } } catch (JMSException jmse) { CommonGlobals.stdErrPrintln("JMSException caught: " + jmse.getMessage()); jmse.printStackTrace(); } } // REVISIT: should this be synchronized to make sure isConnected is properly set? public void close() { if (!isConnected()) { return; } try { if (msgAckThread != null) { msgAckThread.stop(); msgAckThread = null; if (debug) CommonGlobals.stdOutPrintln("***** Stopped msgAckThread thread..."); } if (debug) CommonGlobals.stdOutPrintln("***** Closing sender and receiver..."); sender.close(); if (debug) CommonGlobals.stdOutPrintln("***** Closed sender."); receiver.close(); if (debug) CommonGlobals.stdOutPrintln("***** Closed receiver."); if (debug) CommonGlobals.stdOutPrintln("***** Closing queue session and queue connection..."); session.close(); if (debug) CommonGlobals.stdOutPrintln("***** Closed session."); } catch (JMSException jmse) { CommonGlobals.stdErrPrintln("JMSException caught: " + jmse.getMessage()); jmse.printStackTrace(); } catch (Exception e) { CommonGlobals.stdErrPrintln("Exception caught: " + e.getMessage()); e.printStackTrace(); } try { if (connection != null) { connection.close(); if (debug) CommonGlobals.stdOutPrintln("***** Closed connection."); } isConnected = false; setBusy(false); } catch (JMSException jmse) { if (sslTransportUsed) { isConnected = false; setBusy(false); } else { CommonGlobals.stdErrPrintln("JMSException caught: " + jmse.getMessage()); jmse.printStackTrace(); } } catch (Exception e) { if (sslTransportUsed) { isConnected = false; setBusy(false); } else { CommonGlobals.stdErrPrintln("Exception caught: " + e.getMessage()); e.printStackTrace(); } } } private void setFactoryAttr(String propName, String propVal) throws JMSException { if (qcf == null) { return; } qcf.setProperty(propName, propVal); } private String getFactoryAttr(String propName) { if (qcf == null) { return (null); } String s; try { s = qcf.getProperty(propName); } catch (JMSException jmse) { s = null; } return (s); } private void createFactory(Properties brokerAttrs) throws BrokerAdminException { BrokerAdminException bae; qcf = new QueueConnectionFactory(); try { qcf.setConnectionType(ClientConstants.CONNECTIONTYPE_ADMIN); for (Enumeration e = brokerAttrs.propertyNames(); e.hasMoreElements(); ) { String propName = (String)e.nextElement(); String value = brokerAttrs.getProperty(propName); if (value != null) { qcf.setProperty(propName, value); } } } catch (JMSException jmse) { bae = new BrokerAdminException(BrokerAdminException.CONNECT_ERROR); bae.setLinkedException(jmse); bae.setBrokerHost(getBrokerHost()); bae.setBrokerPort(getBrokerPort()); throw bae; } catch (Exception e) { bae = new BrokerAdminException(BrokerAdminException.CONNECT_ERROR); bae.setLinkedException(e); bae.setBrokerHost(getBrokerHost()); bae.setBrokerPort(getBrokerPort()); throw bae; } if (debug) { CommonGlobals.stdOutPrintln("***** BrokerAdminConn instance: " + getKey()); CommonGlobals.stdOutPrintln("BrokerAdminConn created with timeout set to: " + (this.timeout/1000) + " seconds"); CommonGlobals.stdOutPrintln("BrokerAdminConn created with num retries set to: " + this.numRetries); } } protected Message receiveCheckMessageTimeout(boolean isShutdownReply) throws BrokerAdminException { return (receiveCheckMessageTimeout(isShutdownReply, true)); } /* * Convenience method used to check the received mesg * if it is null. * * If it is null, this means that the receive() method timed out. * An appropriate number of retries is attempted after which * a BrokerAdminException is thrown. Each receive retry is made * with a timeout that is a multiple of the original timeout. */ protected Message receiveCheckMessageTimeout(boolean isShutdownReply, boolean waitForResponse) throws BrokerAdminException { Message mesg = null; BrokerAdminException bae; long incrTimeout = timeout; int localNumRetries = 0; try { while (localNumRetries <= numRetries) { mesg = (ObjectMessage)receiver.receive(incrTimeout); /* REVISIT: There is a timing problem in the protocol. The GOODBYE message could be processed before the SHUTDOWN_REPLY message and therefore could be sending null as a value for 'mesg' when receive() returns. We will assume that the SHUTDOWN operation was successful when we receive status == 200 or mesg == null. */ if (mesg != null) { break; } else { if (isShutdownReply) { isConnected = false; break; } else { localNumRetries++; incrTimeout += timeout; if (localNumRetries <= numRetries) { /* * Send a status event so that something like * the following can be printed: * * Broker not responding, * retrying [1 of 2 attempts, timeout=20 seconds] */ CommonCmdStatusEvent cse = newCommonCmdStatusEvent(CommonCmdStatusEvent.BROKER_BUSY); cse.setNumRetriesAttempted(localNumRetries); cse.setMaxNumRetries(numRetries); cse.setRetryTimeount((incrTimeout/1000)); fireAdminEventDispatched(cse); } else { /* * It looks like we timed out waiting for a reply * even after several retries. * We should: * - fire off a thread to continue waiting for the reply. * (this will mark this BrokerAdminConn as 'busy'). * - throw an exception saying the reply was not received. */ msgAckThread = new MessageAckThread(this); msgAckThread.start(); if (waitForResponse) bae = new BrokerAdminException( BrokerAdminException.REPLY_NOT_RECEIVED); else bae = new BrokerAdminException( BrokerAdminException.IGNORE_REPLY_IF_RCVD); throw bae; } } } } } catch (Exception e) { handleReceiveExceptions(e); } return (mesg); } protected void checkReplyTypeStatus(Message mesg, int msgType, String msgTypeString) throws BrokerAdminException { BrokerAdminException bae; int actualMsgType, actualReplyStatus; /* REVISIT: There is a timing problem in the protocol. The GOODBYE message could be processed before the SHUTDOWN_REPLY message and therefore could be sending null as a value for 'mesg' when receive() returns. We will assume that the SHUTDOWN operation was successful when we receive status == 200 or mesg == null. */ if (mesg == null) { if (checkShutdownReply && (msgType == getAdminMessageTypeSHUTDOWN_REPLY())) { isConnected = false; return; } } /* * Fetch reply message type */ try { actualMsgType = mesg.getIntProperty(getAdminMessagePropNameMessageType()); } catch (JMSException jmse) { bae = new BrokerAdminException( BrokerAdminException.PROB_GETTING_MSG_TYPE); bae.setLinkedException(jmse); throw bae; } /* * Fetch reply status code */ try { actualReplyStatus = mesg.getIntProperty(getAdminMessagePropNameStatus()); } catch (JMSException jmse) { bae = new BrokerAdminException( BrokerAdminException.PROB_GETTING_STATUS); bae.setLinkedException(jmse); throw bae; } if (debug) { CommonGlobals.stdOutPrintln("\tReplyMsgType=" + actualMsgType + "(expecting " + msgType + "[" + msgTypeString + "]), ReplyStatus=" + actualReplyStatus); } /* * Both values must be correct */ if ((msgType == actualMsgType) && (actualReplyStatus == getAdminMessageStatusOK())) { if (msgType == getAdminMessageTypeSHUTDOWN_REPLY()) isConnected = false; return; } /* * Otherwise, report an error */ String errorStr = getErrorMessage(mesg); if (debug) { CommonGlobals.stdOutPrintln("\tJMQ_ERROR_STRING=" + errorStr); } bae = new BrokerAdminException(BrokerAdminException.MSG_REPLY_ERROR); bae.setBrokerErrorStr(errorStr); bae.setReplyMsgType(actualMsgType); bae.setReplyStatus(actualReplyStatus); bae.setReplyMsg(mesg); throw bae; } protected void handleSendExceptions(Exception e) throws BrokerAdminException { BrokerAdminException bae; if (e instanceof BrokerAdminException) { throw ((BrokerAdminException)e); } else if (e instanceof JMSException) { /* * Handled separately from regular Exceptions in case we know * enough to report them in a more useful way. */ bae = new BrokerAdminException(BrokerAdminException.MSG_SEND_ERROR); bae.setLinkedException(e); throw bae; } else { bae = new BrokerAdminException(BrokerAdminException.MSG_SEND_ERROR); bae.setLinkedException(e); throw bae; } } protected void handleReceiveExceptions(Exception e) throws BrokerAdminException { BrokerAdminException bae; if (e instanceof BrokerAdminException) { /* * Could be thrown by checkReplyTypeStatus() */ throw ((BrokerAdminException)e); } else if (e instanceof JMSException) { /* * Handled separately from regular Exceptions in case we know * enough to report them in a more useful way. */ bae = new BrokerAdminException(BrokerAdminException.MSG_REPLY_ERROR); bae.setLinkedException(e); throw bae; } else { bae = new BrokerAdminException(BrokerAdminException.MSG_REPLY_ERROR); bae.setLinkedException(e); throw bae; } } /** * Add an admin event listener. * @param l admin event listener to add. */ public void addAdminEventListener(AdminEventListener l) { eListeners.addElement(l); } /** * Remove an admin event listener. * @param l admin event listener to remove. */ public void removeAdminEventListener(AdminEventListener l) { eListeners.removeElement(l); } /** * Remove all admin event listeners. */ public void removeAllAdminEventListeners() { eListeners.removeAllElements(); } /** * Fire off/dispatch an admin event to all the listeners. * @param ae AdminEvent to dispatch to event listeners. */ public void fireAdminEventDispatched(AdminEvent ae) { for (int i = 0; i < eListeners.size(); i++) { ((AdminEventListener)eListeners.elementAt(i)). adminEventDispatched(ae); } } protected void sendStatusEvent(Message mesg, Exception ex) { if (getCurrentStatusEvent() != null) { /* * Set success flag to true/false before * firing off status event. */ if (mesg == null) { /* * If mesg is null, ex should hold an exception * that caused the failure */ getCurrentStatusEvent().setSuccess(false); getCurrentStatusEvent().setLinkedException(ex); } else { /* * If mesg is not null, check for reply/status code */ try { checkReplyTypeStatus(mesg, getCurrentStatusEvent().getReplyType(), getCurrentStatusEvent().getReplyTypeString()); if (mesg instanceof ObjectMessage) { try { getCurrentStatusEvent().setReturnedObject( ((ObjectMessage)mesg).getObject()); } catch (JMSException jmse) { /* * Problems retrieving the associated object. * Report an error. */ getCurrentStatusEvent().setSuccess(false); getCurrentStatusEvent().setLinkedException(jmse); } } getCurrentStatusEvent().setSuccess(true); } catch (BrokerAdminException bae) { getCurrentStatusEvent().setSuccess(false); getCurrentStatusEvent().setLinkedException(bae); } } fireAdminEventDispatched(getCurrentStatusEvent()); clearStatusEvent(); } } /* * BEGIN INTERFACE ExceptionListener */ public void onException(JMSException jmse) { BrokerErrorEvent bee = null; isConnected = false; /* * Broker initiated connection close. */ if (ClientResources.X_BROKER_GOODBYE == jmse.getErrorCode()) { /* * Check to see if this BrokerAdminConn has initiated the * shutdown. Only propagate the error message if it is * NOT initiated by this BrokerAdminConn. */ if (!isInitiator()) { bee = new BrokerErrorEvent(this, BrokerErrorEvent.ALT_SHUTDOWN); bee.setBrokerHost(getBrokerHost()); bee.setBrokerPort(getBrokerPort()); bee.setBrokerName(getKey()); } /* * Broker unexpectedly shutdown. */ } else if (jmse.getLinkedException() instanceof EOFException) { bee = new BrokerErrorEvent(this, BrokerErrorEvent.UNEXPECTED_SHUTDOWN); bee.setBrokerHost(getBrokerHost()); bee.setBrokerPort(getBrokerPort()); bee.setBrokerName(getKey()); /* * Other misc. connection problems. */ } else { bee = new BrokerErrorEvent(this, BrokerErrorEvent.CONNECTION_ERROR); bee.setBrokerHost(getBrokerHost()); bee.setBrokerPort(getBrokerPort()); bee.setBrokerName(getKey()); } if (bee != null) fireAdminEventDispatched(bee); removeAllAdminEventListeners(); } /* * END INTERFACE ExceptionListener */ public static void setDebug(boolean b) { debug = b; } public static boolean getDebug() { return (debug); } } class MessageAckThread implements Runnable { private Thread ackThread = null; private BrokerAdminConn ba; private boolean msgReceived = false; private long timeout = 30000; private boolean debug = false, stopRequested = false; public MessageAckThread(BrokerAdminConn ba) { debug = BrokerAdminConn.getDebug(); if (debug) { CommonGlobals.stdOutPrintln("***** Created MessageAckThread"); } this.ba = ba; } public synchronized void start() { if (ackThread == null) { ackThread = new Thread(this, "JMQ Administration MessageAckThread"); ackThread.start(); if (debug) { CommonGlobals.stdOutPrintln("***** Started MessageAckThread"); } } } public synchronized void stop() { stopRequested = true; } public void run() { Message mesg = null; ba.setBusy(true); while (!msgReceived && ackThread != null && !stopRequested) { try { mesg = ba.receiver.receive(timeout); if (mesg != null) { if (debug) { CommonGlobals.stdOutPrintln("***** MessageAckThread: received reply message !"); } msgReceived = true; if (debug) { CommonGlobals.stdOutPrintln("***** MessageAckThread: acknowledging reply message."); } mesg.acknowledge(); synchronized (this) { ba.setBusy(false); ba.sendStatusEvent(mesg, null); } } else { synchronized (this) { if (stopRequested) { if (debug) { CommonGlobals.stdOutPrintln("***** MessageAckThread: receive() timed out. Not retrying (stop requested)."); } stopRequested = false; ackThread = null; return; } } if (debug) { CommonGlobals.stdOutPrintln("***** MessageAckThread: receive() timed out. Retrying..."); } } } catch (Exception e) { /* * Caught exception while waiting for reply message. * Report error in status event. */ synchronized (this) { ba.setBusy(false); ba.sendStatusEvent(null, e); } } } ba.setBusy(false); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy