/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2007 Bull S.A.S.
 * Contact: jonas-team@ow2.org
 *
 * 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.services.bootstrap;

import java.io.ObjectInputStream;
import java.lang.management.ManagementFactory;
import java.util.Set;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.InvalidAttributeValueException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.OperationsException;
import javax.management.QueryExp;
import javax.management.ReflectionException;
import javax.management.loading.ClassLoaderRepository;

/**
 * This component register a MBeanServer service that delegates all the call to the platform MBeanServer.
 * @author Francois Fornaciari
 */
public class PlatformMBeanServerDelegate implements MBeanServer {

    /**
     * The real MBeanServer
     */
    private MBeanServer delegate;

    /**
     * Start the component (aka retrieve the platform MBeanServer)
     */
    public void start() throws Exception {
        // Check whether javax.management.builder.initial property was set
        if (System.getProperty("javax.management.builder.initial") == null) {
            throw new Exception("The system property 'javax.management.builder.initial' was not set.");
        }

        // Change classloader to load customized MBeanServerBuilder class
        ClassLoader old = Thread.currentThread().getContextClassLoader();
        try {
            Thread.currentThread().setContextClassLoader(PlatformMBeanServerDelegate.class.getClassLoader());
            this.delegate = ManagementFactory.getPlatformMBeanServer();
        } finally {
            Thread.currentThread().setContextClassLoader(old);
        }
    }

    // All the delegating methods...
    // --------------------------------------------------------------

    public ObjectInstance createMBean(final String className,
                                      final ObjectName name)
            throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException {
        return delegate.createMBean(className, name);
    }

    public ObjectInstance createMBean(final String className,
                                      final ObjectName name,
                                      final ObjectName loaderName)
            throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException {
        return delegate.createMBean(className, name, loaderName);
    }

    public ObjectInstance createMBean(final String className,
                                      final ObjectName name,
                                      final Object[] params,
                                      final String[] signature)
            throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException {
        return delegate.createMBean(className, name, params, signature);
    }

    public ObjectInstance createMBean(final String className,
                                      final ObjectName name,
                                      final ObjectName loaderName,
                                      final Object[] params,
                                      final String[] signature)
            throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException {
        return delegate.createMBean(className, name, loaderName, params, signature);
    }

    public ObjectInstance registerMBean(final Object object, final ObjectName name)
            throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
        return delegate.registerMBean(object, name);
    }

    public void unregisterMBean(final ObjectName name) throws InstanceNotFoundException, MBeanRegistrationException {
        delegate.unregisterMBean(name);
    }

    public ObjectInstance getObjectInstance(final ObjectName name) throws InstanceNotFoundException {
        return delegate.getObjectInstance(name);
    }

    public Set<ObjectInstance> queryMBeans(final ObjectName name, final QueryExp query) {
        return delegate.queryMBeans(name, query);
    }

    public Set<ObjectName> queryNames(final ObjectName name, final QueryExp query) {
        return delegate.queryNames(name, query);
    }

    public boolean isRegistered(final ObjectName name) {
        return delegate.isRegistered(name);
    }

    public Integer getMBeanCount() {
        return delegate.getMBeanCount();
    }

    public Object getAttribute(final ObjectName name, final String attribute)
            throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException {
        return delegate.getAttribute(name, attribute);
    }

    public AttributeList getAttributes(final ObjectName name, final String[] attributes)
            throws InstanceNotFoundException, ReflectionException {
        return delegate.getAttributes(name, attributes);
    }

    public void setAttribute(final ObjectName name, final Attribute attribute)
            throws InstanceNotFoundException, AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
        delegate.setAttribute(name, attribute);
    }

    public AttributeList setAttributes(final ObjectName name, final AttributeList attributes)
            throws InstanceNotFoundException, ReflectionException {
        return delegate.setAttributes(name, attributes);
    }

    public Object invoke(final ObjectName name,
                         final String operationName,
                         final Object[] params,
                         final String[] signature)
            throws InstanceNotFoundException, MBeanException, ReflectionException {
        return delegate.invoke(name, operationName, params, signature);
    }

    public String getDefaultDomain() {
        return delegate.getDefaultDomain();
    }

    public String[] getDomains() {
        return delegate.getDomains();
    }

    public void addNotificationListener(final ObjectName name,
                                        final NotificationListener listener,
                                        final NotificationFilter filter,
                                        final Object handback) throws InstanceNotFoundException {
        delegate.addNotificationListener(name, listener, filter, handback);
    }

    public void addNotificationListener(final ObjectName name,
                                        final ObjectName listener,
                                        final NotificationFilter filter,
                                        final Object handback) throws InstanceNotFoundException {
        delegate.addNotificationListener(name, listener, filter, handback);
    }

    public void removeNotificationListener(final ObjectName name, final ObjectName listener)
            throws InstanceNotFoundException, ListenerNotFoundException {
        delegate.removeNotificationListener(name, listener);
    }

    public void removeNotificationListener(final ObjectName name,
                                           final ObjectName listener,
                                           final NotificationFilter filter,
                                           final Object handback)
            throws InstanceNotFoundException, ListenerNotFoundException {
        delegate.removeNotificationListener(name, listener, filter, handback);
    }

    public void removeNotificationListener(final ObjectName name, final NotificationListener listener)
            throws InstanceNotFoundException, ListenerNotFoundException {
        delegate.removeNotificationListener(name, listener);
    }

    public void removeNotificationListener(final ObjectName name,
                                           final NotificationListener listener,
                                           final NotificationFilter filter,
                                           final Object handback)
            throws InstanceNotFoundException, ListenerNotFoundException {
        delegate.removeNotificationListener(name, listener, filter, handback);
    }

    public MBeanInfo getMBeanInfo(final ObjectName name)
            throws InstanceNotFoundException, IntrospectionException, ReflectionException {
        return delegate.getMBeanInfo(name);
    }

    public boolean isInstanceOf(final ObjectName name, final String className) throws InstanceNotFoundException {
        return delegate.isInstanceOf(name, className);
    }

    public Object instantiate(final String className) throws ReflectionException, MBeanException {
        return delegate.instantiate(className);
    }

    public Object instantiate(final String className, final ObjectName loaderName)
            throws ReflectionException, MBeanException, InstanceNotFoundException {
        return delegate.instantiate(className, loaderName);
    }

    public Object instantiate(final String className, final Object[] params, final String[] signature)
            throws ReflectionException, MBeanException {
        return delegate.instantiate(className, params, signature);
    }

    public Object instantiate(final String className,
                              final ObjectName loaderName,
                              final Object[] params,
                              final String[] signature)
            throws ReflectionException, MBeanException, InstanceNotFoundException {
        return delegate.instantiate(className, loaderName, params, signature);
    }

    @Deprecated
    public ObjectInputStream deserialize(final ObjectName name, final byte[] data)
            throws InstanceNotFoundException, OperationsException {
        return delegate.deserialize(name, data);
    }

    @Deprecated
    public ObjectInputStream deserialize(final String className, final byte[] data)
            throws OperationsException, ReflectionException {
        return delegate.deserialize(className, data);
    }

    @Deprecated
    public ObjectInputStream deserialize(final String className, final ObjectName loaderName, final byte[] data)
            throws InstanceNotFoundException, OperationsException, ReflectionException {
        return delegate.deserialize(className, loaderName, data);
    }

    public ClassLoader getClassLoaderFor(final ObjectName mbeanName) throws InstanceNotFoundException {
        return delegate.getClassLoaderFor(mbeanName);
    }

    public ClassLoader getClassLoader(final ObjectName loaderName) throws InstanceNotFoundException {
        return delegate.getClassLoader(loaderName);
    }

    public ClassLoaderRepository getClassLoaderRepository() {
        return delegate.getClassLoaderRepository();
    }
}
