org.ops4j.gaderian.management.impl.MBeanRegistryImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.ops4j.gaderian.management.impl.MBeanRegistryImpl.java

Source

// Copyright 2005 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.ops4j.gaderian.management.impl;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.management.DynamicMBean;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.JMException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.StandardMBean;

import org.apache.commons.logging.Log;
import org.ops4j.gaderian.ErrorHandler;
import org.ops4j.gaderian.events.RegistryShutdownListener;
import org.ops4j.gaderian.internal.ServicePoint;
import org.ops4j.gaderian.management.MBeanRegistry;
import org.ops4j.gaderian.management.ManagementMessages;
import org.ops4j.gaderian.management.ObjectNameBuilder;

/**
 * Implementation of {@link MBeanRegistry}. Registers MBeans in an standard JMX MBeanServer Supports
 * calling start methods, after the registration. MBeans can be provided as service references in a
 * configuration. Standard MBeans must use the primitive service model. Any interceptor destroys JMX
 * compliance due to naming conventions. Implements shutdown listener to unregisters all MBeans when
 * the registry is shutdown
 * 
 * @author Achim Huegen
 * @since 1.1
 */
public class MBeanRegistryImpl implements MBeanRegistry, RegistryShutdownListener {
    private ErrorHandler _errorHandler;

    private Log _log;

    private MBeanServer _beanServer;

    private ObjectNameBuilder _objectNameBuilder;

    private List _beans;

    // Holds all registered MBean instances
    private List _objectInstances = new ArrayList();

    /**
     * Creates new instance Registers all MBeans as defined in <code>beans</code>
     * 
     * @param objectNameBuilder
     *            Service responsible for naming MBeans
     * @param beans
     *            List with instances of {@link MBeanRegistrationContribution}. The specified
     *            services get registered as MBeans
     */
    public MBeanRegistryImpl(ErrorHandler errorHandler, Log log, MBeanServer beanServer,
            ObjectNameBuilder objectNameBuilder, List beans) {
        _errorHandler = errorHandler;
        _log = log;
        _beanServer = beanServer;
        _objectNameBuilder = objectNameBuilder;
        _beans = beans;
        if (_beans != null)
            processContributions(_beans);
    }

    /**
     * Registers all services as MBeans, specified in the contribution to this service
     * 
     * @param beans
     *            List of MBeanRegistrationContribution
     */
    private void processContributions(List beans) {
        Iterator iter = beans.iterator();
        while (iter.hasNext()) {
            MBeanRegistrationContribution mbeanReg = (MBeanRegistrationContribution) iter.next();
            registerServiceAsMBean(mbeanReg.getObjectName(), mbeanReg.getServicePoint(), mbeanReg.getStartMethod());
        }
    }

    /**
     * Registers a service as MBean. Retrieves an instance of the service by calling
     * {@link ServicePoint#getService(Class)}
     * 
     * @param objectName
     *            ObjectName for the MBean, if null the ObjectName is determined by the
     *            {@link ObjectNameBuilder}
     * @param servicePoint
     *            ServicePoint
     * @param startMethodName
     *            Name of the start method to call in the servicePoint after registration Can be
     *            null
     */
    private void registerServiceAsMBean(ObjectName objectName, ServicePoint servicePoint, String startMethodName) {
        // By default the ObjectName is built by ObjectNameBuilder service
        // but the name can be overriden in the contribution
        if (objectName == null)
            objectName = _objectNameBuilder.createServiceObjectName(servicePoint);

        // Register the bean
        Object mbean;
        try {
            Class managementInterface = servicePoint.getDeclaredInterface();
            // TODO: Check if ServiceModel is != pool and threaded
            mbean = servicePoint.getService(managementInterface);
            registerMBean(mbean, managementInterface, objectName);
        } catch (JMException e) {
            _errorHandler.error(_log, ManagementMessages.errorRegisteringMBean(objectName, e), null, e);
            return;
        }
        // Call the start method if defined
        try {
            if (startMethodName != null)
                invokeStartMethod(mbean, startMethodName);
        } catch (InvocationTargetException e) {
            _errorHandler.error(_log,
                    ManagementMessages.errorStartMethodFailed(startMethodName, objectName, e.getTargetException()),
                    null, e);
            return;
        } catch (Exception e) {
            _errorHandler.error(_log, ManagementMessages.errorStartMethodFailed(startMethodName, objectName, e),
                    null, e);
            return;
        }
    }

    /**
     * @throws InstanceAlreadyExistsException
     * @throws MBeanRegistrationException
     * @throws NotCompliantMBeanException
     * @see MBeanRegistry#registerMBean(Object, Class, ObjectName)
     */
    public ObjectInstance registerMBean(Object obj, Class managementInterface, ObjectName objectName)
            throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
        ObjectInstance instance = null;
        try {
            if (_log.isDebugEnabled()) {
                _log.debug("Trying to register MBean " + objectName);
            }
            instance = _beanServer.registerMBean(obj, objectName);
        } catch (NotCompliantMBeanException e) {
            if (_log.isDebugEnabled()) {
                _log.debug("MBean " + objectName + " is not compliant. Registering" + " using StandardMBean");
            }
            if (DynamicMBean.class.isAssignableFrom(obj.getClass()) || managementInterface == null)
                throw e;
            // if the object is a Standard MBean that is surrounded by
            // a proxy or an interceptor it is not compliant since
            // the naming conventions are not fulfilled.
            // Now we use the StandardMBean class to adapt the MBean to the
            // DynamicMBean interface which is not restricted by these
            // naming conventions
            StandardMBean standardMBean = new StandardMBean(obj, managementInterface);
            instance = _beanServer.registerMBean(standardMBean, objectName);
        }
        _objectInstances.add(instance);
        return instance;
    }

    /**
     * @see org.ops4j.gaderian.management.MBeanRegistry#unregisterMBean(javax.management.ObjectName)
     */
    public void unregisterMBean(ObjectName objectName)
            throws InstanceNotFoundException, MBeanRegistrationException {
        ObjectInstance instance = _beanServer.getObjectInstance(objectName);
        _objectInstances.remove(instance);
        _beanServer.unregisterMBean(objectName);
    }

    /**
     * Calls the start method of an mbean
     */
    private void invokeStartMethod(Object mbean, String methodName)
            throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        Class serviceClass = mbean.getClass();
        Method m = serviceClass.getMethod(methodName, null);
        m.invoke(mbean, null);
    }

    /**
     * Unregisters all registered MBeans
     */
    public void registryDidShutdown() {
        // Unregister objects in reversed order. Otherwise the
        // Jsr 160 connector gets problems after the namingservice is unregistered
        for (int i = _objectInstances.size() - 1; i >= 0; i--) {
            ObjectInstance objectInstance = (ObjectInstance) _objectInstances.get(i);
            try {
                _beanServer.unregisterMBean(objectInstance.getObjectName());
            } catch (JMException e) {
                // Uncritical error, just warn
                _log.warn(ManagementMessages.errorUnregisteringMBean(objectInstance.getObjectName(), e));
            }
        }
    }

}