/* JFox, the OpenSource J2EE Application Server
 *
 * Copyright (C) 2002 huihoo.com
 * Distributable under GNU LGPL license
 * See the GNU Lesser General Public License for more details.
 */

package org.jfox.mx;

import java.util.List;
import java.util.ArrayList;
import java.util.Properties;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * 注册到 MxServer Repository 的对象,包含了 Mx Bean 的所有信息
 * 
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

public class MxMetaData {

  private MxOperationInfo[] operations = null;
  private ObjectName objectName = null;
  private Mxable mxObject = null;
  private MxConstructorInfo[] constructorInfos = null;

  public MxMetaData(ObjectName objectName, Mxable mxObject) {
    this.objectName = objectName;
    this.mxObject = mxObject;
    constructConstructorInfos();
    constructOperationInfos();
  }

  public MxInfo getMxInfo() {
    return new MxInfo(this.getClassName(),
                         this.getMxDescription(),
                         constructorInfos,
                         operations);
  }

  public String getClassName() {
    return mxObject.getClass().getName();
  }

  public String getMxDescription(){
    return ((Mxable)mxObject).getMxDescription();
  }

  public ClassLoader getClassLoader() {
    return mxObject.getClass().getClassLoader();
  }

  public MxOperationInfo[] getOperations() {
    return operations;
  }

  public ObjectName getObjectName() {
    return objectName;
  }

  public Mxable getMxObject() {
    return mxObject;
  }

  /*
   * Note: Getters and setters cannot be invoked through the invoke method, since JMX 1.2
   */
  public Object invoke(String operationName, Object params[], Class[] signatures) throws MxException {
    return this.reflectInvoke(operationName,params,signatures);
  }

// ################ private methods ##########3

  private void constructConstructorInfos() {
    Constructor[] constructors = mxObject.getClass().getConstructors();
    int length = constructors.length;
    constructorInfos = new MxConstructorInfo[length];
    for(int i = 0; i < length; i++) {
      Constructor constructor = constructors[i];
      MxConstructorInfo constructorInfo = null;
      constructorInfo = new MxConstructorInfo("Constructor of " + this.getClassName(), constructor);
      constructorInfos[i] = constructorInfo;
    }
  }

  private void constructOperationInfos(){
    List operationInfos = new ArrayList();
    Method[] methods = mxObject.getClass().getMethods();
    Properties operProperties = ((Mxable)mxObject).getOperationDescriptions();
    if(operProperties == null) operProperties = new Properties();
    for(int i=0; i<methods.length; i++){
      Method method = methods[i];
      if(method.getName().startsWith("mx_")) { // 管理方法
        String desc = operProperties.getProperty(method.getName());
        if(desc == null || desc.equals("")) desc = method.getName();
        MxOperationInfo operationInfo = new MxOperationInfo(desc,method);
        operationInfos.add(operationInfo);
      }
    }
    operations = (MxOperationInfo[])operationInfos.toArray(new MxOperationInfo[0]);
  }

  private Object reflectInvoke(String operationName, Object params[], Class[] signatures) throws MxException {
    Object obj = null;
    try{
      obj = mxObject.getClass().getMethod(operationName,signatures).invoke(mxObject,params);
    }
    catch(Exception e){
      throw new MxException(e);
    }
    return obj;
  }

}