Commit 933b8b48 authored by Andre Freyssinet's avatar Andre Freyssinet

Enhancements allowing to use the component from an external way.

parent 4e228218
/*
* Copyright (C) 2020 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 javax.naming.InitialContext;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import fr.dyade.aaa.agent.AgentServer;
import fr.dyade.aaa.common.Debug;
/**
* This component regularly tests the state of a JMS connector and publishes the results to JMX.
* <br>
* It is configured through a set of OSGi properties:<ul>
* <li>org.ow2.joram.check.jndi.file: Path of JNDI properties file. If not defined, Joram's
* default are used. "fr.dyade.aaa.jndi2.client.NamingContextFactory" for JNDI Factory,
* "localhost", and 16400 for host and port.<br>
* These values can be overloaded by specific properties below.</li>
* <li>org.ow2.joram.check.jndi.factory: Classname of the JNDI factory (cf java.naming.factory.initial
* property).</li>
* <li>org.ow2.joram.check.jndi.host: Hostname ou IP address of JNDI server.</li>
* <li>org.ow2.joram.check.jndi.port: Listening port of JNDI server.</li>
* <li>org.ow2.joram.check.period: Period between 2 checks, by default 60s.</li>
* <li>org.ow2.joram.check.timeout: Maximum amount of time to wait connecting and receiving
* messages, by default 10s.</li>
* </ul>
* For each JMS connector to monitor there is 4 properties to define:<ul>
* <li>org.ow2.joram.check.cf: JNDI name of the ConnectionFactory to use.</li>
* <li>org.ow2.joram.check.queue: Internal name of JMS destination.</li>
* <li>org.ow2.joram.check.user: User name for authentication, if no defined uses the
* ConnectionFactory default.</li>
* <li>org.ow2.joram.check.pass: Password for authentication, if no defined uses the
* ConnectionFactory default.</li>
* </ul>
* If there are multiple connectors to monitor, suffix each property with 1, 2, etc.
*/
public class Activator implements BundleActivator {
public static final Logger logger = Debug.getLogger(Activator.class.getName());
public final static String CHECK_PREFIX = "org.ow2.joram.check.";
public final static String GLOBAL_PERIOD = CHECK_PREFIX + "period";
public final static String GLOBAL_TIMEOUT = CHECK_PREFIX + "timeout";
public final static String DUMP_FILE = CHECK_PREFIX + "dump.file";
public final static String DUMP_THRESHOLD = CHECK_PREFIX + "dump.threshold";
public final static String DUMP_DELAY = CHECK_PREFIX + "dump.delay";
public final static String JNDI_FILE = CHECK_PREFIX + "jndi.file";
public final static String JNDI_FACTORY = CHECK_PREFIX + "jndi.factory";
public final static String JNDI_HOST = CHECK_PREFIX + "jndi.host";
public final static String JNDI_PORT = CHECK_PREFIX + "jndi.port";
public static final String CF_NAME = CHECK_PREFIX + "cf";
public static final String USER_NAME = CHECK_PREFIX + "user";
public static final String PASSWORD = CHECK_PREFIX + "password";
public static final String QUEUE_NAME = CHECK_PREFIX + "queue";
private static BundleContext context;
public Activator() {
}
int period, timeout;
JMSStatus jmsStatus;
@Override
public void start(BundleContext context) throws Exception {
Activator.context = context;
// Gets the global period.
period = JMSStatus.DFLT_PERIOD;
String value = context.getProperty(GLOBAL_PERIOD);
if (value != null) {
try {
period = Integer.parseInt(value);
} catch (NumberFormatException exc) {
logger.log(BasicLevel.WARN,
"MqttCheckActivator.start: bad value for property " + GLOBAL_PERIOD + ", set to default.");
period = JMSStatus.DFLT_PERIOD;
}
}
if (period <= 0) return;
// Gets the global timeout.
timeout = JMSStatus.DFLT_TIMEOUT;
value = context.getProperty(GLOBAL_TIMEOUT);
if (value != null) {
try {
timeout = Integer.parseInt(value);
} catch (NumberFormatException exc) {
logger.log(BasicLevel.WARN,
"MqttCheckActivator.start: bad value for property " + GLOBAL_TIMEOUT + ", set to default.");
timeout = JMSStatus.DFLT_TIMEOUT;
}
}
// Gets the pathname of the dump file.
String dumpFilePath = context.getProperty(DUMP_FILE);
if (dumpFilePath == null) {
dumpFilePath = JMSStatus.DFLT_DUMP_FILE;
}
// Gets the threshold to generate a dump file.
int threshold = JMSStatus.DFLT_THRESHOLD;
value = context.getProperty(DUMP_THRESHOLD);
if (value != null) {
try {
threshold = Integer.parseInt(value);
} catch (NumberFormatException exc) {
logger.log(BasicLevel.WARN,
"MqttCheckActivator.start: bad value for property " + DUMP_THRESHOLD + ", set to default.");
threshold = JMSStatus.DFLT_THRESHOLD;
}
}
// Gets the minimal delay before to generate anew a dump file.
int delay = JMSStatus.DFLT_DELAY;
value = context.getProperty(DUMP_DELAY);
if (value != null) {
try {
delay = Integer.parseInt(value);
} catch (NumberFormatException exc) {
logger.log(BasicLevel.WARN,
"MqttCheckActivator.start: bad value for property " + DUMP_DELAY + ", set to default.");
delay = JMSStatus.DFLT_DELAY;
}
}
jmsStatus = new JMSStatus("Joram#" + AgentServer.getServerId(), period, timeout, dumpFilePath, threshold, delay);
String jndiFile = context.getProperty(JNDI_FILE);
String jndiFactory = context.getProperty(JNDI_FACTORY);
String jndiHost = context.getProperty(JNDI_HOST);
String jndiPort = context.getProperty(JNDI_PORT);
InitialContext ictx = jmsStatus.getInitialContext(jndiFile, jndiFactory, jndiHost, jndiPort);
createConnector(jmsStatus, "", ictx);
for (int i=1;; i++) {
if (!createConnector(jmsStatus, "." + i, ictx)) break;
}
jmsStatus.start();
}
// public synchronized Object lookup(String name) throws NamingException {
// if (logger.isLoggable(BasicLevel.DEBUG))
// logger.log(BasicLevel.DEBUG, "Helper.lookup " + name);
//
// ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
// try {
// Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
//
// if (ictx == null)
// ictx = new InitialContext(jndiProps);
// return ictx.lookup(name);
// } finally {
// Thread.currentThread().setContextClassLoader(originalContextClassLoader);
// }
// }
/**
* Adds a new check component using the related properties.
*
* @param check The root component.
* @param suffix The property suffix.
* @param ictx The InitialContext to use.
* @return True if the component is successively created.
*/
private boolean createConnector(JMSStatus check, String suffix, InitialContext ictx) {
String cfname = context.getProperty(CF_NAME + suffix);
if (cfname != null) {
String user = context.getProperty(USER_NAME + suffix);
String pass = context.getProperty(PASSWORD + suffix);
String qname = context.getProperty(QUEUE_NAME + suffix);
// TODO (AF): Allow to override period and timeout.
check.addConnectorStatus(cfname, ictx, user, pass, qname, period, timeout);
return true;
}
return false;
}
@Override
public void stop(BundleContext context) throws Exception {
context = null;
jmsStatus.stop();
}
}
/*
* 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 javax.naming.InitialContext;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import fr.dyade.aaa.agent.AgentServer;
import fr.dyade.aaa.common.Debug;
/**
* This component regularly tests the state of a JMS connector and publishes the results to JMX.
* <br>
* It is configured through a set of OSGi properties:<ul>
* <li>org.ow2.joram.check.jndi.file: Path of JNDI properties file. If not defined, Joram's
* default are used. "fr.dyade.aaa.jndi2.client.NamingContextFactory" for JNDI Factory,
* "localhost", and 16400 for host and port.<br>
* These values can be overloaded by specific properties below.</li>
* <li>org.ow2.joram.check.jndi.factory: Classname of the JNDI factory (cf java.naming.factory.initial
* property).</li>
* <li>org.ow2.joram.check.jndi.host: Hostname ou IP address of JNDI server.</li>
* <li>org.ow2.joram.check.jndi.port: Listening port of JNDI server.</li>
* <li>org.ow2.joram.check.period: Period between 2 checks, by default 60s.</li>
* <li>org.ow2.joram.check.timeout: Maximum amount of time to wait connecting and receiving
* messages, by default 10s.</li>
* </ul>
* For each JMS connector to monitor there is 4 properties to define:<ul>
* <li>org.ow2.joram.check.cf: JNDI name of the ConnectionFactory to use.</li>
* <li>org.ow2.joram.check.queue: Internal name of JMS destination.</li>
* <li>org.ow2.joram.check.user: User name for authentication, if no defined uses the
* ConnectionFactory default.</li>
* <li>org.ow2.joram.check.pass: Password for authentication, if no defined uses the
* ConnectionFactory default.</li>
* </ul>
* If there are multiple connectors to monitor, suffix each property with 1, 2, etc.
*/
public final class Activator implements BundleActivator {
public static final Logger logger = Debug.getLogger(Activator.class.getName());
public final static String CHECK_PREFIX = "org.ow2.joram.check.";
public final static String GLOBAL_PERIOD = CHECK_PREFIX + "period";
public final static String GLOBAL_TIMEOUT = CHECK_PREFIX + "timeout";
public final static String DUMP_FILE = CHECK_PREFIX + "dump.file";
public final static String DUMP_THRESHOLD = CHECK_PREFIX + "dump.threshold";
public final static String DUMP_DELAY = CHECK_PREFIX + "dump.delay";
public final static String JNDI_FILE = CHECK_PREFIX + "jndi.file";
public final static String JNDI_FACTORY = CHECK_PREFIX + "jndi.factory";
public final static String JNDI_HOST = CHECK_PREFIX + "jndi.host";
public final static String JNDI_PORT = CHECK_PREFIX + "jndi.port";
public static final String CF_NAME = CHECK_PREFIX + "cf";
public static final String USER_NAME = CHECK_PREFIX + "user";
public static final String PASSWORD = CHECK_PREFIX + "password";
public static final String QUEUE_NAME = CHECK_PREFIX + "queue";
private static BundleContext context;
public Activator() {
}
int period, timeout;
JMSStatus jmsStatus;
@Override
public void start(BundleContext context) throws Exception {
Activator.context = context;
// Gets the global period.
period = JMSStatus.DFLT_PERIOD;
String value = context.getProperty(GLOBAL_PERIOD);
if (value != null) {
try {
period = Integer.parseInt(value);
} catch (NumberFormatException exc) {
logger.log(BasicLevel.WARN,
"MqttCheckActivator.start: bad value for property " + GLOBAL_PERIOD + ", set to default.");
period = JMSStatus.DFLT_PERIOD;
}
}
if (period <= 0) return;
// Gets the global timeout.
timeout = JMSStatus.DFLT_TIMEOUT;
value = context.getProperty(GLOBAL_TIMEOUT);
if (value != null) {
try {
timeout = Integer.parseInt(value);
} catch (NumberFormatException exc) {
logger.log(BasicLevel.WARN,
"MqttCheckActivator.start: bad value for property " + GLOBAL_TIMEOUT + ", set to default.");
timeout = JMSStatus.DFLT_TIMEOUT;
}
}
// Gets the pathname of the dump file.
String dumpFilePath = context.getProperty(DUMP_FILE);
if (dumpFilePath == null) {
dumpFilePath = JMSStatus.DFLT_DUMP_FILE;
}
// Gets the threshold to generate a dump file.
int threshold = JMSStatus.DFLT_THRESHOLD;
value = context.getProperty(DUMP_THRESHOLD);
if (value != null) {
try {
threshold = Integer.parseInt(value);
} catch (NumberFormatException exc) {
logger.log(BasicLevel.WARN,
"MqttCheckActivator.start: bad value for property " + DUMP_THRESHOLD + ", set to default.");
threshold = JMSStatus.DFLT_THRESHOLD;
}
}
// Gets the minimal delay before to generate anew a dump file.
int delay = JMSStatus.DFLT_DELAY;
value = context.getProperty(DUMP_DELAY);
if (value != null) {
try {
delay = Integer.parseInt(value);
} catch (NumberFormatException exc) {
logger.log(BasicLevel.WARN,
"MqttCheckActivator.start: bad value for property " + DUMP_DELAY + ", set to default.");
delay = JMSStatus.DFLT_DELAY;
}
}
jmsStatus = new JMSStatus("Joram#" + AgentServer.getServerId(), period, timeout, dumpFilePath, threshold, delay);
String jndiFile = context.getProperty(JNDI_FILE);
String jndiFactory = context.getProperty(JNDI_FACTORY);
String jndiHost = context.getProperty(JNDI_HOST);
String jndiPort = context.getProperty(JNDI_PORT);
InitialContext ictx = jmsStatus.getInitialContext(jndiFile, jndiFactory, jndiHost, jndiPort);
createConnector(jmsStatus, "", ictx);
for (int i=1;; i++) {
if (!createConnector(jmsStatus, "." + i, ictx)) break;
}
jmsStatus.start();
}
// public synchronized Object lookup(String name) throws NamingException {
// if (logger.isLoggable(BasicLevel.DEBUG))
// logger.log(BasicLevel.DEBUG, "Helper.lookup " + name);
//
// ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
// try {
// Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
//
// if (ictx == null)
// ictx = new InitialContext(jndiProps);
// return ictx.lookup(name);
// } finally {
// Thread.currentThread().setContextClassLoader(originalContextClassLoader);
// }
// }
/**
* Adds a new check component using the related properties.
*
* @param check The root component.
* @param suffix The property suffix.
* @param ictx The InitialContext to use.
* @return True if the component is successively created.
*/
private boolean createConnector(JMSStatus check, String suffix, InitialContext ictx) {
String cfname = context.getProperty(CF_NAME + suffix);
if (cfname != null) {
String user = context.getProperty(USER_NAME + suffix);
String pass = context.getProperty(PASSWORD + suffix);
String qname = context.getProperty(QUEUE_NAME + suffix);
// TODO (AF): Allow to override period and timeout.
check.addConnectorStatus(cfname, ictx, user, pass, qname, period, timeout);
return true;
}
return false;
}
@Override
public void stop(BundleContext context) throws Exception {
context = null;
jmsStatus.stop();
}
}
/*
* Copyright (C) 2020 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.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import javax.naming.InitialContext;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import fr.dyade.aaa.common.Debug;
/**
* This client regularly tests the state of a JMS connector and publishes the results to JMX.
* <br><br>
* usage: java -DJNDI_FILE=./jndi.properties -DPERIOD=1 -DTIMEOUT=5000<br>
* <dd>-DCF=cf -DQUEUE=queue</dd>
* <dd>-jar jmscheck.jar [help]</dd>
* <br>
* Options, set by Java environment variable ("-Dproperty=value" in command line):<ul>
* <li>JNDI_FILE: Path of JNDI properties file. If not defined, Joram's default are
* used. "fr.dyade.aaa.jndi2.client.NamingContextFactory" for JNDI Factory,
* "localhost", and 16400 for host and port.<br>
* These values can be overloaded by specific properties below.</li>
* <li>JNDI_FACTORY: Classname of the JNDI factory (cf java.naming.factory.initial
* property).</li>
* <li>JNDI_HOST: Hostname ou IP address of JNDI server.</li>
* <li>JNDI_PORT: Listening port of JNDI server.</li>
*
* <li>PERIOD: Period between 2 checks, by default 60s.</li>
* <li>TIMEOUT: Maximum amount of time to wait connecting and receiving messages,
* by default 10s.</li>
* <br>
* For each JMS connector to monitor there is 4 properties to define:<ul>
* <li>CF: JNDI name of the ConnectionFactory to use.</li>
* <li>QUEUE: Internal name of JMS destination.</li>
* <li>USER: User name for authentication, if no defined uses the ConnectionFactory
* default.</li>
* <li>PASS: Password for authentication, if no defined uses the ConnectionFactory
* default.</li>
* </ul>
* If there are multiple connectors to monitor, suffix each property with 1, 2,
* 3, etc.
* <br>
* All these properties can be defined in a file whose name is given by the
* CONF_FILE property. In this case the other properties defined in the command
* line are ignored.
*/
public class JMSCheck {
public static final Logger logger = Debug.getLogger(JMSCheck.class.getName());
public final static String GLOBAL_PERIOD = "PERIOD";
public final static String GLOBAL_TIMEOUT = "TIMEOUT";
public static final String JNDI_FILE = "JNDI_FILE";
public static final String JNDI_FACTORY = "JNDI_FACTORY";
public static final String JNDI_HOST = "JNDI_HOST";
public static final String JNDI_PORT = "JNDI_PORT";
public static final String CF_NAME = "CF";
public static final String USER_NAME = "USER";
public static final String PASSWORD = "PASS";
public static final String QUEUE_NAME = "QUEUE";
public static final String CONF_FILE = "CONF_FILE";
static int period, timeout;
static JMSStatus jmsStatus;
public static void main(String[] args) throws Exception {
if (args.length != 0) {
System.out.println("usage: java -DJNDI_FILE=./jndi.properties -DPERIOD=1 -DTIMEOUT=5000\n" +
"\t-DCF=cf -DQUEUE=queue\n" +
"\t-jar jmscheck.jar [help]\n");
System.err.println("Options, set by Java environment variable (\"-Dproperty=value\" in command line)");
System.err.println(" - JNDI_FILE: Path of JNDI properties file. If not defined, Joram's default are\n" +
" used. \"fr.dyade.aaa.jndi2.client.NamingContextFactory\" for JNDI Factory,\n" +
" \"localhost\", and 16400 for host and port.\n" +
" These values can be overloaded by specific properties below.");
System.err.println(" - JNDI_FACTORY: Classname of the JNDI factory (cf java.naming.factory.initial\n" +
" property).");
System.err.println(" - JNDI_HOST: Hostname ou IP address of JNDI server.");
System.err.println(" - JNDI_PORT: Listening port of JNDI server.\n");
System.err.println(" - PERIOD: Period between 2 checks, by default 60s.");
System.err.println(" - TIMEOUT: Maximum amount of time to wait connecting and receiving messages,\n" +
" by default 10s.\n");
System.err.println("For each JMS connector to monitor there is 4 properties to define:");
System.err.println(" - CF: JNDI name of the ConnectionFactory to use.");
System.err.println(" - QUEUE: Internal name of JMS destination.");
System.err.println(" - USER: User name for authentication, if no defined uses the ConnectionFactory\n" +
" default.");
System.err.println(" - PASS: Password for authentication, if no defined uses the ConnectionFactory\n" +
" default.");
System.err.println("If there are multiple connectors to monitor, suffix each property with 1, 2, \n" +
" 3, etc.\n");
System.err.println("All these properties can be defined in a file whose name is given by the \n" +
"CONF_FILE property. In this case the other properties defined in the command\n" +
"line are ignored.");
System.exit(0);
}
String conf = System.getProperty(CONF_FILE);
Properties props = null;
if (conf != null) {
try {
props = new Properties();
props.load(new FileInputStream(conf));
} catch (IOException exc) {
System.err.println("Cannot read properties from \"" + conf + "\": " + exc.getMessage());
System.exit(-1);
}
} else {
props = System.getProperties();
}
// Gets the global period.
period = JMSStatus.DFLT_PERIOD;
String value = props.getProperty(GLOBAL_PERIOD);
if (value != null) {
try {
period = Integer.parseInt(value);
} catch (NumberFormatException exc) {
logger.log(BasicLevel.WARN,
"MqttCheckActivator.start: bad value for property " + GLOBAL_PERIOD + ", set to default.");
period = JMSStatus.DFLT_PERIOD;
}