/*
 * Copyright (C) MX4J.
 * All rights reserved.
 *
 * This software is distributed under the terms of the MX4J License version 1.0.
 * See the terms of the MX4J License in the documentation provided with this software.
*/
/* 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.felix.mosgi.jmx.agent.mx4j;

import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;

import javax.management.DynamicMBean;
import javax.management.AttributeNotFoundException;
import javax.management.MBeanException;
import javax.management.ReflectionException;
import javax.management.AttributeList;
import javax.management.MBeanInfo;
import javax.management.Attribute;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanConstructorInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.RuntimeErrorException;
import javax.management.MBeanParameterInfo;
import javax.management.RuntimeMBeanException;

import org.apache.felix.mosgi.jmx.agent.mx4j.util.Utils;

/**
 * Utility class that allow the user to easily write DynamicMBeans. <br>
 * By extending this class, the developer does not have to implement the methods of the DynamicMBean interface, but
 * has instead to provide only the metadata (by overriding few methods) and the implementation (by implementing
 * the methods) of the MBean itself. <br>
 * The methods to override that provides metadata information are usually the following:
 * <ul>
 * <li> <code>createMBeanAttributeInfo</code>, if the MBeans has manageable attributes </li>
 * <li> <code>createMBeanOperationInfo</code>, if the MBeans has manageable operations </li>
 * <li> <code>createMBeanNotificationInfo</code>, if the MBeans has manageable notifications </li>
 * <li> <code>createMBeanConstructorInfo</code>, if the MBeans has manageable constructors </li>
 * <li> <code>getMBeanDescription</code> </li>
 * </ul>
 * For example, the following MBean only has one manageable attribute:
 * <pre>
 * public class SimpleDynamic extends AbstractDynamicMBean
 * {
 *    protected MBeanAttributeInfo[] createMBeanAttributeInfo()
 *    {
 *       return new MBeanAttributeInfo[]
 *       {
 *          new MBeanAttributeInfo("Name", String.class.getName(), "The name", true, true, false)
 *       };
 *    }
 *
 *    protected String getMBeanDescription()
 *    {
 *       return "A simple DynamicMBean";
 *    }
 *
 *    public String getName() { ... }
 *
 *    public void setName(String name) { ... }
 * }
 * </pre>
 * It is responsibility of the developer to specify the metadata <b>and</b> implement the methods specified by the
 * metadata, that will be invoked via reflection by the AbstractDynamicMBean class. For this reason, the methods
 * belonging to the MBean implementation (in the case above <code>getName()</code> and <code>setName(...)</code>)
 * must be public.
 *
 * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
 * @version $Revision: 1.1.1.1 $
 */
public abstract class AbstractDynamicMBean implements DynamicMBean
{
   private MBeanInfo info;
   private Object resource;

   /**
    * Only subclasses can create a new instance of an AbstractDynamicMBean.
    * @see #createMBeanConstructorInfo
    */
   protected AbstractDynamicMBean()
   {
   }

   /**
    * Returns the value of the manageable attribute, as specified by the DynamicMBean interface.
    * @see #createMBeanAttributeInfo
    */
   public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException
   {
      if (attribute == null) throw new AttributeNotFoundException("Attribute " + attribute + " not found");

      Object resource = null;
      MBeanInfo info = null;
      synchronized (this)
      {
         resource = getResourceOrThis();
         info = getMBeanInfo();
      }

      MBeanAttributeInfo[] attrs = info.getAttributes();
      if (attrs == null || attrs.length == 0) throw new AttributeNotFoundException("No attributes defined for this MBean");

      for (int i = 0; i < attrs.length; ++i)
      {
         MBeanAttributeInfo attr = attrs[i];
         if (attr == null) continue;

         if (attribute.equals(attr.getName()))
         {
            if (!attr.isReadable()) throw new ReflectionException(new NoSuchMethodException("No getter defined for attribute: " + attribute));

            // Found, invoke via reflection
            String prefix = null;
            if (attr.isIs())
               prefix = "is";
            else
               prefix = "get";

            try
            {
               return invoke(resource, prefix + attr.getName(), new Class[0], new Object[0]);
            }
            catch (InvalidAttributeValueException x)
            {
               throw new ReflectionException(x);
            }
         }
      }

      throw new AttributeNotFoundException("Attribute " + attribute + " not found");
   }

   /**
    * Returns the manageable attributes, as specified by the DynamicMBean interface.
    */
   public AttributeList getAttributes(String[] attributes)
   {
      AttributeList list = new AttributeList();

      if (attributes != null)
      {
         for (int i = 0; i < attributes.length; ++i)
         {
            String attribute = attributes[i];
            try
            {
               Object result = getAttribute(attribute);
               list.add(new Attribute(attribute, result));
            }
            catch (AttributeNotFoundException ignored)
            {
            }
            catch (MBeanException ignored)
            {
            }
            catch (ReflectionException ignored)
            {
            }
         }
      }

      return list;
   }

   /**
    * Returns the MBeaInfo, as specified by the DynamicMBean interface; the default implementation caches the value
    * returned by {@link #createMBeanInfo} (that is thus called only once).
    * @see #createMBeanInfo
    * @see #setMBeanInfo
    */
   public synchronized MBeanInfo getMBeanInfo()
   {
      if (info == null) setMBeanInfo(createMBeanInfo());
      return info;
   }

   /**
    * Returns the value of the manageable operation as specified by the DynamicMBean interface
    * @see #createMBeanOperationInfo
    */
   public Object invoke(String method, Object[] arguments, String[] params) throws MBeanException, ReflectionException
   {
      if (method == null) throw new IllegalArgumentException("Method name cannot be null");
      if (arguments == null) arguments = new Object[0];
      if (params == null) params = new String[0];

      Object resource = null;
      MBeanInfo info = null;
      synchronized (this)
      {
         resource = getResourceOrThis();
         info = getMBeanInfo();
      }

      MBeanOperationInfo[] opers = info.getOperations();
      if (opers == null || opers.length == 0) throw new ReflectionException(new NoSuchMethodException("No operations defined for this MBean"));

      for (int i = 0; i < opers.length; ++i)
      {
         MBeanOperationInfo oper = opers[i];
         if (oper == null) continue;

         if (method.equals(oper.getName()))
         {
            MBeanParameterInfo[] parameters = oper.getSignature();
            if (params.length != parameters.length) continue;

            String[] signature = new String[parameters.length];
            for (int j = 0; j < signature.length; ++j)
            {
               MBeanParameterInfo param = parameters[j];
               if (param == null)
                  signature[j] = null;
               else
                  signature[j] = param.getType();
            }

            if (Utils.arrayEquals(params, signature))
            {
               // Found the right operation
               try
               {
                  Class[] classes = Utils.loadClasses(resource.getClass().getClassLoader(), signature);
                  return invoke(resource, method, classes, arguments);
               }
               catch (ClassNotFoundException x)
               {
                  throw new ReflectionException(x);
               }
               catch (InvalidAttributeValueException x)
               {
                  throw new ReflectionException(x);
               }
            }
         }
      }

      throw new ReflectionException(new NoSuchMethodException("Operation " + method + " with signature " + Arrays.asList(params) + " is not defined for this MBean"));
   }

   /**
    * Sets the value of the manageable attribute, as specified by the DynamicMBean interface.
    * @see #createMBeanAttributeInfo
    */
   public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException
   {
      if (attribute == null) throw new AttributeNotFoundException("Attribute " + attribute + " not found");

      Object resource = null;
      MBeanInfo info = null;
      synchronized (this)
      {
         resource = getResourceOrThis();
         info = getMBeanInfo();
      }

      MBeanAttributeInfo[] attrs = info.getAttributes();
      if (attrs == null || attrs.length == 0) throw new AttributeNotFoundException("No attributes defined for this MBean");

      for (int i = 0; i < attrs.length; ++i)
      {
         MBeanAttributeInfo attr = attrs[i];
         if (attr == null) continue;

         if (attribute.getName().equals(attr.getName()))
         {
            if (!attr.isWritable()) throw new ReflectionException(new NoSuchMethodException("No setter defined for attribute: " + attribute));

            try
            {
               String signature = attr.getType();
               Class cls = Utils.loadClass(resource.getClass().getClassLoader(), signature);
               invoke(resource, "set" + attr.getName(), new Class[]{cls}, new Object[]{attribute.getValue()});
               return;
            }
            catch (ClassNotFoundException x)
            {
               throw new ReflectionException(x);
            }
         }
      }

      throw new AttributeNotFoundException("Attribute " + attribute + " not found");
   }

   /**
    * Sets the manageable attributes, as specified by the DynamicMBean interface.
    */
   public AttributeList setAttributes(AttributeList attributes)
   {
      AttributeList list = new AttributeList();

      if (attributes != null)
      {
         for (int i = 0; i < attributes.size(); ++i)
         {
            Attribute attribute = (Attribute)attributes.get(i);
            try
            {
               setAttribute(attribute);
               list.add(attribute);
            }
            catch (AttributeNotFoundException ignored)
            {
            }
            catch (InvalidAttributeValueException ignored)
            {
            }
            catch (MBeanException ignored)
            {
            }
            catch (ReflectionException ignored)
            {
            }
         }
      }

      return list;
   }

   /**
    * @deprecated Replaced by {@link #invoke(Object,String,Class[],Object[])}. <br>
    * The resource passed is the resource as set by {@link #setResource} or - if it is null - 'this' instance. <br>
    * This method is deprecated because it is not thread safe.
    */
   protected Object invoke(String name, Class[] params, Object[] args) throws InvalidAttributeValueException, MBeanException, ReflectionException
   {
      Object resource = getResourceOrThis();
      return invoke(resource, name, params, args);
   }

   /**
    * Looks up the method to call on given resource and invokes it.
    * The default implementation requires that the methods that implement attribute and operation behavior
    * on the resource object are public, but it is possible to override this behavior, and call
    * also private methods.
    * @see #findMethod
    * @see #invokeMethod
    */
   protected Object invoke(Object resource, String name, Class[] params, Object[] args) throws InvalidAttributeValueException, MBeanException, ReflectionException
   {
      try
      {
         Class cls = resource.getClass();
         Method method = findMethod(cls, name, params);
         return invokeMethod(method, resource, args);
      }
      catch (NoSuchMethodException x)
      {
         throw new ReflectionException(x);
      }
      catch (IllegalAccessException x)
      {
         throw new ReflectionException(x);
      }
      catch (IllegalArgumentException x)
      {
         throw new InvalidAttributeValueException(x.toString());
      }
      catch (InvocationTargetException x)
      {
         Throwable t = x.getTargetException();
         if (t instanceof RuntimeException)
            throw new RuntimeMBeanException((RuntimeException)t);
         else if (t instanceof Exception) throw new MBeanException((Exception)t);
         throw new RuntimeErrorException((Error)t);
      }
   }

   /**
    * Returns the (public) method with the given name and signature on the given class. <br>
    * Override to return non-public methods, or to map methods to other classes, or to map methods with
    * different signatures
    * @see #invoke(String, Class[], Object[])
    * @see #invokeMethod
    */
   protected Method findMethod(Class cls, String name, Class[] params) throws NoSuchMethodException
   {
      return cls.getMethod(name, params);
   }

   /**
    * Invokes the given method on the given resource object with the given arguments. <br>
    * Override to map methods to other objects, or to map methods with different arguments
    * @see #invoke(String, Class[], Object[])
    * @see #findMethod
    */
   protected Object invokeMethod(Method method, Object resource, Object[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
   {
      return method.invoke(resource, args);
   }

   private Object getResourceOrThis()
   {
      Object resource = getResource();
      if (resource == null) resource = this;
      return resource;
   }

   /**
    * Returns the resource object on which invoke attribute's getters, attribute's setters and operation's methods
    * @see #setResource
    */
   protected synchronized Object getResource()
   {
      return resource;
   }

   /**
    * Specifies the resource object on which invoke attribute's getters, attribute's setters and operation's methods.
    * @see #getResource
    */
   public synchronized void setResource(Object resource)
   {
      this.resource = resource;
   }

   /**
    * Sets the MBeanInfo object cached by this instance. <br>
    * The given MBeanInfo is not cloned.
    * @see #getMBeanInfo
    */
   protected synchronized void setMBeanInfo(MBeanInfo info)
   {
      this.info = info;
   }

   /**
    * Creates the MBeanInfo for this instance, calling in succession factory methods that the user can override.
    * Information to create MBeanInfo are taken calling the following methods:
    * <ul>
    * <li><code>{@link #createMBeanAttributeInfo}</code></li>
    * <li><code>{@link #createMBeanConstructorInfo}</code></li>
    * <li><code>{@link #createMBeanOperationInfo}</code></li>
    * <li><code>{@link #createMBeanNotificationInfo}</code></li>
    * <li><code>{@link #getMBeanClassName}</code></li>
    * <li><code>{@link #getMBeanDescription}</code></li>
    * </ul>
    */
   protected MBeanInfo createMBeanInfo()
   {
      MBeanAttributeInfo[] attrs = createMBeanAttributeInfo();
      MBeanConstructorInfo[] ctors = createMBeanConstructorInfo();
      MBeanOperationInfo[] opers = createMBeanOperationInfo();
      MBeanNotificationInfo[] notifs = createMBeanNotificationInfo();
      String className = getMBeanClassName();
      String description = getMBeanDescription();
      return new MBeanInfo(className, description, attrs, ctors, opers, notifs);
   }

   /**
    * To be overridden to return metadata information about manageable attributes.
    */
   protected MBeanAttributeInfo[] createMBeanAttributeInfo()
   {
      return new MBeanAttributeInfo[0];
   }

   /**
    * To be overridden to return metadata information about manageable constructors.
    */
   protected MBeanConstructorInfo[] createMBeanConstructorInfo()
   {
      return new MBeanConstructorInfo[0];
   }

   /**
    * To be overridden to return metadata information about manageable operations.
    */
   protected MBeanOperationInfo[] createMBeanOperationInfo()
   {
      return new MBeanOperationInfo[0];
   }

   /**
    * To be overridden to return metadata information about manageable notifications.
    */
   protected MBeanNotificationInfo[] createMBeanNotificationInfo()
   {
      return new MBeanNotificationInfo[0];
   }

   /**
    * To be overridden to return metadata information about the class name of this MBean;
    * by default returns this class' name.
    */
   protected String getMBeanClassName()
   {
      return getClass().getName();
   }

   /**
    * To be overridden to return metadata information about the description of this MBean.
    */
   protected String getMBeanDescription()
   {
      return null;
   }
}
