Commit de028c6f authored by Andre Freyssinet's avatar Andre Freyssinet

Marks the class final.

parent a4fc7dca
/* /*
* Copyright (C) 2020 ScalAgent Distributed Technologies * Copyright (C) 2020 - 2021 ScalAgent Distributed Technologies
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -57,7 +57,8 @@ import fr.dyade.aaa.common.Debug; ...@@ -57,7 +57,8 @@ import fr.dyade.aaa.common.Debug;
* </ul> * </ul>
* If there are multiple connectors to monitor, suffix each property with 1, 2, etc. * If there are multiple connectors to monitor, suffix each property with 1, 2, etc.
*/ */
public class Activator implements BundleActivator {
public final class Activator implements BundleActivator {
public static final Logger logger = Debug.getLogger(Activator.class.getName()); public static final Logger logger = Debug.getLogger(Activator.class.getName());
public final static String CHECK_PREFIX = "org.ow2.joram.check."; public final static String CHECK_PREFIX = "org.ow2.joram.check.";
......
/* /*
* Copyright (C) 2020 ScalAgent Distributed Technologies * Copyright (C) 2020 - 2021 ScalAgent Distributed Technologies
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -68,7 +68,7 @@ import fr.dyade.aaa.common.Debug; ...@@ -68,7 +68,7 @@ import fr.dyade.aaa.common.Debug;
* CONF_FILE property. In this case the other properties defined in the command * CONF_FILE property. In this case the other properties defined in the command
* line are ignored. * line are ignored.
*/ */
public class JMSCheck { public final class JMSCheck {
public static final Logger logger = Debug.getLogger(JMSCheck.class.getName()); public static final Logger logger = Debug.getLogger(JMSCheck.class.getName());
public final static String GLOBAL_PERIOD = "PERIOD"; public final static String GLOBAL_PERIOD = "PERIOD";
......
/*
* 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 ScalAgent Distributed Technologies * Copyright (C) 2020 - 2021 ScalAgent Distributed Technologies
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -21,109 +21,65 @@ ...@@ -21,109 +21,65 @@
*/ */
package org.ow2.joram.tools.jmscheck; package org.ow2.joram.tools.jmscheck;
import java.text.DateFormat;
import java.util.Date;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.jms.Connection;
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.InitialContext;
import javax.naming.NamingException;
import org.objectweb.joram.client.jms.ConnectionFactory;
import org.objectweb.joram.client.jms.Queue;
import org.objectweb.util.monolog.api.BasicLevel; import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger; import org.objectweb.util.monolog.api.Logger;
import fr.dyade.aaa.common.Debug; import fr.dyade.aaa.common.Debug;
import fr.dyade.aaa.util.management.MXWrapper; import fr.dyade.aaa.util.management.MXWrapper;
class JMSConnectorStatus implements JMSConnectorStatusMBean { final class JMSConnectorStatus implements JMSConnectorStatusMBean {
static Logger logger = Debug.getLogger(JMSConnectorStatus.class.getName()); static Logger logger = Debug.getLogger(JMSConnectorStatus.class.getName());
public static final int RUNNING = 0; private JMSConnectorCheck check;
public static final int UNREACHABLE = 1;
static String[] info = { "RUNNING", "UNREACHABLE" };
/** retryStatusCount == 0 => RUNNING, retryStatusCount > 0 => UNREACHABLE */
private int retryStatusCount = UNREACHABLE;
@Override @Override
public int getStatus() { public int getStatus() {
return retryStatusCount; return check.getStatus();
} }
@Override @Override
public String getStatusInfo() { public String getStatusInfo() {
if (retryStatusCount > 0) return check.getStatusInfo();
return info[1] + '(' + retryStatusCount + ')';
return info[0];
} }
void setStatus(int retry) {
JMSStatus.checkDump(cfname, retry);
this.retryStatusCount = retry;
}
private int nbtry = 0;
@Override @Override
public int getNbTry() { public int getNbTry() {
return nbtry; return check.getNbTry();
} }
private transient int failures = 0;
@Override @Override
public int getNbFailures() { public int getNbFailures() {
return failures; return check.getNbFailures();
} }
private String errorMsg;
@Override @Override
public String getErrorMsg() { public String getErrorMsg() {
return errorMsg; return check.getErrorMsg();
} }
private long latencyConnect = -1;
@Override @Override
public long getLatencyConnect() { public long getLatencyConnect() {
return latencyConnect; return check.getLatencyConnect();
} }
private void setLatencyConnect(long latencyConnect) {
this.latencyConnect = latencyConnect;
}
private String lastConnectTime = "-";
@Override @Override
public String getLastConnectTime() { public String getLastConnectTime() {
return lastConnectTime; return check.getLastConnectTime();
} }
private long latencyPubSub = -1;
@Override @Override
public long getLatencyPubSub() { public long getLatencyPubSub() {
return latencyPubSub; return check.getLatencyConnect();
}
private void setLatencyPubSub(long latencyPubSub) {
this.latencyPubSub = latencyPubSub;
} }
/** The period of time between 2 checks. */ /** The period of time between 2 checks (in seconds). */
private int period = 60; // in seconds private int period = 60;
@Override @Override
public int getPeriod() { public int getPeriod() {
return period; return period;
...@@ -134,8 +90,8 @@ class JMSConnectorStatus implements JMSConnectorStatusMBean { ...@@ -134,8 +90,8 @@ class JMSConnectorStatus implements JMSConnectorStatusMBean {
try { try {
if (period < 5) if (period < 5)
period = 5; period = 5;
if (period < (2* timeout)) if (period < (2* check.getTimeOut()))
period = 2* timeout; period = 2* check.getTimeOut();
this.period = period; this.period = period;
schedule(); schedule();
} catch (Exception e) { } catch (Exception e) {
...@@ -143,47 +99,24 @@ class JMSConnectorStatus implements JMSConnectorStatusMBean { ...@@ -143,47 +99,24 @@ class JMSConnectorStatus implements JMSConnectorStatusMBean {
} }
} }
/** The maximum time waiting for connection. */
private int timeout = 10; // in seconds
@Override @Override
public int getTimeOut() { public int getTimeOut() {
return timeout; return check.