FileDocCategorySizeDatePackage
MBeanEasyConfig.javaAPI DocGlassfish v2 API34535Fri May 04 22:34:08 BST 2007com.sun.enterprise.admin.server.core.mbean.meta

MBeanEasyConfig.java

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 * 
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.enterprise.admin.server.core.mbean.meta;


import com.sun.enterprise.admin.util.PropertiesStringSource;

//JDK imports
import java.util.ArrayList;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;

//JMX imports
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanConstructorInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanInfo;
import javax.management.IntrospectionException;

//Admin imports
//import com.sun.enterprise.admin.common.exception.ServerInstanceException;
import com.sun.enterprise.admin.common.exception.MBeanConfigException;

//i18n import
import com.sun.enterprise.util.i18n.StringManager;

/****************************************************************************************************************
    This <code>class</code> is for holding and providing <code>MBeanInfo</code> data
    <strong>for Dynamic MBeans</strong> (operations,attributes,MBean description...).
*/

public class MBeanEasyConfig //extends AdminBase implements MBeanRegistration
{
	// i18n StringManager
	private static StringManager localStrings =
		StringManager.getManager( MBeanEasyConfig.class );
 
  final static String DESCR_LINE_DELIMITER         = ",";
  
  //STRING SOURCE FILE
  final static String STRINGSOUREC_FILENAME         = "MBeanConfig.properties";
  
  //EXCEPTIONS 
  final static String EXCEPTION_LINE_EMPTY          = localStrings.getString( "admin.server.core.mbean.meta.empty_description_line" );
  final static String EXCEPTION_WRONG_LINE_FORMAT   = localStrings.getString( "admin.server.core.mbean.meta.wrong_fields_number_in_description_line" );
  final static String EXCEPTION_NAME_FLD_EMPTY      = localStrings.getString( "admin.server.core.mbean.meta.empty_name_in_description_line" );
  final static String EXCEPTION_CLASSNAME_FLD_EMPTY = localStrings.getString( "admin.server.core.mbean.meta.empty_classname_in_description_line" );
  final static String EXCEPTION_UNKNOWN_RWTYPE      = localStrings.getString( "admin.server.core.mbean.meta.unknown_rw_type_in_description_line" );
  final static String EXCEPTION_UNKNOWN_IMPACT_TYPE = localStrings.getString( "admin.server.core.mbean.meta.unknown_impact_type_in_description" );
  final static String EXCEPTION_OPER_NOT_FOUND      = localStrings.getString( "admin.server.core.mbean.meta.unfound_operation_in_bean_class" );
  
  final static String EXCEPTION_WRONG_PARAM_FORMAT  = localStrings.getString( "admin.server.core.mbean.meta.wrong_operation_parameter_in_description" );
  final static String EXCEPTION_WRONG_PARAM_DIM     = localStrings.getString( "admin.server.core.mbean.meta.wrong_operation_parameter_dimension_in_description" );
   final static String EXCEPTION_WRONG_PARAM_CLASS  = localStrings.getString( "admin.server.core.mbean.meta.wrong_parameter_attribute_class_in_description" );
 final static String EXCEPTION_EMPTY_PARAM_TYPE     = localStrings.getString( "admin.server.core.mbean.meta.empty_parameter_attribute_type_in_description_line" );
//IMPACT CODES
  final static String TYPE_INFO        = "INFO";
  final static String TYPE_ACTION      = "ACTION";
  final static String TYPE_ACTION_INFO = "ACTION_INFO";
  final static String TYPE_UNKNOWN     = "UNKNOWN";

  //info members
  private MBeanAttributeInfo[]		  m_attrs	 = new MBeanAttributeInfo[0];
  private MBeanConstructorInfo[]    m_cstrs  = new MBeanConstructorInfo[0];
  private MBeanOperationInfo[]		  m_opers	 = new MBeanOperationInfo[0];
  private MBeanNotificationInfo[]   m_notfs	 = new MBeanNotificationInfo[0];
  private Class      	 	            m_beanClass	 = null;   //configured MBean Class
  private String 		                m_descr  = null;   //MBean dscription

  /****************************************************************************************************************
    * Constructs of <code>MBeansEasyConfig</code> from provided
    * text descriptions of MBean components (operations, attributes,...).
    * @param configuringMBeanClass the configuring Dynamic MBean object Class.
    * @param attrDescr array of text decriptions of MBean attributes,
    * each string represents one attribute in format: 
    * <ul><ATTR_NAME>,<ATTR_OBJECT_CLASS>, <ATTR_RW_TYPE>, <ATTR_DESCRIPTION_RESOURCE_ID>.
    * <br>E.g.
    * <ul>   {
    * <ul>     "courses,    java.lang.String[], RW, MBEAN_DESCR_ATTR_COURSES",
    * <br>     "beginTime,  java.util.Date,     RW, MBEAN_DESCR_ATTR_BEGINTIME",
    * <br>     "sum,        int,                R , MBEAN_DESCR_ATTR_SUM"
    * </ul><br>   };</ul></ul>
    * @param operDescr array of text decriptions of MBean operations, 
    * <ul>each string represents one operation in format: 
    * <br><OP_NAME>,<OP_TYPE>,<OP_DESCRIPTION_RESOURCE_ID>
  *  e.g.:
  *  <br>   {  
  *  <ul>       "eat, ACTION, MBEAN_DESCR_OPER_EAT",
  *  <br>       "throw_up, ACTION_INFO, MBEAN_DESCR_OPER_THROW_UP",
  *  <br>       "calc, INFO, MBEAN_DESCR_OPER_CALC" 
  *  </ul>   }; (note that last description includes comma) </ul>
  *  @throws MBeanConfigException exception if the param parsing is not successful
  */
  public MBeanEasyConfig(Class configuringMBeanClass, String[] attrDescr, String[] operDescr, String descr) throws MBeanConfigException 
  {
      m_beanClass  = configuringMBeanClass; // configuring MBean save
      m_descr = descr; //save MBean descriptor
      if(m_descr==null || m_descr.length()==0)
         m_descr = ""+getPureClassName(configuringMBeanClass)+".mbean";
         
      // create INFOs
      m_attrs = createAttributesInfo(m_beanClass, attrDescr);
      m_cstrs = createConstructorsInfo(m_beanClass, null);
      m_opers = createOperationsInfo(m_beanClass, operDescr);
      //m_notfs = createNotificationsInfo(notfsDescr);
  }
		
  //**********************************************************************************************************************************************************************************************************************************************
  /****************************************************************************************************************
      Creates <code>MBeanAttributeInfo[]</code> array according to descriptions 
      given in text format (see constructor comments).
      @param configuringMBeanClass the configuring MBean Class object;
      @param attrDescr array of text decriptions of MBean <strong>attributes</strong>,
      @throws MBeanConfigException exception if the param parsing is not successful
  */
  public static MBeanAttributeInfo[] createAttributesInfo(Class configuringMBeanClass, String[] attrDescr) throws MBeanConfigException
	{
    if(attrDescr==null || attrDescr.length<1)
      return new MBeanAttributeInfo[0];
    MBeanAttributeInfo[] infos = new MBeanAttributeInfo[attrDescr.length];
    String beanName  = getPureClassName(configuringMBeanClass);
   // the weak restriction - all descr strings should be non-empty
    for(int i=0; i<attrDescr.length; i++)
      {
        infos[i] = parseAttributeDescrLine(beanName, attrDescr[i]);
      }
    return  infos;
  }  
    
  /****************************************************************************************************************
      Creates <code>MBeanOperationInfo[]</code> array according to descriptions 
      given in text format (see constructor comments) and to configuring
      MBean class reflection.
      @param configuringMBeanClass the configuring MBean object;
      @param operDescr array of text decriptions of MBean <strong>operations</strong>,
      @throws MBeanConfigException exception if the param parsing is not successful
  */
  public static MBeanOperationInfo[] createOperationsInfo(Class configuringMBeanClass, String[] operDescr) throws MBeanConfigException
	{
    if(configuringMBeanClass==null)
      return new MBeanOperationInfo[0];
    if(operDescr==null || operDescr.length<1)
      return new MBeanOperationInfo[0];
    ArrayList arr = new ArrayList();
    for(int i=0; i<operDescr.length; i++)
      {
        MBeanOperationInfo[] overloads = parseOperationDescrLine(configuringMBeanClass, operDescr[i]);
        for(int j=0; j<overloads.length; j++)
          arr.add(overloads[j]);
      }
        
    MBeanOperationInfo[] infos = new MBeanOperationInfo[arr.size()];
    // the weak restriction - all descr strings should be non-empty
    for(int i=0; i<infos.length; i++)
      {
        infos[i] = (MBeanOperationInfo)arr.get(i);
      }
    return  infos;
  }  
    
    
  /****************************************************************************************************************
      Creates <code>MBeanConstructorInfo[]</code> array according to configuring
      MBean class reflection.
      @param configuringMBeanClass the configuring MBean Class object
      @param constructorDescr constructors text decriptions
  */
  public static MBeanConstructorInfo[] createConstructorsInfo(Class configuringMBeanClass, String constructorDescr)
	{
    if(configuringMBeanClass==null)
      return new MBeanConstructorInfo[0];
    if(constructorDescr==null)
      {
         String nameDescr = getPureClassName(configuringMBeanClass)+".constructor";
         constructorDescr = getResourceString(nameDescr, nameDescr); 
      }
    //enumerate all constructors
    Constructor[] ctrs = configuringMBeanClass.getConstructors();
    MBeanConstructorInfo[] infos = new MBeanConstructorInfo[ctrs.length];
    for(int i=0; i<ctrs.length; i++)
      {
        infos[i] = new MBeanConstructorInfo(constructorDescr, ctrs[i]); 
      }
    return  infos;
  }  
    
  /****************************************************************************************************************
      Get <code>MBeanInfo</code> description object for configurable MBean.
      @return <code>MBeanInfo</code> description object for configurable MBean.
  */
  public MBeanInfo getMBeanInfo()
  {
    if(m_beanClass==null)
      return null;
    else
      return new MBeanInfo(m_beanClass.getName(), m_descr, 
                            m_attrs, m_cstrs, m_opers, m_notfs);

  }

  /****************************************************************************************************************
      Sets (updates) description of configured  <code>MBean</code>
      @param beanDescription the descriptions of MBean.
  */
  public void setMBeanDescription(String beanDescription)
  {
      m_descr = beanDescription; //set MBean descriptor
  }

  /****************************************************************************************************************
      Sets (updates) <code>MBeanAttributeInfo[]</code> component of contained <code>MBeanInfo</code>
      @param attributesInfo array of attribute descriptions.
  */
  public void setAttributesInfo(MBeanAttributeInfo[] attributesInfo)
  {
     if(attributesInfo==null)
        attributesInfo = new MBeanAttributeInfo[0];
     m_attrs = attributesInfo;
  }
		
  /****************************************************************************************************************
      Sets (updates) <code>MBeanConstructorInfo[]</code> component of contained <code>MBeanInfo</code>
      @param constructorInfo array of operation descriptions.
  */
  public void setOperationsInfo(MBeanConstructorInfo[] constructorInfo)
  {
     if(constructorInfo ==null)
        constructorInfo = new MBeanConstructorInfo[0];
     m_cstrs = constructorInfo;
  }
		
  /****************************************************************************************************************
      Sets (updates) <code>MBeanOperationInfo[]</code> component of contained <code>MBeanInfo</code>
      @param operationsInfo array of operation descriptions.
  */
  public void setOperationsInfo(MBeanOperationInfo[] operationsInfo)
  {
     if(operationsInfo ==null)
        operationsInfo = new MBeanOperationInfo[0];
     m_opers = operationsInfo;
  }
		
  /*****************************************************************************************************************
      Sets ( updates) <code>MBeanNotificationInfo[]</code> component of contained <code>MBeanInfo</code>
      @param notificationsInfo array of notifications descriptions.
  */
  public void setNotificationsInfo(MBeanNotificationInfo[] notificationsInfo)
  {
     if(notificationsInfo==null)
        notificationsInfo = new MBeanNotificationInfo[0];
     m_notfs = notificationsInfo;
  }
		
        
  /*****************************************************************************************************************
      Converts string value presentation to target type (esp. useful for CLI).
      @param value The string value to convert
      @param targetType The string description of target value type (@see Class)
      @return The target type object which represents value in the proper type.
  */
  public static Object convertStringValueToProperType(String value, String targetType) throws MBeanConfigException
  {
    if(value==null) 
      return null;
    
    Class cl;
    try 
    {
        if((cl=getPrimitiveClass(targetType))!=null || (cl=getRelatedPrimitiveClass(targetType))!=null)
          {
            if(cl==Byte.TYPE)
                return new Byte(value);
            if(cl==Character.TYPE)
                return new Character(value.charAt(0));
            if(cl==Double.TYPE)
                return new Double(value);
            if(cl==Float.TYPE)
                return new Float(value);
            if(cl==Integer.TYPE)
                return new Integer(value);
            if(cl==Long.TYPE)
                return new Long(value);
            if(cl==Short.TYPE)
                return new Short(value);
            if(cl==Boolean.TYPE)
                return new Boolean(value);
          }
    }
    catch(java.lang.IllegalArgumentException e)
    {
		String msg = localStrings.getString( "admin.server.core.mbean.meta.convertstringvaluetopropertype_wrong_argument_type", e.getMessage() );
        throw new MBeanConfigException( msg );
    }
     //no arrays yet
     return value;
  }

  /****************************************************************************************************************
      Parsing the attr description string to create <code>MBeanAttributeInfo</code> object.
      @param  descrLine string with one attribute description (see constructor's comment).
      @return MBeanAttributeInfo object for given description line.
      @throws MBeanConfigException exception if the param parsing is not successful
  */
  private static MBeanAttributeInfo parseAttributeDescrLine(String beanName, String descrLine) throws MBeanConfigException
  {
    //line format: <ATTR_NAME>,<ATTR_OBJECT_CLASS>,<ATTR_RW_TYPE>,<ATTR_DESCRIPTION_RESOURCE_ID>.
    String name;
    String className;
    String rwType;
    String descr;
    boolean bReadable = false, bWritable = false;
       
    if(descrLine==null) {
	  String msg = localStrings.getString( "admin.server.core.mbean.meta.parseattributedescrline_exception_line_empty", EXCEPTION_LINE_EMPTY );
      throw new MBeanConfigException( msg );
	}

    //EXTRACT line fields
    String[] flds = getLineFields(descrLine, 4);
    if(flds.length<3 || flds.length>4) {
	   String msg = localStrings.getString( "admin.server.core.mbean.meta.parseattributedescrline_wrong_exception_format", EXCEPTION_WRONG_LINE_FORMAT, descrLine );
       throw new MBeanConfigException( msg );
	}
    
    //NAME
    name = flds[0];
    if(name.length()==0) {
	  String msg = localStrings.getString( "admin.server.core.mbean.meta.parseattributedescrline_wrong_exception_format", EXCEPTION_NAME_FLD_EMPTY, descrLine );
      throw new MBeanConfigException( msg );
	}
       
    //OBJECT CLASS NAME
    className = flds[1];
    if(className.length()==0) {
	  String msg = localStrings.getString( "admin.server.core.mbean.meta.parseattributedescrline_wrong_exception_format", EXCEPTION_CLASSNAME_FLD_EMPTY, descrLine );
      throw new MBeanConfigException( msg );
	}
    className = convertTypeToSignatureClass(className).getName();
       
       
    //RWTYPE (R/W/RW)
    rwType = flds[2];   
    if(rwType.equals("R"))
      bReadable = true;
    else   
      if(rwType.equals("W"))
        bWritable = true;
      else   
        if(rwType.equals("RW") || rwType.equals("WR"))
          {
            bWritable = true;
            bReadable = true;
          }
        else {
		  String msg = localStrings.getString( "admin.server.core.mbean.meta.parseattributedescrline_wrong_exception_format", EXCEPTION_UNKNOWN_RWTYPE, descrLine );
          throw new MBeanConfigException( msg );
		}
    
    //DESCRIPTION
    String defaultName = beanName+"."+name+".attribute";

    if(flds.length<4 || flds[3].length()==0)
      descr = getResourceString(defaultName, defaultName);
    else
      descr = getResourceString(flds[3], defaultName);
       
    return new MBeanAttributeInfo(name, className, descr, bReadable, bWritable, false);
  }

  /****************************************************************************************************************
      Parsing the operation description string to create <code>MBeanAttributeInfo[]</code> array
      (There is possible to have more than one resulting element even for one operation - 
      in case of the corresponding method has overloadings).
      @param configuringMBeanClass Mbean object Class for reflection.
      @param descrLine string with one operation description (see constructor's comment).
      @return array of MBeanAttributeInfo for given operation.
      @throws MBeanConfigException exception if the param parsing is not successful
  */
  private static MBeanOperationInfo[] parseOperationDescrLine(Class configuringMBeanClass, String descrLine) throws MBeanConfigException
  {
    //line format: <OP_NAME>,<OP_TYPE>,<OP_DESCRIPTION>
    String name;
    String typeName;
    int    type;
    String descr;
       
    if(descrLine==null) {
	  String msg = localStrings.getString( "admin.server.core.mbean.meta.parseattributedescrline_exception_line_empty", EXCEPTION_LINE_EMPTY );
      throw new MBeanConfigException( msg );
	}
    
    //EXTRACT method_name(param1, param2, ...) part
    int idx1 = descrLine.indexOf('(');
    if(idx1<=0 || idx1==descrLine.length()-1) {
	   String msg = localStrings.getString( "admin.server.core.mbean.meta.parseattributedescrline_wrong_exception_format", EXCEPTION_WRONG_PARAM_FORMAT, descrLine );
       throw new MBeanConfigException( msg );
	}
    name = descrLine.substring(0, idx1).trim();
    if(name.length()==0) {
	  String msg = localStrings.getString( "admin.server.core.mbean.meta.parseattributedescrline_wrong_exception_format", EXCEPTION_NAME_FLD_EMPTY, descrLine );
      throw new MBeanConfigException( msg );
	}
    int idx2 = descrLine.indexOf(')', idx1+1);
    if(idx2<=0) {
	  String msg = localStrings.getString( "admin.server.core.mbean.meta.parseattributedescrline_wrong_exception_format", EXCEPTION_WRONG_PARAM_FORMAT, descrLine );
      throw new MBeanConfigException( msg );
	}
    
    Object[] params = decomposeParametersDescription(descrLine.substring(idx1+1,idx2));
    
    //EXTRACT line fields
    String[] flds = getLineFields(descrLine.substring(idx2), 3);
    if(flds.length<2) {
	   String msg = localStrings.getString( "admin.server.core.mbean.meta.parseattributedescrline_wrong_exception_format", EXCEPTION_WRONG_LINE_FORMAT, descrLine );
       throw new MBeanConfigException( msg );
	}
    
    
    //TYPE (INFO/ACTION...)
    typeName = flds[1];   
    if(typeName.equals(TYPE_INFO))
      type = MBeanOperationInfo.INFO;
    else   
      if(typeName.equals(TYPE_ACTION))
        type = MBeanOperationInfo.ACTION;
      else   
        if(typeName.equals(TYPE_ACTION_INFO))
          type = MBeanOperationInfo.ACTION_INFO;
        else   
          if(typeName.equals(TYPE_UNKNOWN))
            type = MBeanOperationInfo.UNKNOWN;
          else {
			String msg = localStrings.getString( "admin.server.core.mbean.meta.parseattributedescrline_wrong_exception_format", EXCEPTION_UNKNOWN_IMPACT_TYPE, descrLine );
            throw new MBeanConfigException( msg );
		  }
      
    //DESCRIPTION
    String beanName  = getPureClassName(configuringMBeanClass);
    String defaultName = beanName+"."+name+".operation";
    if(flds.length<3 || flds[2].length()==0)
      descr = getResourceString(defaultName, defaultName);
    else
      descr = getResourceString(flds[2], defaultName);
       

    //REFLECTION
    Class[] signature = new Class[params.length/3];
    for(int i=0; i<signature.length; i++)
      signature[i] = (Class)params[i*3];
    Method method;
    try {
      method  = configuringMBeanClass.getMethod(name, signature);
    } catch (NoSuchMethodException e)
    {
	  String msg = localStrings.getString( "admin.server.core.mbean.meta.parseoperationdescrline_wrong_exception_format", EXCEPTION_OPER_NOT_FOUND, descrLine );
      throw new MBeanConfigException( msg );
    }
    MBeanParameterInfo[] infos = new MBeanParameterInfo[signature.length];
    for(int i=0; i<signature.length; i++)
      {
        String pName = (String)params[i*3+1];
        if(pName==null)
           pName = ""; //get default name ?
        String pDescr = (String)params[i*3+2];
        if(pDescr==null) //get default descr ?
           {
              if(pName.length()>0)
                 pDescr = beanName+"."+name+"."+pName+".parameter";
              else
                 pDescr = "";
           }
        infos[i] = new MBeanParameterInfo(pName, signature[i].getName(), pDescr);
      }
    return new MBeanOperationInfo[] {new MBeanOperationInfo(name, descr, infos, method.getReturnType().getName(), type)};   
    

//    Method[] methods  = getMethodsForName(configuringMBeanClass, name);
//    MBeanOperationInfo[] infos = new MBeanOperationInfo[methods.length];
//    for(int i=0; i<methods.length; i++)
//        infos[i] = new MBeanOperationInfo(descr, methods[i]);
        //NOTE: ACTION/INFO operation type is not used by this constructor. To do later.
//    return infos;
  }

  //****************************************************************************************************************
  // extracts up to <nMAx> fields separated by line delimiter
  // only nMax-th field can contain unmasked delimiters
  static private String[] getLineFields(String line, int nMax)
  {    
    ArrayList flds = new ArrayList();
    int idx1=0, idx2=100;
    if(line==null || line.length()==0 || nMax==0)
      return null;
    while(idx2>0 && nMax>flds.size() && idx1<line.length())
      {
        idx2 = line.indexOf(DESCR_LINE_DELIMITER, idx1);
        if(idx2<0)
          flds.add(line.substring(idx1).trim());
        else
          flds.add(line.substring(idx1, idx2).trim());
        idx1 = idx2 + 1;
        if(idx2==line.length())
           flds.add("");
      }
    String[] strs = new String[flds.size()];
    for(int i=0; i<strs.length; i++)
      {
        strs[i] = (String)flds.get(i);
      }
    return strs;
  }

  //********************************************************************************************************************
  static String getResourceString(String resourceID, String nullReplacer)
  {
    return resourceID; //TEMPORARY FOP TEST
    /* should be discussed with Kedar
       String res = null;
       try {
         PropertiesStringSource propSource = new PropertiesStringSource(STRINGSOUREC_FILENAME);
         res = propSource.getString(resourceID);
         if(res!=null)
            return res;
         if(nullReplacer!=null)
            return nullReplacer;
         else
            return resourceID;
       } catch(IOException e) {
         if(nullReplacer!=null)
            return nullReplacer;
         else
            return resourceID;
       }
  */
  }

  //*********************************************************************************************************************
  static private Method[] getMethodsForName(Class configuringMBeanClass, String name)
  {
    ArrayList overloads = new ArrayList();
    Method[] all = configuringMBeanClass.getMethods();
    if(all==null)
      return null;
    for(int i=0; i<all.length; i++)
      {
        if(name.equals(all[i].getName()))
          overloads.add(all[i]);
      }
    if(overloads.size()==0)
      return null;
    Method[] ret = new Method[overloads.size()];
    for(int i=0; i<ret.length; i++)
      ret[i] = (Method)overloads.get(i);
    return ret;
  }


  //****************************************************************************************************************
  // converts type from description to java signature style
  // 
  static private Class convertTypeToSignatureClass(String type) throws MBeanConfigException
  {    
    type = type.trim();
    int idx = type.indexOf("[");
    if(idx==0 || type.length()==0) {
	   String msg = localStrings.getString( "admin.server.core.mbean.meta.converttypetosignatureclass_wrong_exception_format", EXCEPTION_EMPTY_PARAM_TYPE, type );
       throw new MBeanConfigException( msg );
	}
    try 
    {
      if(idx>0)
        { // array
          String name = type.substring(0,idx).trim();
          if(name.length()==0) {
		    String msg = localStrings.getString( "admin.server.core.mbean.meta.converttypetosignatureclass_wrong_exception_format", EXCEPTION_EMPTY_PARAM_TYPE, type );
            throw new MBeanConfigException( msg );
		  }
          String code = getPrimitiveCode(name);
          if(code==null)
            {
              if(name.indexOf('.')<0)
                 name = "java.lang."+name;
              return Class.forName(getArrayPrefix(type, idx) + "L" + name + ";");
            }
          else
            return Class.forName(getArrayPrefix(type, idx) + code) ;
        }
      else
        {
          Class cl = getPrimitiveClass(type);
          if(cl!=null)
            return cl;
          //non-primitive plain class
          
          try {
            return Class.forName(type);
          }
          catch(ClassNotFoundException e)
          {
             if(type.indexOf('.')>0) {
				String msg = localStrings.getString( "admin.server.core.mbean.meta.converttypetosignatureclass_wrong_exception_format", EXCEPTION_WRONG_PARAM_CLASS, type );
                throw new MBeanConfigException( msg );
			 }
          }
          //here we are if no . in name
          return Class.forName("java.lang."+type);
        }
    } 
    catch(ClassNotFoundException e)
    {
	  String msg = localStrings.getString( "admin.server.core.mbean.meta.converttypetosignatureclass_wrong_exception_format", EXCEPTION_WRONG_PARAM_CLASS, type );
      throw new MBeanConfigException( msg );
    }
    
  }

  //****************************************************************************************************************
  static private String getArrayPrefix(String line, int idx)  throws MBeanConfigException
  {
    String pref = "";
    int dimCheck = 0;
    for( ; idx<line.length(); idx++)
      {
        if(line.charAt(idx)=='[')
          pref = pref + "[";
        else
          if(line.charAt(idx)==']')
            dimCheck++;
      }
    if(pref.length()!=dimCheck) {
	   String msg = localStrings.getString( "admin.server.core.mbean.meta.getarrayprefix_wrong_exception_format", EXCEPTION_WRONG_PARAM_DIM, line );
       throw new MBeanConfigException( msg );
	}
    return pref;
  }

  //****************************************************************************************************************
  static Object[][] convTable = new Object[][] {
    {"byte",    "B",    Byte.TYPE,        "java.lang.Byte"},
    {"char",    "C",    Character.TYPE,   "java.lang.Character"},
    {"double",  "D",    Double.TYPE,      "java.lang.Double"},
    {"float",   "F",    Float.TYPE,       "java.lang.Float"},
    {"int",     "I",    Integer.TYPE,     "java.lang.Integer"},
    {"long",    "J",    Long.TYPE,        "java.lang.Long"},
    {"short",   "S",    Short.TYPE,       "java.lang.Short"},
    {"boolean", "Z",    Boolean.TYPE,     "java.lang.Boolean"},
    {"void",    "V",    Void.TYPE,        "?"} };
    
  //****************************************************************************************************************
  static private Object findConvTableElemByType(String type, int idx)
  {
     for(int i=0; i<convTable.length; i++)
        {
           if(type.equals((String)convTable[i][0]))
              return convTable[i][idx];
        }
     return null;
  }    

  //****************************************************************************************************************
  static private Object findConvTableElemByAssoClassName(String assoClass, int idx)
  {
     for(int i=0; i<convTable.length; i++)
        {
           if(assoClass.equals((String)convTable[i][3]))
              return convTable[i][idx];
        }
     return null;
  }    

  //****************************************************************************************************************
  static private String getPrimitiveCode(String type)
  {
     return (String)findConvTableElemByType(type, 1);
  }    
      
  //****************************************************************************************************************
  static private Class getPrimitiveClass(String type)
  {
     return (Class)findConvTableElemByType(type, 2);
  }    
      
  //****************************************************************************************************************
  static private Class getRelatedPrimitiveClass(String className)
  {
     return (Class)findConvTableElemByAssoClassName(className, 2);
  }    
     
  //****************************************************************************************************************
  // extracts parameters description
  // 
  static private Object[] decomposeParametersDescription(String line) throws MBeanConfigException
  {    
    ArrayList flds = new ArrayList();
    int idx1=0, idx2=100;
    line = line.trim();
    int len = line.length();
    int parmEnd;
    if(len==0)
      return new Object[0];
    String type;
    while(idx1<len)
      {
        if((parmEnd=line.indexOf(',', idx1))<0)
           parmEnd = len;
        //TYPE
        idx2 = line.indexOf(' ', idx1);
        if(idx2>parmEnd)
           idx2=parmEnd;
        if(idx2<0)
          {
            flds.add(convertTypeToSignatureClass(line.substring(idx1)));
            idx2 = parmEnd;
          }
        else
          flds.add(convertTypeToSignatureClass(line.substring(idx1,idx2)));
        idx1 = idx2 + 1;
        while(idx1<parmEnd && line.charAt(idx1)==' ')
          idx1++;
        if(idx1>=parmEnd)
          {
            flds.add(null); //name
            flds.add(null); //descr
            if(idx1==parmEnd)
               idx1++;
            while(idx1<len && line.charAt(idx1)==' ')
              idx1++;
            continue;
          }
        
        //NAME
        idx2 = line.indexOf(' ', idx1);
        if(idx2>parmEnd)
           idx2=parmEnd;
        if(idx2<0)
          {
            flds.add(line.substring(idx1).trim());
            idx2 = parmEnd;
          }
        else
          flds.add(line.substring(idx1,idx2).trim());
        idx1 = idx2 + 1;
        while(idx1<parmEnd && line.charAt(idx1)==' ')
          idx1++;
        if(idx1>=parmEnd)
          {
            flds.add(null); //descr
            if(idx1==parmEnd)
               idx1++;
            while(idx1<len && line.charAt(idx1)==' ')
              idx1++;
            continue;
          }
        
        // DESCRIPTION
        idx2 = line.indexOf(',', idx1);
        if(idx2<0)
          {
            flds.add(line.substring(idx1).trim());
            idx2 = len;
          }
        else
          flds.add(line.substring(idx1,idx2).trim());
        idx1 = idx2 + 1;
        while(idx1<len && line.charAt(idx1)==' ')
          idx1++;
      }

    Object[] strs = new Object[flds.size()];
    for(int i=0; i<strs.length; i++)
      {
        strs[i] = flds.get(i);
      }
    return strs;
  }
  //****************************************************************************************************************
  private static String getPureClassName(Class configuringMBeanClass)
  {
     if(configuringMBeanClass==null)     
        return null;
     String className = configuringMBeanClass.getName();
     int idx = className.lastIndexOf('.');
     if(idx>=0)
        return className.substring(idx+1);
     return className;
  }
}