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.
|