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

org.objectweb.jonas.jmx.JmxServiceImpl Maven / Gradle / Ivy

/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2007 Bull S.A.S.
 * Contact: [email protected]
 *
 * 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
 *
 * --------------------------------------------------------------------------
 * $Id:JmxServiceImpl.java 10348 2007-05-10 08:32:03Z sauthieg $
 * --------------------------------------------------------------------------
 */

package org.objectweb.jonas.jmx;

import java.lang.reflect.Method;
import java.net.URI;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import javax.naming.Context;
import javax.naming.InitialContext;

import org.objectweb.jonas.common.Log;
import org.objectweb.jonas.jmx.oname.J2eeObjectName;
import org.objectweb.jonas.jmx.oname.JonasObjectName;
import org.objectweb.jonas.registry.RegistryService;
import org.objectweb.jonas.service.JonasAlreadyStartedException;
import org.objectweb.jonas.service.ServiceException;
import org.objectweb.jonas.service.manager.ServiceManager;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;

/**
 * JMX Service implementation. Provides specific doStart() and doStop () methods
 * to start /stop JOnAS JMX Service.
 * @author Adriana Danes.
 */
public class JmxServiceImpl extends AbsJmxServiceImpl {

    /**
     * MX4J CommonsLogger fully qualified Classname
     */
    private static final String MX4J_COMMONS_LOGGER_CLASSNAME = "mx4j.log.CommonsLogger";

    /**
     * MX4J Log class
     */
    private static final String MX4J_LOG_CLASSNAME = "mx4j.log.Log";

    /**
     * MX4J Logger class
     */
    private static final String MX4J_LOGGER_CLASS = "mx4j.log.Logger";


    /**
     * Connector servers attached to the MBean server. We may have several
     * connector servers only if several communication protocols are used, as
     * defined by the carol configuration.
     */
    private JMXConnectorServer[] connectorServers = null;

    /**
     * The JMXServiceURLs the connector servers are actually listening on.
     */
    private JMXServiceURL[] connectorServerURLs = null;

    /**
     * Management loggers
     */
    private static Logger logger = Log.getLogger(Log.JONAS_JMX_PREFIX);

    /**
     * JOnAS Registry Service.
     */
    private RegistryService registryService = null;

    /**
     * List of Connector ObjectName (1 / protocol)
     */
    private List connectorObjectNames = null;

    /**
     * Init the logger and then use super method.
     * @param ctx configuration for the init method
     * @throws ServiceException if initialization failed
     */
    public void doInit(Context ctx) throws ServiceException {
        // Init MX4J
        initializeMX4JLoggingSystem();

        // Delegate init work
        super.doInit(ctx);

        // Get the registry service
        try {
            ServiceManager manager = ServiceManager.getInstance();
            registryService = (RegistryService) manager.getRegistryService();
        } catch (ServiceException se) {
            logger.log(BasicLevel.ERROR, "Cannot get 'registry' service instance.");
            throw se;
        }
    }

    /**
     * Test if MX4J CommonsLoggger class is present.
     * In this case, redirect MX4J logging to Jakarta Commons Logging.
     */
    private void initializeMX4JLoggingSystem() {

        Class mx4jCommonsLoggerClass = null;
        try {
            mx4jCommonsLoggerClass = Thread.currentThread().getContextClassLoader().loadClass(
                    MX4J_COMMONS_LOGGER_CLASSNAME);
            if (logger.isLoggable(BasicLevel.DEBUG)) {
                logger.log(BasicLevel.DEBUG, "Class " + MX4J_COMMONS_LOGGER_CLASSNAME + " founded");
            }
            Object o = mx4jCommonsLoggerClass.newInstance();

            // Load Log a Logger class
            Class clazz = Thread.currentThread().getContextClassLoader().loadClass(MX4J_LOG_CLASSNAME);
            Class mx4jLoggerClass = Thread.currentThread().getContextClassLoader().loadClass(MX4J_LOGGER_CLASS);

            // Then get method redirectTo
            Method m = clazz.getMethod("redirectTo", new Class[] {mx4jLoggerClass});
            m.invoke(clazz, new Object[] {o});
            if (logger.isLoggable(BasicLevel.DEBUG)) {
                logger.log(BasicLevel.DEBUG, "MX4J logging redirected to the Jakarta commons logger");
            }
        } catch (ClassNotFoundException cnfe) {
            if (logger.isLoggable(BasicLevel.DEBUG)) {
                logger.log(BasicLevel.DEBUG, "Class " + MX4J_COMMONS_LOGGER_CLASSNAME + " not found: " + cnfe);
            }
        } catch (Exception e) {
            if (logger.isLoggable(BasicLevel.WARN)) {
                logger.log(BasicLevel.WARN, "Problem with " + MX4J_COMMONS_LOGGER_CLASSNAME + " instance creation "
                                + e);
            }
        }
    }

    /**
     * Start the Service. Only need to create a RMI connector
     * @exception ServiceException the service could not be started
     */
    public void doStart() throws ServiceException {
        // Server name
        String serverName = getJonasServerName();

        // Store the default protocol name
        String defaultProtocolName = registryService.getDefaultProtocolName();

        try {

            // Create one or more connector servers
            // (cf. JSR 160, JMX Remote 1.0)
            // Create a JMXServiceURL and a JMXConnectorServer per protocol
            // As some protocols does not have associated connectors, the
            // 2 arrays below may have null values
            // ------------------------------------
            List protocols = registryService.getActiveProtocolNames();
            int nbProtocols = protocols.size();
            connectorServerURLs = new JMXServiceURL[nbProtocols];
            connectorServers = new JMXConnectorServer[nbProtocols];
            connectorObjectNames = new ArrayList();

            int index = 0;
            for (Iterator i = protocols.iterator(); i.hasNext();) {

                // Protocol name
                String name = (String) i.next();

                // Connector JNDI name
                String connectorName = null;

                // Use this protocol as the new default
                registryService.setDefaultProtocol(name);

                // Only IIOP do not use the rmi protocol in the URL
                String protocol = "rmi";

                URI carolURL = registryService.getProviderURL(name);
                String scheme = carolURL.getScheme();
                String host = carolURL.getHost();
                int port = registryService.getExportedObjectPort(name);

                String ictxFactory = registryService.getInitialContextFactoryName(name);

                Properties props = new Properties();

                // - Set the "jmx.remote.jndi.rebind" to ask the JMX impl to do
                // a rebind() rather than a bind() in the registry
                props.put("jmx.remote.jndi.rebind", "true");
                props.put(Context.INITIAL_CONTEXT_FACTORY, ictxFactory);
                props.put(Context.PROVIDER_URL, carolURL.toString());

                JMXServiceURL serviceURL = null;

                if (name.equals("jrmp")) {
                    connectorName = "jrmpconnector_" + serverName;
                } else if (name.equals("irmi")) {
                    connectorName = "irmiconnector_" + serverName;

                    // Add 1 to this port for IRMI as the JMX object will
                    // not use IRMI to bind but JRMP methods.
                    if (port != 0) {
                        port++;
                    }
                } else if (name.equals("cmi")) {
                    connectorName = "cmiconnector_" + serverName;
                } else if (name.equals("iiop")) {
                    connectorName = "iiopconnector_" + serverName;
                    protocol = "iiop";
                    props.put("java.naming.corba.orb", new InitialContext().lookup("java:comp/ORB"));
                } else {
                    // ignore that unsupported protocol
                    continue;
                }

                serviceURL = new JMXServiceURL(protocol, host, port, "/jndi/" + carolURL.toString() + "/" + connectorName);
                JMXConnectorServer connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(serviceURL,
                                                                                                     (Map) props,
                                                                                                     null);
                connectorServers[index] = connectorServer;
                // Create the MBean associated to the connector
                String connectorObjectName = "connector_" + name;
                ObjectName connectorServerName = JonasObjectName.jmxConnectorServer(scheme, connectorObjectName);
                connectorObjectNames.add(connectorServerName);
                getJmxServer().registerMBean(connectorServer, connectorServerName);
                // Start the JMXConnectorServer
                try {
                    connectorServer.start();
                    connectorServerURLs[index] = connectorServer.getAddress();
                } catch (IllegalArgumentException e) {
                    throw e;
                }

                // increment
                index++;

            }
        } catch (javax.naming.NameAlreadyBoundException ne) {
            logger.log(BasicLevel.DEBUG, "Cannot start JMX service " + ne);
            throw new JonasAlreadyStartedException();
        } catch (Exception e) {
            logger.log(BasicLevel.WARN, "Cannot start JMX service " + e);
            throw new ServiceException("Cannot start JMX service", e);
        } finally {
            // Switch back to the old default
            registryService.setDefaultProtocol(defaultProtocolName);
        }

    }

    /**
     * Stop this service
     */
    public void doStop() {

        // Unregister Connector MBeans
        for (Iterator i = connectorObjectNames.iterator(); i.hasNext();) {
            ObjectName name = (ObjectName) i.next();
            try {
                getJmxServer().unregisterMBean(name);
            } catch (Exception e) {
                logger.log(BasicLevel.INFO, "Cannot unregister Connector MBean for '" + name + "'", e);
            }
        }

        // Desactivates the connector server, that is, stops listening for
        // client connections.
        // Calling this method will also close all client connections that
        // were made by this server.
        for (int i = 0; i < connectorServers.length; i++) {
            try {
                connectorServers[i].stop();
            } catch (Exception e) {
                logger.log(BasicLevel.INFO, "Cannot Stop JMX Connector", e);
            }
        }

        // TODO Is this the good place for J2EEDomain and J2EEServer MBeans
        // unregistering ?

        // Unregister some MBeans
        ObjectName domainOn = J2eeObjectName.J2EEDomain(getDomainName());
        try {
            getJmxServer().unregisterMBean(domainOn);
        } catch (Exception e) {
            logger.log(BasicLevel.INFO, "Cannot unregister JEEDomain MBean:" + domainOn.toString());
        }
        ObjectName serverOn = J2eeObjectName.J2EEServer(getDomainName(), getJonasServerName());
        try {
            getJmxServer().unregisterMBean(serverOn);
        } catch (Exception e) {
            logger.log(BasicLevel.INFO, "Cannot unregister JEEServer MBean:" + serverOn.toString());
        }
        // Remove internal references to the MBeanServer.
        releaseJmxServer();

        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, "JMX Service stopped");
        }
    }

    /**
     * @return The actual adresses on which listen the created connector servers
     */
    public JMXServiceURL[] getConnectorServerURLs() {
        return this.connectorServerURLs;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy