jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java

Print this page
rev 5696 : 8000537: Contextualize RequiredModelMBean class
Reviewed-by: ahgross, dsamersoff, skoivu
Contributed-by: Jaroslav Bachorik <jaroslav.bachorik@oracle.com>
   1 /*
   2  * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 /*
  26  * @author    IBM Corp.
  27  *
  28  * Copyright IBM Corp. 1999-2000.  All rights reserved.
  29  */
  30 
  31 
  32 package javax.management.modelmbean;
  33 
  34 /* java imports */
  35 
  36 import static com.sun.jmx.defaults.JmxProperties.MODELMBEAN_LOGGER;
  37 import java.io.FileOutputStream;
  38 import java.io.PrintStream;
  39 import java.lang.reflect.InvocationTargetException;
  40 
  41 import java.lang.reflect.Method;



  42 
  43 import java.util.Date;
  44 import java.util.HashMap;
  45 import java.util.HashSet;
  46 import java.util.Iterator;
  47 import java.util.logging.Level;
  48 import java.util.Map;
  49 import java.util.Set;
  50 
  51 import java.util.Vector;
  52 import javax.management.Attribute;
  53 import javax.management.AttributeChangeNotification;
  54 import javax.management.AttributeChangeNotificationFilter;
  55 import javax.management.AttributeList;
  56 import javax.management.AttributeNotFoundException;
  57 import javax.management.Descriptor;
  58 import javax.management.InstanceNotFoundException;
  59 import javax.management.InvalidAttributeValueException;
  60 import javax.management.ListenerNotFoundException;
  61 import javax.management.MBeanAttributeInfo;
  62 import javax.management.MBeanConstructorInfo;
  63 import javax.management.MBeanException;
  64 import javax.management.MBeanInfo;
  65 import javax.management.MBeanNotificationInfo;
  66 import javax.management.MBeanOperationInfo;
  67 import javax.management.MBeanRegistration;
  68 import javax.management.MBeanServer;
  69 import javax.management.MBeanServerFactory;
  70 import javax.management.Notification;
  71 import javax.management.NotificationBroadcasterSupport;
  72 import javax.management.NotificationEmitter;
  73 import javax.management.NotificationFilter;
  74 import javax.management.NotificationListener;
  75 import javax.management.ObjectName;
  76 import javax.management.ReflectionException;
  77 import javax.management.RuntimeErrorException;
  78 import javax.management.RuntimeOperationsException;
  79 import javax.management.ServiceNotFoundException;
  80 import javax.management.loading.ClassLoaderRepository;


  81 
  82 import sun.reflect.misc.MethodUtil;
  83 import sun.reflect.misc.ReflectUtil;
  84 
  85 /**
  86  * This class is the implementation of a ModelMBean. An appropriate
  87  * implementation of a ModelMBean must be shipped with every JMX Agent
  88  * and the class must be named RequiredModelMBean.
  89  * <P>
  90  * Java resources wishing to be manageable instantiate the
  91  * RequiredModelMBean using the MBeanServer's createMBean method.
  92  * The resource then sets the MBeanInfo and Descriptors for the
  93  * RequiredModelMBean instance. The attributes and operations exposed
  94  * via the ModelMBeanInfo for the ModelMBean are accessible
  95  * from MBeans, connectors/adaptors like other MBeans. Through the
  96  * Descriptors, values and methods in the managed application can be
  97  * defined and mapped to attributes and operations of the ModelMBean.
  98  * This mapping can be defined in an XML formatted file or dynamically and
  99  * programmatically at runtime.
 100  * <P>


 121     /* attributes                        */
 122     /*************************************/
 123     ModelMBeanInfo modelMBeanInfo;
 124 
 125     /* Notification broadcaster for any notification to be sent
 126      * from the application through the RequiredModelMBean.  */
 127     private NotificationBroadcasterSupport generalBroadcaster = null;
 128 
 129     /* Notification broadcaster for attribute change notifications */
 130     private NotificationBroadcasterSupport attributeBroadcaster = null;
 131 
 132     /* handle, name, or reference for instance on which the actual invoke
 133      * and operations will be executed */
 134     private Object managedResource = null;
 135 
 136 
 137     /* records the registering in MBeanServer */
 138     private boolean registered = false;
 139     private transient MBeanServer server = null;
 140 



 141     /*************************************/
 142     /* constructors                      */
 143     /*************************************/
 144 
 145     /**
 146      * Constructs an <CODE>RequiredModelMBean</CODE> with an empty
 147      * ModelMBeanInfo.
 148      * <P>
 149      * The RequiredModelMBean's MBeanInfo and Descriptors
 150      * can be customized using the {@link #setModelMBeanInfo} method.
 151      * After the RequiredModelMBean's MBeanInfo and Descriptors are
 152      * customized, the RequiredModelMBean can be registered with
 153      * the MBeanServer.
 154      *
 155      * @exception MBeanException Wraps a distributed communication Exception.
 156      *
 157      * @exception RuntimeOperationsException Wraps a {@link
 158      * RuntimeException} during the construction of the object.
 159      **/
 160     public RequiredModelMBean()


1008                     RequiredModelMBean.class.getName(),
1009                         mth, "looking for method in managedResource class");
1010             }
1011             if (targetObjectField != null)
1012                 targetObject = targetObjectField;
1013             else {
1014                 targetObject = managedResource;
1015                 if (targetObject == null) {
1016                     final String msg =
1017                         "managedResource for invoke " + opName +
1018                         " is null";
1019                     Exception snfe = new ServiceNotFoundException(msg);
1020                     throw new MBeanException(snfe);
1021                 }
1022             }
1023 
1024             final Class<?> targetClass;
1025 
1026             if (opClassName != null) {
1027                 try {











1028                     final ClassLoader targetClassLoader =
1029                         targetObject.getClass().getClassLoader();
1030                     targetClass = Class.forName(opClassName, false,
1031                                                 targetClassLoader);
1032                 } catch (ClassNotFoundException e) {










1033                     final String msg =
1034                         "class for invoke " + opName + " not found";
1035                     throw new ReflectionException(e, msg);
1036                 }
1037             } else
1038                 targetClass = targetObject.getClass();
1039 
1040             method = resolveMethod(targetClass, opMethodName, sig);
1041         }
1042 
1043         if (tracing) {
1044             MODELMBEAN_LOGGER.logp(Level.FINER,
1045                 RequiredModelMBean.class.getName(),
1046                     mth, "found " + opMethodName + ", now invoking");
1047         }
1048 
1049         final Object result =
1050             invokeMethod(opName, method, targetObject, opArgs);
1051 
1052         if (tracing) {
1053             MODELMBEAN_LOGGER.logp(Level.FINER,
1054                 RequiredModelMBean.class.getName(),
1055                     mth, "successfully invoked method");
1056         }
1057 
1058         if (result != null)
1059             cacheResult(opInfo, opDescr, result);
1060 
1061         return result;
1062     }
1063 
1064     private static Method resolveMethod(Class<?> targetClass,
1065                                         String opMethodName,
1066                                         String[] sig)
1067             throws ReflectionException {
1068         final boolean tracing = MODELMBEAN_LOGGER.isLoggable(Level.FINER);
1069 
1070         if (tracing) {
1071             MODELMBEAN_LOGGER.logp(Level.FINER,
1072                 RequiredModelMBean.class.getName(),"resolveMethod",
1073                   "resolving " + targetClass.getName() + "." + opMethodName);
1074         }
1075 
1076         final Class<?>[] argClasses;
1077 
1078         if (sig == null)
1079             argClasses = null;
1080         else {


1081             final ClassLoader targetClassLoader = targetClass.getClassLoader();
1082             argClasses = new Class<?>[sig.length];





1083             for (int i = 0; i < sig.length; i++) {
1084                 if (tracing) {
1085                     MODELMBEAN_LOGGER.logp(Level.FINER,
1086                         RequiredModelMBean.class.getName(),"resolveMethod",
1087                             "resolve type " + sig[i]);
1088                 }
1089                 argClasses[i] = (Class<?>) primitiveClassMap.get(sig[i]);
1090                 if (argClasses[i] == null) {
1091                     try {

1092                         argClasses[i] =
1093                             Class.forName(sig[i], false, targetClassLoader);
1094                     } catch (ClassNotFoundException e) {
1095                         if (tracing) {
1096                             MODELMBEAN_LOGGER.logp(Level.FINER,
1097                                     RequiredModelMBean.class.getName(),
1098                                     "resolveMethod",
1099                                     "class not found");
1100                         }
1101                         final String msg = "Parameter class not found";
1102                         throw new ReflectionException(e, msg);


1103                     }

1104                 }




1105             }
1106         }
1107 
1108         try {
1109             return targetClass.getMethod(opMethodName, argClasses);
1110         } catch (NoSuchMethodException e) {
1111             final String msg =
1112                 "Target method not found: " + targetClass.getName() + "." +
1113                 opMethodName;
1114             throw new ReflectionException(e, msg);
1115         }
1116     }
1117 
1118     /* Map e.g. "int" to int.class.  Goodness knows how many time this
1119        particular wheel has been reinvented.  */
1120     private static final Class<?>[] primitiveClasses = {
1121         int.class, long.class, boolean.class, double.class,
1122         float.class, short.class, byte.class, char.class,
1123     };
1124     private static final Map<String,Class<?>> primitiveClassMap =
1125         new HashMap<String,Class<?>>();
1126     static {
1127         for (int i = 0; i < primitiveClasses.length; i++) {
1128             final Class<?> c = primitiveClasses[i];
1129             primitiveClassMap.put(c.getName(), c);
1130         }
1131     }
1132 
1133     /* Find a method in RequiredModelMBean as determined by the given
1134        parameters.  Return null if there is none, or if the parameters
1135        exclude using it.  Called from invoke. */
1136     private static Method findRMMBMethod(String opMethodName,
1137                                          Object targetObjectField,
1138                                          String opClassName,
1139                                          String[] sig) {
1140         final boolean tracing = MODELMBEAN_LOGGER.isLoggable(Level.FINER);
1141 
1142         if (tracing) {
1143             MODELMBEAN_LOGGER.logp(Level.FINER,
1144                 RequiredModelMBean.class.getName(),
1145                     "invoke(String, Object[], String[])",
1146                   "looking for method in RequiredModelMBean class");
1147         }
1148 
1149         if (!isRMMBMethodName(opMethodName))
1150             return null;
1151         if (targetObjectField != null)
1152             return null;
1153         final Class<RequiredModelMBean> rmmbClass = RequiredModelMBean.class;
1154         final Class<?> targetClass;
1155         if (opClassName == null)
1156             targetClass = rmmbClass;
1157         else {






1158             try {

1159                 final ClassLoader targetClassLoader =
1160                     rmmbClass.getClassLoader();
1161                 targetClass = Class.forName(opClassName, false,
1162                                             targetClassLoader);
1163                 if (!rmmbClass.isAssignableFrom(targetClass))
1164                     return null;

1165             } catch (ClassNotFoundException e) {
1166                 return null;
1167             }
1168         }


1169         try {
1170             return resolveMethod(targetClass, opMethodName, sig);
1171         } catch (ReflectionException e) {
1172             return null;
1173         }
1174     }
1175 
1176     /*
1177      * Invoke the given method, and throw the somewhat unpredictable
1178      * appropriate exception if the method itself gets an exception.
1179      */
1180     private Object invokeMethod(String opName, Method method,
1181                                 Object targetObject, Object[] opArgs)
1182             throws MBeanException, ReflectionException {
1183         try {







1184             ReflectUtil.checkPackageAccess(method.getDeclaringClass());
1185             return MethodUtil.invoke(method, targetObject, opArgs);
















1186         } catch (RuntimeErrorException ree) {
1187             throw new RuntimeOperationsException(ree,
1188                       "RuntimeException occurred in RequiredModelMBean "+
1189                       "while trying to invoke operation " + opName);
1190         } catch (RuntimeException re) {
1191             throw new RuntimeOperationsException(re,
1192                       "RuntimeException occurred in RequiredModelMBean "+
1193                       "while trying to invoke operation " + opName);
1194         } catch (IllegalAccessException iae) {
1195             throw new ReflectionException(iae,
1196                       "IllegalAccessException occurred in " +
1197                       "RequiredModelMBean while trying to " +
1198                       "invoke operation " + opName);
1199         } catch (InvocationTargetException ite) {
1200             Throwable mmbTargEx = ite.getTargetException();
1201             if (mmbTargEx instanceof RuntimeException) {
1202                 throw new MBeanException ((RuntimeException)mmbTargEx,
1203                       "RuntimeException thrown in RequiredModelMBean "+
1204                       "while trying to invoke operation " + opName);
1205             } else if (mmbTargEx instanceof Error) {


1550                         }
1551                     } else {
1552                         // not getMethod so return descriptor (default) value
1553                         String qualifier="";
1554                         response = attrDescr.getFieldValue("value");
1555                         if (response == null) {
1556                             qualifier="default ";
1557                             response = attrDescr.getFieldValue("default");
1558                         }
1559                         if (tracing) {
1560                             MODELMBEAN_LOGGER.logp(Level.FINER,
1561                                     RequiredModelMBean.class.getName(), mth,
1562                                 "could not find getMethod for " +attrName +
1563                                 ", returning descriptor " +qualifier + "value");
1564                         }
1565                         // !! cast response to right class
1566                     }
1567                 }
1568 
1569                 // make sure response class matches type field
1570                 String respType = attrInfo.getType();
1571                 if (response != null) {
1572                     String responseClass = response.getClass().getName();
1573                     if (!respType.equals(responseClass)) {
1574                         boolean wrongType = false;
1575                         boolean primitiveType = false;
1576                         boolean correspondingTypes = false;
1577                         for (int i = 0; i < primitiveTypes.length; i++) {
1578                             if (respType.equals(primitiveTypes[i])) {
1579                                 primitiveType = true;
1580                                 if (responseClass.equals(primitiveWrappers[i]))
1581                                     correspondingTypes = true;
1582                                 break;
1583                             }
1584                         }
1585                         if (primitiveType) {
1586                             // inequality may come from primitive/wrapper class
1587                             if (!correspondingTypes)
1588                                 wrongType = true;
1589                         } else {
1590                             // inequality may come from type subclassing
1591                             boolean subtype;
1592                             try {











1593                                 ClassLoader cl =
1594                                     response.getClass().getClassLoader();
1595                                 Class<?> c = Class.forName(respType, true, cl);











1596                                 subtype = c.isInstance(response);
1597                             } catch (Exception e) {
1598                                 subtype = false;
1599 
1600                                 if (tracing) {
1601                                     MODELMBEAN_LOGGER.logp(Level.FINER,
1602                                             RequiredModelMBean.class.getName(),
1603                                         mth, "Exception: ",e);
1604                                 }
1605                             }
1606                             if (!subtype)
1607                                 wrongType = true;
1608                         }
1609                         if (wrongType) {
1610                             if (tracing) {
1611                                 MODELMBEAN_LOGGER.logp(Level.FINER,
1612                                         RequiredModelMBean.class.getName(), mth,
1613                                     "Wrong response type '" + respType + "'");
1614                             }
1615                             // throw exception, didn't get


2728             MODELMBEAN_LOGGER.logp(Level.FINER,
2729                     RequiredModelMBean.class.getName(),mth,
2730                 "Exit");
2731         }
2732 
2733     }
2734 
2735     /**
2736      * Return the Class Loader Repository used to perform class loading.
2737      * Subclasses may wish to redefine this method in order to return
2738      * the appropriate {@link javax.management.loading.ClassLoaderRepository}
2739      * that should be used in this object.
2740      *
2741      * @return the Class Loader Repository.
2742      *
2743      */
2744     protected ClassLoaderRepository getClassLoaderRepository() {
2745         return MBeanServerFactory.getClassLoaderRepository(server);
2746     }
2747 
2748     private Class<?> loadClass(String className)
2749         throws ClassNotFoundException {







2750         try {

2751             return Class.forName(className);
2752         } catch (ClassNotFoundException e) {
2753             final ClassLoaderRepository clr =
2754                 getClassLoaderRepository();

2755             if (clr == null) throw new ClassNotFoundException(className);
2756             return clr.loadClass(className);



2757         }









2758     }
2759 
2760 
2761     /*************************************/
2762     /* MBeanRegistration Interface       */
2763     /*************************************/
2764 
2765     /**
2766      * Allows the MBean to perform any operations it needs before
2767      * being registered in the MBean server.  If the name of the MBean
2768      * is not specified, the MBean can provide a name for its
2769      * registration.  If any exception is raised, the MBean will not be
2770      * registered in the MBean server.
2771      * <P>
2772      * In order to ensure proper run-time semantics of RequireModelMBean,
2773      * Any subclass of RequiredModelMBean overloading or overriding this
2774      * method should call <code>super.preRegister(server, name)</code>
2775      * in its own <code>preRegister</code> implementation.
2776      *
2777      * @param server The MBean server in which the MBean will be registered.


   1 /*
   2  * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 /*
  26  * @author    IBM Corp.
  27  *
  28  * Copyright IBM Corp. 1999-2000.  All rights reserved.
  29  */
  30 
  31 
  32 package javax.management.modelmbean;
  33 
  34 /* java imports */
  35 
  36 import static com.sun.jmx.defaults.JmxProperties.MODELMBEAN_LOGGER;
  37 import java.io.FileOutputStream;
  38 import java.io.PrintStream;
  39 import java.lang.reflect.InvocationTargetException;
  40 
  41 import java.lang.reflect.Method;
  42 import java.security.AccessControlContext;
  43 import java.security.AccessController;
  44 import java.security.PrivilegedAction;
  45 
  46 import java.util.Date;
  47 import java.util.HashMap;
  48 import java.util.HashSet;

  49 import java.util.logging.Level;
  50 import java.util.Map;
  51 import java.util.Set;
  52 
  53 import java.util.Vector;
  54 import javax.management.Attribute;
  55 import javax.management.AttributeChangeNotification;
  56 import javax.management.AttributeChangeNotificationFilter;
  57 import javax.management.AttributeList;
  58 import javax.management.AttributeNotFoundException;
  59 import javax.management.Descriptor;
  60 import javax.management.InstanceNotFoundException;
  61 import javax.management.InvalidAttributeValueException;
  62 import javax.management.ListenerNotFoundException;
  63 import javax.management.MBeanAttributeInfo;
  64 import javax.management.MBeanConstructorInfo;
  65 import javax.management.MBeanException;
  66 import javax.management.MBeanInfo;
  67 import javax.management.MBeanNotificationInfo;
  68 import javax.management.MBeanOperationInfo;
  69 import javax.management.MBeanRegistration;
  70 import javax.management.MBeanServer;
  71 import javax.management.MBeanServerFactory;
  72 import javax.management.Notification;
  73 import javax.management.NotificationBroadcasterSupport;
  74 import javax.management.NotificationEmitter;
  75 import javax.management.NotificationFilter;
  76 import javax.management.NotificationListener;
  77 import javax.management.ObjectName;
  78 import javax.management.ReflectionException;
  79 import javax.management.RuntimeErrorException;
  80 import javax.management.RuntimeOperationsException;
  81 import javax.management.ServiceNotFoundException;
  82 import javax.management.loading.ClassLoaderRepository;
  83 import sun.misc.JavaSecurityAccess;
  84 import sun.misc.SharedSecrets;
  85 
  86 import sun.reflect.misc.MethodUtil;
  87 import sun.reflect.misc.ReflectUtil;
  88 
  89 /**
  90  * This class is the implementation of a ModelMBean. An appropriate
  91  * implementation of a ModelMBean must be shipped with every JMX Agent
  92  * and the class must be named RequiredModelMBean.
  93  * <P>
  94  * Java resources wishing to be manageable instantiate the
  95  * RequiredModelMBean using the MBeanServer's createMBean method.
  96  * The resource then sets the MBeanInfo and Descriptors for the
  97  * RequiredModelMBean instance. The attributes and operations exposed
  98  * via the ModelMBeanInfo for the ModelMBean are accessible
  99  * from MBeans, connectors/adaptors like other MBeans. Through the
 100  * Descriptors, values and methods in the managed application can be
 101  * defined and mapped to attributes and operations of the ModelMBean.
 102  * This mapping can be defined in an XML formatted file or dynamically and
 103  * programmatically at runtime.
 104  * <P>


 125     /* attributes                        */
 126     /*************************************/
 127     ModelMBeanInfo modelMBeanInfo;
 128 
 129     /* Notification broadcaster for any notification to be sent
 130      * from the application through the RequiredModelMBean.  */
 131     private NotificationBroadcasterSupport generalBroadcaster = null;
 132 
 133     /* Notification broadcaster for attribute change notifications */
 134     private NotificationBroadcasterSupport attributeBroadcaster = null;
 135 
 136     /* handle, name, or reference for instance on which the actual invoke
 137      * and operations will be executed */
 138     private Object managedResource = null;
 139 
 140 
 141     /* records the registering in MBeanServer */
 142     private boolean registered = false;
 143     private transient MBeanServer server = null;
 144 
 145     private final static JavaSecurityAccess javaSecurityAccess = SharedSecrets.getJavaSecurityAccess();
 146     final private AccessControlContext acc = AccessController.getContext();
 147 
 148     /*************************************/
 149     /* constructors                      */
 150     /*************************************/
 151 
 152     /**
 153      * Constructs an <CODE>RequiredModelMBean</CODE> with an empty
 154      * ModelMBeanInfo.
 155      * <P>
 156      * The RequiredModelMBean's MBeanInfo and Descriptors
 157      * can be customized using the {@link #setModelMBeanInfo} method.
 158      * After the RequiredModelMBean's MBeanInfo and Descriptors are
 159      * customized, the RequiredModelMBean can be registered with
 160      * the MBeanServer.
 161      *
 162      * @exception MBeanException Wraps a distributed communication Exception.
 163      *
 164      * @exception RuntimeOperationsException Wraps a {@link
 165      * RuntimeException} during the construction of the object.
 166      **/
 167     public RequiredModelMBean()


1015                     RequiredModelMBean.class.getName(),
1016                         mth, "looking for method in managedResource class");
1017             }
1018             if (targetObjectField != null)
1019                 targetObject = targetObjectField;
1020             else {
1021                 targetObject = managedResource;
1022                 if (targetObject == null) {
1023                     final String msg =
1024                         "managedResource for invoke " + opName +
1025                         " is null";
1026                     Exception snfe = new ServiceNotFoundException(msg);
1027                     throw new MBeanException(snfe);
1028                 }
1029             }
1030 
1031             final Class<?> targetClass;
1032 
1033             if (opClassName != null) {
1034                 try {
1035                     AccessControlContext stack = AccessController.getContext();
1036                     final Object obj = targetObject;
1037                     final String className = opClassName;
1038                     final ClassNotFoundException[] caughtException = new ClassNotFoundException[1];
1039 
1040                     targetClass = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Class<?>>() {
1041 
1042                         @Override
1043                         public Class<?> run() {
1044                             try {
1045                                 ReflectUtil.checkPackageAccess(className);
1046                                 final ClassLoader targetClassLoader =
1047                                     obj.getClass().getClassLoader();
1048                                 return Class.forName(className, false,
1049                                                             targetClassLoader);
1050                             } catch (ClassNotFoundException e) {
1051                                 caughtException[0] = e;
1052                             }
1053                             return null;
1054                         }
1055                     }, stack, acc);
1056 
1057                     if (caughtException[0] != null) {
1058                         throw caughtException[0];
1059                     }
1060                 } catch (ClassNotFoundException e) {
1061                     final String msg =
1062                         "class for invoke " + opName + " not found";
1063                     throw new ReflectionException(e, msg);
1064                 }
1065             } else
1066                 targetClass = targetObject.getClass();
1067 
1068             method = resolveMethod(targetClass, opMethodName, sig);
1069         }
1070 
1071         if (tracing) {
1072             MODELMBEAN_LOGGER.logp(Level.FINER,
1073                 RequiredModelMBean.class.getName(),
1074                     mth, "found " + opMethodName + ", now invoking");
1075         }
1076 
1077         final Object result =
1078             invokeMethod(opName, method, targetObject, opArgs);
1079 
1080         if (tracing) {
1081             MODELMBEAN_LOGGER.logp(Level.FINER,
1082                 RequiredModelMBean.class.getName(),
1083                     mth, "successfully invoked method");
1084         }
1085 
1086         if (result != null)
1087             cacheResult(opInfo, opDescr, result);
1088 
1089         return result;
1090     }
1091 
1092     private Method resolveMethod(Class<?> targetClass,
1093                                         String opMethodName,
1094                                         final String[] sig)
1095             throws ReflectionException {
1096         final boolean tracing = MODELMBEAN_LOGGER.isLoggable(Level.FINER);
1097 
1098         if (tracing) {
1099             MODELMBEAN_LOGGER.logp(Level.FINER,
1100                 RequiredModelMBean.class.getName(),"resolveMethod",
1101                   "resolving " + targetClass.getName() + "." + opMethodName);
1102         }
1103 
1104         final Class<?>[] argClasses;
1105 
1106         if (sig == null)
1107             argClasses = null;
1108         else {
1109             final AccessControlContext stack = AccessController.getContext();
1110             final ReflectionException[] caughtException = new ReflectionException[1];
1111             final ClassLoader targetClassLoader = targetClass.getClassLoader();
1112             argClasses = new Class<?>[sig.length];
1113 
1114             javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Void>() {
1115 
1116                 @Override
1117                 public Void run() {
1118                     for (int i = 0; i < sig.length; i++) {
1119                         if (tracing) {
1120                             MODELMBEAN_LOGGER.logp(Level.FINER,
1121                                 RequiredModelMBean.class.getName(),"resolveMethod",
1122                                     "resolve type " + sig[i]);
1123                         }
1124                         argClasses[i] = (Class<?>) primitiveClassMap.get(sig[i]);
1125                         if (argClasses[i] == null) {
1126                             try {
1127                                 ReflectUtil.checkPackageAccess(sig[i]);
1128                                 argClasses[i] =
1129                                     Class.forName(sig[i], false, targetClassLoader);
1130                             } catch (ClassNotFoundException e) {
1131                                 if (tracing) {
1132                                     MODELMBEAN_LOGGER.logp(Level.FINER,
1133                                             RequiredModelMBean.class.getName(),
1134                                             "resolveMethod",
1135                                             "class not found");
1136                                 }
1137                                 final String msg = "Parameter class not found";
1138                                 caughtException[0] = new ReflectionException(e, msg);
1139                             }
1140                         }
1141                     }
1142                     return null;
1143                 }
1144             }, stack, acc);
1145 
1146             if (caughtException[0] != null) {
1147                 throw caughtException[0];
1148             }
1149         }
1150 
1151         try {
1152             return targetClass.getMethod(opMethodName, argClasses);
1153         } catch (NoSuchMethodException e) {
1154             final String msg =
1155                 "Target method not found: " + targetClass.getName() + "." +
1156                 opMethodName;
1157             throw new ReflectionException(e, msg);
1158         }
1159     }
1160 
1161     /* Map e.g. "int" to int.class.  Goodness knows how many time this
1162        particular wheel has been reinvented.  */
1163     private static final Class<?>[] primitiveClasses = {
1164         int.class, long.class, boolean.class, double.class,
1165         float.class, short.class, byte.class, char.class,
1166     };
1167     private static final Map<String,Class<?>> primitiveClassMap =
1168         new HashMap<String,Class<?>>();
1169     static {
1170         for (int i = 0; i < primitiveClasses.length; i++) {
1171             final Class<?> c = primitiveClasses[i];
1172             primitiveClassMap.put(c.getName(), c);
1173         }
1174     }
1175 
1176     /* Find a method in RequiredModelMBean as determined by the given
1177        parameters.  Return null if there is none, or if the parameters
1178        exclude using it.  Called from invoke. */
1179     private Method findRMMBMethod(String opMethodName,
1180                                          Object targetObjectField,
1181                                          String opClassName,
1182                                          String[] sig) {
1183         final boolean tracing = MODELMBEAN_LOGGER.isLoggable(Level.FINER);
1184 
1185         if (tracing) {
1186             MODELMBEAN_LOGGER.logp(Level.FINER,
1187                 RequiredModelMBean.class.getName(),
1188                     "invoke(String, Object[], String[])",
1189                   "looking for method in RequiredModelMBean class");
1190         }
1191 
1192         if (!isRMMBMethodName(opMethodName))
1193             return null;
1194         if (targetObjectField != null)
1195             return null;
1196         final Class<RequiredModelMBean> rmmbClass = RequiredModelMBean.class;
1197         final Class<?> targetClass;
1198         if (opClassName == null)
1199             targetClass = rmmbClass;
1200         else {
1201             AccessControlContext stack = AccessController.getContext();
1202             final String className = opClassName;
1203             targetClass = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Class<?>>() {
1204 
1205                 @Override
1206                 public Class<?> run() {
1207                     try {
1208                         ReflectUtil.checkPackageAccess(className);
1209                         final ClassLoader targetClassLoader =
1210                             rmmbClass.getClassLoader();
1211                         Class clz = Class.forName(className, false,
1212                                                     targetClassLoader);
1213                         if (!rmmbClass.isAssignableFrom(clz))
1214                             return null;
1215                         return clz;
1216                     } catch (ClassNotFoundException e) {
1217                         return null;
1218                     }
1219                 }
1220             }, stack, acc);
1221         }
1222         try {
1223             return targetClass != null ? resolveMethod(targetClass, opMethodName, sig) : null;
1224         } catch (ReflectionException e) {
1225             return null;
1226         }
1227     }
1228 
1229     /*
1230      * Invoke the given method, and throw the somewhat unpredictable
1231      * appropriate exception if the method itself gets an exception.
1232      */
1233     private Object invokeMethod(String opName, final Method method,
1234                                 final Object targetObject, final Object[] opArgs)
1235             throws MBeanException, ReflectionException {
1236         try {
1237             final Throwable[] caughtException = new Throwable[1];
1238             AccessControlContext stack = AccessController.getContext();
1239             Object rslt = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Object>() {
1240 
1241                 @Override
1242                 public Object run() {
1243                     try {
1244                         ReflectUtil.checkPackageAccess(method.getDeclaringClass());
1245                         return MethodUtil.invoke(method, targetObject, opArgs);
1246                     } catch (InvocationTargetException e) {
1247                         caughtException[0] = e;
1248                     } catch (IllegalAccessException e) {
1249                         caughtException[0] = e;
1250                     }
1251                     return null;
1252                 }
1253             }, stack, acc);
1254             if (caughtException[0] != null) {
1255                 if (caughtException[0] instanceof Exception) {
1256                     throw (Exception)caughtException[0];
1257                 } else if(caughtException[0] instanceof Error) {
1258                     throw (Error)caughtException[0];
1259                 }
1260             }
1261             return rslt;
1262         } catch (RuntimeErrorException ree) {
1263             throw new RuntimeOperationsException(ree,
1264                       "RuntimeException occurred in RequiredModelMBean "+
1265                       "while trying to invoke operation " + opName);
1266         } catch (RuntimeException re) {
1267             throw new RuntimeOperationsException(re,
1268                       "RuntimeException occurred in RequiredModelMBean "+
1269                       "while trying to invoke operation " + opName);
1270         } catch (IllegalAccessException iae) {
1271             throw new ReflectionException(iae,
1272                       "IllegalAccessException occurred in " +
1273                       "RequiredModelMBean while trying to " +
1274                       "invoke operation " + opName);
1275         } catch (InvocationTargetException ite) {
1276             Throwable mmbTargEx = ite.getTargetException();
1277             if (mmbTargEx instanceof RuntimeException) {
1278                 throw new MBeanException ((RuntimeException)mmbTargEx,
1279                       "RuntimeException thrown in RequiredModelMBean "+
1280                       "while trying to invoke operation " + opName);
1281             } else if (mmbTargEx instanceof Error) {


1626                         }
1627                     } else {
1628                         // not getMethod so return descriptor (default) value
1629                         String qualifier="";
1630                         response = attrDescr.getFieldValue("value");
1631                         if (response == null) {
1632                             qualifier="default ";
1633                             response = attrDescr.getFieldValue("default");
1634                         }
1635                         if (tracing) {
1636                             MODELMBEAN_LOGGER.logp(Level.FINER,
1637                                     RequiredModelMBean.class.getName(), mth,
1638                                 "could not find getMethod for " +attrName +
1639                                 ", returning descriptor " +qualifier + "value");
1640                         }
1641                         // !! cast response to right class
1642                     }
1643                 }
1644 
1645                 // make sure response class matches type field
1646                 final String respType = attrInfo.getType();
1647                 if (response != null) {
1648                     String responseClass = response.getClass().getName();
1649                     if (!respType.equals(responseClass)) {
1650                         boolean wrongType = false;
1651                         boolean primitiveType = false;
1652                         boolean correspondingTypes = false;
1653                         for (int i = 0; i < primitiveTypes.length; i++) {
1654                             if (respType.equals(primitiveTypes[i])) {
1655                                 primitiveType = true;
1656                                 if (responseClass.equals(primitiveWrappers[i]))
1657                                     correspondingTypes = true;
1658                                 break;
1659                             }
1660                         }
1661                         if (primitiveType) {
1662                             // inequality may come from primitive/wrapper class
1663                             if (!correspondingTypes)
1664                                 wrongType = true;
1665                         } else {
1666                             // inequality may come from type subclassing
1667                             boolean subtype;
1668                             try {
1669                                 final Class respClass = response.getClass();
1670                                 final Exception[] caughException = new Exception[1];
1671 
1672                                 AccessControlContext stack = AccessController.getContext();
1673 
1674                                 Class c = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Class<?>>() {
1675 
1676                                     @Override
1677                                     public Class<?> run() {
1678                                         try {
1679                                             ReflectUtil.checkPackageAccess(respType);
1680                                             ClassLoader cl =
1681                                                 respClass.getClassLoader();
1682                                             return Class.forName(respType, true, cl);
1683                                         } catch (Exception e) {
1684                                             caughException[0] = e;
1685                                         }
1686                                         return null;
1687                                     }
1688                                 }, stack, acc);
1689 
1690                                 if (caughException[0] != null) {
1691                                     throw caughException[0];
1692                                 }
1693 
1694                                 subtype = c.isInstance(response);
1695                             } catch (Exception e) {
1696                                 subtype = false;
1697 
1698                                 if (tracing) {
1699                                     MODELMBEAN_LOGGER.logp(Level.FINER,
1700                                             RequiredModelMBean.class.getName(),
1701                                         mth, "Exception: ",e);
1702                                 }
1703                             }
1704                             if (!subtype)
1705                                 wrongType = true;
1706                         }
1707                         if (wrongType) {
1708                             if (tracing) {
1709                                 MODELMBEAN_LOGGER.logp(Level.FINER,
1710                                         RequiredModelMBean.class.getName(), mth,
1711                                     "Wrong response type '" + respType + "'");
1712                             }
1713                             // throw exception, didn't get


2826             MODELMBEAN_LOGGER.logp(Level.FINER,
2827                     RequiredModelMBean.class.getName(),mth,
2828                 "Exit");
2829         }
2830 
2831     }
2832 
2833     /**
2834      * Return the Class Loader Repository used to perform class loading.
2835      * Subclasses may wish to redefine this method in order to return
2836      * the appropriate {@link javax.management.loading.ClassLoaderRepository}
2837      * that should be used in this object.
2838      *
2839      * @return the Class Loader Repository.
2840      *
2841      */
2842     protected ClassLoaderRepository getClassLoaderRepository() {
2843         return MBeanServerFactory.getClassLoaderRepository(server);
2844     }
2845 
2846     private Class<?> loadClass(final String className)
2847         throws ClassNotFoundException {
2848         AccessControlContext stack = AccessController.getContext();
2849         final ClassNotFoundException[] caughtException = new ClassNotFoundException[1];
2850 
2851         Class c = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Class<?>>() {
2852 
2853             @Override
2854             public Class<?> run() {
2855                 try {
2856                     ReflectUtil.checkPackageAccess(className);
2857                     return Class.forName(className);
2858                 } catch (ClassNotFoundException e) {
2859                     final ClassLoaderRepository clr =
2860                         getClassLoaderRepository();
2861                     try {
2862                         if (clr == null) throw new ClassNotFoundException(className);
2863                         return clr.loadClass(className);
2864                     } catch (ClassNotFoundException ex) {
2865                         caughtException[0] = ex;
2866                     }
2867                 }
2868                 return null;
2869             }
2870         }, stack, acc);
2871 
2872         if (caughtException[0] != null) {
2873             throw caughtException[0];
2874         }
2875 
2876         return c;
2877     }
2878 
2879 
2880     /*************************************/
2881     /* MBeanRegistration Interface       */
2882     /*************************************/
2883 
2884     /**
2885      * Allows the MBean to perform any operations it needs before
2886      * being registered in the MBean server.  If the name of the MBean
2887      * is not specified, the MBean can provide a name for its
2888      * registration.  If any exception is raised, the MBean will not be
2889      * registered in the MBean server.
2890      * <P>
2891      * In order to ensure proper run-time semantics of RequireModelMBean,
2892      * Any subclass of RequiredModelMBean overloading or overriding this
2893      * method should call <code>super.preRegister(server, name)</code>
2894      * in its own <code>preRegister</code> implementation.
2895      *
2896      * @param server The MBean server in which the MBean will be registered.