1 /* 2 * Copyright (c) 2005, 2013, 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 package com.sun.jmx.mbeanserver; 27 28 import java.lang.reflect.InvocationTargetException; 29 import java.lang.reflect.Method; 30 import java.lang.reflect.Type; 31 import java.util.WeakHashMap; 32 import javax.management.Descriptor; 33 import javax.management.ImmutableDescriptor; 34 import javax.management.IntrospectionException; 35 import javax.management.MBeanAttributeInfo; 36 import javax.management.MBeanException; 37 import javax.management.MBeanOperationInfo; 38 import javax.management.NotCompliantMBeanException; 39 import javax.management.NotificationBroadcaster; 40 import javax.management.NotificationBroadcasterSupport; 41 import sun.reflect.misc.MethodUtil; 42 43 /** 44 * @since 1.6 45 */ 46 class StandardMBeanIntrospector extends MBeanIntrospector<Method> { 47 private static final StandardMBeanIntrospector instance = 48 new StandardMBeanIntrospector(); 49 getInstance()50 static StandardMBeanIntrospector getInstance() { 51 return instance; 52 } 53 54 @Override getPerInterfaceMap()55 PerInterfaceMap<Method> getPerInterfaceMap() { 56 return perInterfaceMap; 57 } 58 59 @Override getMBeanInfoMap()60 MBeanInfoMap getMBeanInfoMap() { 61 return mbeanInfoMap; 62 } 63 64 @Override getAnalyzer(Class<?> mbeanInterface)65 MBeanAnalyzer<Method> getAnalyzer(Class<?> mbeanInterface) 66 throws NotCompliantMBeanException { 67 return MBeanAnalyzer.analyzer(mbeanInterface, this); 68 } 69 70 @Override isMXBean()71 boolean isMXBean() { 72 return false; 73 } 74 75 @Override mFrom(Method m)76 Method mFrom(Method m) { 77 return m; 78 } 79 80 @Override getName(Method m)81 String getName(Method m) { 82 return m.getName(); 83 } 84 85 @Override getGenericReturnType(Method m)86 Type getGenericReturnType(Method m) { 87 return m.getGenericReturnType(); 88 } 89 90 @Override getGenericParameterTypes(Method m)91 Type[] getGenericParameterTypes(Method m) { 92 return m.getGenericParameterTypes(); 93 } 94 95 @Override getSignature(Method m)96 String[] getSignature(Method m) { 97 Class<?>[] params = m.getParameterTypes(); 98 String[] sig = new String[params.length]; 99 for (int i = 0; i < params.length; i++) 100 sig[i] = params[i].getName(); 101 return sig; 102 } 103 104 @Override checkMethod(Method m)105 void checkMethod(Method m) { 106 } 107 108 @Override invokeM2(Method m, Object target, Object[] args, Object cookie)109 Object invokeM2(Method m, Object target, Object[] args, Object cookie) 110 throws InvocationTargetException, IllegalAccessException, 111 MBeanException { 112 return MethodUtil.invoke(m, target, args); 113 } 114 115 @Override validParameter(Method m, Object value, int paramNo, Object cookie)116 boolean validParameter(Method m, Object value, int paramNo, Object cookie) { 117 return isValidParameter(m, value, paramNo); 118 } 119 120 @Override getMBeanAttributeInfo(String attributeName, Method getter, Method setter)121 MBeanAttributeInfo getMBeanAttributeInfo(String attributeName, 122 Method getter, Method setter) { 123 124 final String description = "Attribute exposed for management"; 125 try { 126 return new MBeanAttributeInfo(attributeName, description, 127 getter, setter); 128 } catch (IntrospectionException e) { 129 throw new RuntimeException(e); // should not happen 130 } 131 } 132 133 @Override getMBeanOperationInfo(String operationName, Method operation)134 MBeanOperationInfo getMBeanOperationInfo(String operationName, 135 Method operation) { 136 final String description = "Operation exposed for management"; 137 return new MBeanOperationInfo(description, operation); 138 } 139 140 @Override getBasicMBeanDescriptor()141 Descriptor getBasicMBeanDescriptor() { 142 /* We don't bother saying mxbean=false, and we can't know whether 143 the info is immutable until we know whether the MBean class 144 (not interface) is a NotificationBroadcaster. */ 145 return ImmutableDescriptor.EMPTY_DESCRIPTOR; 146 } 147 148 @Override getMBeanDescriptor(Class<?> resourceClass)149 Descriptor getMBeanDescriptor(Class<?> resourceClass) { 150 boolean immutable = isDefinitelyImmutableInfo(resourceClass); 151 return new ImmutableDescriptor("mxbean=false", 152 "immutableInfo=" + immutable); 153 } 154 155 /* Return true if and only if we can be sure that the given MBean implementation 156 * class has immutable MBeanInfo. A Standard MBean that is a 157 * NotificationBroadcaster is allowed to return different values at 158 * different times from its getNotificationInfo() method, which is when 159 * we might not know if it is immutable. But if it is a subclass of 160 * NotificationBroadcasterSupport and does not override 161 * getNotificationInfo(), then we know it won't change. 162 */ isDefinitelyImmutableInfo(Class<?> implClass)163 static boolean isDefinitelyImmutableInfo(Class<?> implClass) { 164 if (!NotificationBroadcaster.class.isAssignableFrom(implClass)) 165 return true; 166 synchronized (definitelyImmutable) { 167 Boolean immutable = definitelyImmutable.get(implClass); 168 if (immutable == null) { 169 final Class<NotificationBroadcasterSupport> nbs = 170 NotificationBroadcasterSupport.class; 171 if (nbs.isAssignableFrom(implClass)) { 172 try { 173 Method m = implClass.getMethod("getNotificationInfo"); 174 immutable = (m.getDeclaringClass() == nbs); 175 } catch (Exception e) { 176 // Too bad, we'll say no for now. 177 return false; 178 } 179 } else 180 immutable = false; 181 definitelyImmutable.put(implClass, immutable); 182 } 183 return immutable; 184 } 185 } 186 private static final WeakHashMap<Class<?>, Boolean> definitelyImmutable = 187 new WeakHashMap<Class<?>, Boolean>(); 188 189 private static final PerInterfaceMap<Method> 190 perInterfaceMap = new PerInterfaceMap<Method>(); 191 192 private static final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap(); 193 } 194