diff --git a/joram/joram/tools/jmscheck/src/main/java/org/ow2/joram/tools/jmscheck/JMSConnectorCheck.java b/joram/joram/tools/jmscheck/src/main/java/org/ow2/joram/tools/jmscheck/JMSConnectorCheck.java index 6041e77593a12196e6e73c6d7ebc1f407f5019e5..1c1e54d7fe90f51a7d62368fba89a987f771e298 100644 --- a/joram/joram/tools/jmscheck/src/main/java/org/ow2/joram/tools/jmscheck/JMSConnectorCheck.java +++ b/joram/joram/tools/jmscheck/src/main/java/org/ow2/joram/tools/jmscheck/JMSConnectorCheck.java @@ -1,329 +1,350 @@ -/* - * Copyright (C) 2020 - 2021 ScalAgent Distributed Technologies - * - * 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 - * Contributor(s): - */ -package org.ow2.joram.tools.jmscheck; - -import java.text.DateFormat; -import java.util.Date; - -import javax.jms.Connection; -import javax.jms.ConnectionFactory; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Session; -import javax.jms.TextMessage; -import javax.naming.InitialContext; -import javax.naming.NamingException; - -import org.objectweb.joram.client.jms.Queue; - -import org.objectweb.util.monolog.api.BasicLevel; -import org.objectweb.util.monolog.api.Logger; - -import fr.dyade.aaa.common.Debug; - -/** - * Component allowing to check a JMS connector. - */ -public final class JMSConnectorCheck { - static Logger logger = Debug.getLogger(JMSConnectorCheck.class.getName()); - - public static final int RUNNING = 0; - public static final int UNREACHABLE = 1; - static final String[] info = { "RUNNING", "UNREACHABLE" }; - - /** retryStatusCount == 0 => RUNNING, retryStatusCount > 0 => UNREACHABLE */ - private int retryStatusCount = UNREACHABLE; - - /** - * Returns the status of the connector: 0 => RUNNING, >0 => UNREACHABLE. - * - * @return the number of unreachable connection - */ - public int getStatus() { - return retryStatusCount; - } - - public String getStatusInfo() { - if (retryStatusCount > 0) - return info[1] + '(' + retryStatusCount + ')'; - return info[0]; - } - - private void setStatus(int retry) { - this.retryStatusCount = retry; - } - - private int nbtry = 0; - - /** - * Returns the total number of try since starting. - * @return the total number of try since starting. - */ - public int getNbTry() { - return nbtry; - } - - private transient int failures = 0; - - /** - * Returns the total number of failures since starting. - * @return the total number of failures since starting. - */ - public int getNbFailures() { - return failures; - } - - private String errorMsg; - - /** - * Returns the error message of the last try. - * Returns null if the test is successful. - * @return - */ - public String getErrorMsg() { - return errorMsg; - } - - private String lastConnectTime = "-"; - - /** - * Returns the date of last successful connection. - * @return the date of last successful connection. - */ - public String getLastConnectTime() { - return lastConnectTime; - } - - private long latencyConnect = -1; - - /** - * Returns the latency of the connection during the last try. - * Returns -1 if the test failed. - * @return the latency of the connection during the last try. - */ - public long getLatencyConnect() { - return latencyConnect; - } - - private void setLatencyConnect(long latencyConnect) { - this.latencyConnect = latencyConnect; - } - - private long latencyPubSub = -1; - - /** - * Returns the latency of the send/receive during the last try. - * Returns -1 if the test failed. - * @return the latency of the send/receive during the last try. - */ - public long getLatencyPubSub() { - return latencyPubSub; - } - - private void setLatencyPubSub(long latencyPubSub) { - this.latencyPubSub = latencyPubSub; - } - - /** The maximum time waiting for connection. */ - private int timeout = 10; // in seconds - - /** - * Returns the maximum time waiting for connection. - * @return the maximum time waiting for connection. - */ - public int getTimeOut() { - return timeout; - } - - /** - * Sets the maximum time waiting for connection. - * @param timeOut the maximum time waiting for connection. - */ - public void setTimeOut(int timeOut) { - this.timeout = timeOut; - } - - /** JNDI Name of the ConnectionFactory to use. */ - private String cfname; - - public String getCFName() { - return cfname; - } - - /* User name and password for authentication */ - private String user; - private String pass; - - /* Internal name of the queue, be careful this name is not a JNDI name. */ - private String qname; - - private InitialContext ictx; - - private ConnectionFactory cf; - private Queue queue; - - /** - * Creates a new component allowing to check a JMS connector. - * - * @param cfname JNDI name of the ConnectionFactory to use. - * @param ictx JNDI context allowing to retrieve ConnectionFactory. - * @param user User name for authentication, if no defined uses the ConnectionFactory default. - * @param pass Password for authentication, if no defined uses the ConnectionFactory default. - * @param qname Internal name of JMS destination. - * @param timeout Maximum amount of time to wait connecting and receiving messages, by default 10s. - */ - public JMSConnectorCheck(String cfname, - InitialContext ictx, - String user, String pass, - String qname, - int timeOut) { - this.cfname = cfname; - this.ictx = ictx; - this.user = user; - this.pass = pass; - - this.qname = qname; - - this.timeout = timeOut; - } - - private void getConnectionFactory() throws NamingException { - if (cf != null) return; - - ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader(); - try { - Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); - cf = (ConnectionFactory) ictx.lookup(cfname); - try { - ((org.objectweb.joram.client.jms.ConnectionFactory) cf).getParameters().connectingTimer = timeout; - } catch (ClassCastException exc) { - logger.log(BasicLevel.INFO, "JMSConnectorStatus(" + cfname + "): Cannot set connectingTimer."); - } - } catch (NamingException exc) { - if (logger.isLoggable(BasicLevel.DEBUG)) - logger.log(BasicLevel.WARN, "JMSConnectorStatus(" + cfname + "): Cannot get ConnectionFactory.", exc); - else - logger.log(BasicLevel.WARN, "JMSConnectorStatus(" + cfname + "): Cannot get ConnectionFactory."); - throw exc; - } finally { - Thread.currentThread().setContextClassLoader(originalContextClassLoader); - } - } - - /** - * Checks the related JMS connector, creates a connection, then sends and receives a message. - * After the call the test results are updated. - * - * @return true if the check is successful, false otherwise. - */ - public boolean check() { - if (logger.isLoggable(BasicLevel.DEBUG)) - logger.log(BasicLevel.DEBUG, "JMSConnectorStatus(" + cfname + ").check"); - - nbtry += 1; - try { - getConnectionFactory(); - } catch (NamingException exc) { - failures += 1; - setStatus(getStatus()+1); - setLatencyConnect(-1L); - setLatencyPubSub(-1L); - errorMsg = "Cannot get ConnectionFactory"; - if (logger.isLoggable(BasicLevel.DEBUG)) - logger.log(BasicLevel.WARN, "JMSConnectorStatus.check(" + cfname + ")<: Cannot get ConnectionFactory.", exc); - else - logger.log(BasicLevel.WARN, "JMSConnectorStatus.check(" + cfname + "): Cannot get ConnectionFactory."); - return false; - } - - Connection cnx = null; - try { - long start = System.nanoTime(); - if ((user == null) || (pass == null)) - cnx = cf.createConnection(); - else - cnx = cf.createConnection(user, pass); - long dt = System.nanoTime() - start; - setLatencyConnect(dt / 1000000L); - lastConnectTime = DateFormat.getDateTimeInstance().format(new Date()); - } catch (JMSException exc) { - failures += 1; - setStatus(getStatus()+1); - setLatencyConnect(-1L); - setLatencyPubSub(-1L); - errorMsg = "Cannot connect"; - if (logger.isLoggable(BasicLevel.DEBUG)) - logger.log(BasicLevel.WARN, "JMSConnectorStatus.check(" + cfname + "): Cannot connect.", exc); - else - logger.log(BasicLevel.WARN, "JMSConnectorStatus.check(" + cfname + "): Cannot connect."); - return false; - } - - try { - Session sess = cnx.createSession(false, Session.AUTO_ACKNOWLEDGE); - if (queue == null) - queue = (Queue) sess.createQueue(qname); - MessageProducer producer = sess.createProducer(queue); - MessageConsumer cons = sess.createConsumer(queue); - cnx.start(); - - TextMessage sent = sess.createTextMessage("Test number " + nbtry); - long start = System.nanoTime(); - producer.send(sent, Message.DEFAULT_DELIVERY_MODE, Message.DEFAULT_PRIORITY, timeout *1000); - - Message received = cons.receive(timeout *1000); - long dt = System.nanoTime() - start; - if (received == null) { - failures += 1; - setStatus(getStatus()+1); - setLatencyPubSub(-1L); - errorMsg = "Message not received"; - } else { - retryStatusCount = 0; - setLatencyPubSub(dt / 1000000L); - errorMsg = null; - } - } catch (JMSException exc) { - failures += 1; - setStatus(getStatus()+1); - setLatencyPubSub(-1L); - errorMsg = "Error during message send/receive."; - if (logger.isLoggable(BasicLevel.DEBUG)) - logger.log(BasicLevel.WARN, "JMSConnectorStatus.check(" + cfname + "): Error during message send/receive.", exc); - else - logger.log(BasicLevel.WARN, "JMSConnectorStatus.check(" + cfname + "): Error during message send/receive."); - return false; - } finally { - try { - cnx.close(); - } catch (JMSException exc) { - if (logger.isLoggable(BasicLevel.DEBUG)) - logger.log(BasicLevel.WARN, "JMSConnectorStatus.check(" + cfname + "): Error closing connection.", exc); - else - logger.log(BasicLevel.WARN, "JMSConnectorStatus.check(" + cfname + "): Error closing connection."); - } - } - return true; - } -} +/* + * Copyright (C) 2020 - 2021 ScalAgent Distributed Technologies + * + * 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 + * Contributor(s): + */ +package org.ow2.joram.tools.jmscheck; + +import java.text.DateFormat; +import java.util.Date; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.naming.InitialContext; +import javax.naming.NamingException; + +import org.objectweb.joram.client.jms.Queue; + +import org.objectweb.util.monolog.api.BasicLevel; +import org.objectweb.util.monolog.api.Logger; + +import fr.dyade.aaa.common.Debug; + +/** + * Component allowing to check a JMS connector. + */ +public final class JMSConnectorCheck { + static Logger logger = Debug.getLogger(JMSConnectorCheck.class.getName()); + + public static final int RUNNING = 0; + public static final int UNREACHABLE = 1; + static final String[] info = { "RUNNING", "UNREACHABLE" }; + + /** retryStatusCount == 0 => RUNNING, retryStatusCount > 0 => UNREACHABLE */ + private int retryStatusCount = UNREACHABLE; + + /** + * Returns the status of the connector: 0 => RUNNING, >0 => UNREACHABLE. + * + * @return the number of unreachable connection + */ + public int getStatus() { + return retryStatusCount; + } + + public String getStatusInfo() { + if (retryStatusCount > 0) + return info[1] + '(' + retryStatusCount + ')'; + return info[0]; + } + + private void setStatus(int retry) { + this.retryStatusCount = retry; + } + + private int nbtry = 0; + + /** + * Returns the total number of try since starting. + * @return the total number of try since starting. + */ + public int getNbTry() { + return nbtry; + } + + private transient int failures = 0; + + /** + * Returns the total number of failures since starting. + * @return the total number of failures since starting. + */ + public int getNbFailures() { + return failures; + } + + private String errorMsg; + + /** + * Returns the error message of the last try. + * Returns null if the test is successful. + * @return + */ + public String getErrorMsg() { + return errorMsg; + } + + private String lastConnectTime = "-"; + + /** + * Returns the date of last successful connection. + * @return the date of last successful connection. + */ + public String getLastConnectTime() { + return lastConnectTime; + } + + private long latencyConnect = -1; + + /** + * Returns the latency of the connection during the last try. + * Returns -1 if the test failed. + * @return the latency of the connection during the last try. + */ + public long getLatencyConnect() { + return latencyConnect; + } + + private void setLatencyConnect(long latencyConnect) { + this.latencyConnect = latencyConnect; + } + + private long latencyPubSub = -1; + + /** + * Returns the latency of the send/receive during the last try. + * Returns -1 if the test failed. + * @return the latency of the send/receive during the last try. + */ + public long getLatencyPubSub() { + return latencyPubSub; + } + + private void setLatencyPubSub(long latencyPubSub) { + this.latencyPubSub = latencyPubSub; + } + + /** The maximum time waiting for connection. */ + private int timeout = 10; // in seconds + + /** + * Returns the maximum time waiting for connection. + * @return the maximum time waiting for connection. + */ + public int getTimeOut() { + return timeout; + } + + /** + * Sets the maximum time waiting for connection. + * @param timeOut the maximum time waiting for connection. + */ + public void setTimeOut(int timeOut) { + this.timeout = timeOut; + } + + /** JNDI Name of the ConnectionFactory to use. */ + private String cfname; + + public String getCFName() { + return cfname; + } + + /* User name and password for authentication */ + private String user; + private String pass; + + /* Internal name of the queue, be careful this name is not a JNDI name. */ + private String qname; + + private InitialContext ictx; + + private ConnectionFactory cf; + private Queue queue; + + /** + * Creates a new component allowing to check a JMS connector. + * + * @param cfname JNDI name of the ConnectionFactory to use. + * @param ictx JNDI context allowing to retrieve ConnectionFactory. + * @param user User name for authentication, if no defined uses the ConnectionFactory default. + * @param pass Password for authentication, if no defined uses the ConnectionFactory default. + * @param qname Internal name of JMS destination. + * @param timeout Maximum amount of time to wait connecting and receiving messages, by default 10s. + */ + public JMSConnectorCheck(String cfname, + InitialContext ictx, + String user, String pass, + String qname, + int timeOut) { + this.cfname = cfname; + this.ictx = ictx; + this.user = user; + this.pass = pass; + + this.qname = qname; + + this.timeout = timeOut; + } + + private void getConnectionFactory() throws NamingException { + if (cf != null) return; + + ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); + cf = (ConnectionFactory) ictx.lookup(cfname); + try { + ((org.objectweb.joram.client.jms.ConnectionFactory) cf).getParameters().connectingTimer = timeout; + } catch (ClassCastException exc) { + logger.log(BasicLevel.INFO, "JMSConnectorStatus(" + cfname + "): Cannot set connectingTimer."); + } + } catch (NamingException exc) { + if (logger.isLoggable(BasicLevel.DEBUG)) + logger.log(BasicLevel.WARN, "JMSConnectorStatus(" + cfname + "): Cannot get ConnectionFactory.", exc); + else + logger.log(BasicLevel.WARN, "JMSConnectorStatus(" + cfname + "): Cannot get ConnectionFactory."); + throw exc; + } finally { + Thread.currentThread().setContextClassLoader(originalContextClassLoader); + } + } + + /** + * Checks the related JMS connector, creates a connection, then sends and receives a message. + * After the call the test results are updated. + * + * @return true if the check is successful, false otherwise. + */ + public boolean check() { + if (logger.isLoggable(BasicLevel.DEBUG)) + logger.log(BasicLevel.DEBUG, "JMSConnectorStatus(" + cfname + ").check"); + + nbtry += 1; + try { + getConnectionFactory(); + } catch (NamingException exc) { + failures += 1; + setStatus(getStatus()+1); + setLatencyConnect(-1L); + setLatencyPubSub(-1L); + errorMsg = "Cannot get ConnectionFactory"; + if (logger.isLoggable(BasicLevel.DEBUG)) + logger.log(BasicLevel.WARN, "JMSConnectorStatus.check(" + cfname + ")<: Cannot get ConnectionFactory.", exc); + else + logger.log(BasicLevel.WARN, "JMSConnectorStatus.check(" + cfname + "): Cannot get ConnectionFactory."); + return false; + } + + Connection cnx = null; + try { + long start = System.nanoTime(); + if ((user == null) || (pass == null)) + cnx = cf.createConnection(); + else + cnx = cf.createConnection(user, pass); + long dt = System.nanoTime() - start; + setLatencyConnect(dt / 1000000L); + lastConnectTime = DateFormat.getDateTimeInstance().format(new Date()); + } catch (JMSException exc) { + failures += 1; + setStatus(getStatus()+1); + setLatencyConnect(-1L); + setLatencyPubSub(-1L); + errorMsg = "Cannot connect"; + if (logger.isLoggable(BasicLevel.DEBUG)) + logger.log(BasicLevel.WARN, "JMSConnectorStatus.check(" + cfname + "): Cannot connect.", exc); + else + logger.log(BasicLevel.WARN, "JMSConnectorStatus.check(" + cfname + "): Cannot connect."); + return false; + } + + try { + Session sess = cnx.createSession(false, Session.AUTO_ACKNOWLEDGE); + if (queue == null) + queue = (Queue) sess.createQueue(qname); + MessageProducer producer = sess.createProducer(queue); + MessageConsumer cons = sess.createConsumer(queue); + cnx.start(); + + TextMessage sent = sess.createTextMessage("Test number " + nbtry); + long start = System.nanoTime(); + producer.send(sent, Message.DEFAULT_DELIVERY_MODE, Message.DEFAULT_PRIORITY, timeout *1000); + + Message received = cons.receive(timeout *1000); + long dt = System.nanoTime() - start; + if (received == null) { + failures += 1; + setStatus(getStatus()+1); + setLatencyPubSub(-1L); + errorMsg = "Message not received"; + return false; + } else { + retryStatusCount = 0; + setLatencyPubSub(dt / 1000000L); + errorMsg = null; + return true; + } + } catch (JMSException exc) { + failures += 1; + setStatus(getStatus()+1); + setLatencyPubSub(-1L); + errorMsg = "Error during message send/receive."; + if (logger.isLoggable(BasicLevel.DEBUG)) + logger.log(BasicLevel.WARN, "JMSConnectorStatus.check(" + cfname + "): Error during message send/receive.", exc); + else + logger.log(BasicLevel.WARN, "JMSConnectorStatus.check(" + cfname + "): Error during message send/receive."); + return false; + } finally { + try { + cnx.close(); + } catch (JMSException exc) { + if (logger.isLoggable(BasicLevel.DEBUG)) + logger.log(BasicLevel.WARN, "JMSConnectorStatus.check(" + cfname + "): Error closing connection.", exc); + else + logger.log(BasicLevel.WARN, "JMSConnectorStatus.check(" + cfname + "): Error closing connection."); + } + } + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("JMSConnectorCheck [") + .append("cfname=").append(cfname) + .append(", user=").append(user) + .append(", pass=****") + .append(", qname=").append(qname) + .append(", timeout=").append(timeout) + .append("] -> [") + .append("retryStatusCount=").append(retryStatusCount) + .append(", nbtry=").append(nbtry) + .append(", errorMsg=").append(errorMsg) + .append(", lastConnectTime=").append(lastConnectTime) + .append(", latencyConnect=").append(latencyConnect) + .append(", latencyPubSub=").append(latencyPubSub) + .append("]"); + return builder.toString(); + } +}