author | kbarrett |
Mon, 18 Feb 2019 16:34:46 -0500 | |
changeset 53792 | 6fb43030a1b4 |
parent 47216 | 71c04702a3d5 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
23010
6dadb192ad81
8029235: Update copyright year to match last edit in jdk8 jdk repository for 2013
lana
parents:
18805
diff
changeset
|
2 |
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. |
2 | 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 |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 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 |
* |
|
5506 | 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. |
|
2 | 24 |
*/ |
25 |
||
26 |
package javax.management; |
|
27 |
||
28 |
import com.sun.jmx.mbeanserver.MXBeanProxy; |
|
29 |
||
30 |
import java.lang.ref.WeakReference; |
|
31 |
import java.lang.reflect.InvocationHandler; |
|
32 |
import java.lang.reflect.Method; |
|
33 |
import java.lang.reflect.Proxy; |
|
34 |
import java.util.Arrays; |
|
35 |
import java.util.WeakHashMap; |
|
36 |
||
37 |
/** |
|
38 |
* <p>{@link InvocationHandler} that forwards methods in an MBean's |
|
39 |
* management interface through the MBean server to the MBean.</p> |
|
40 |
* |
|
41 |
* <p>Given an {@link MBeanServerConnection}, the {@link ObjectName} |
|
42 |
* of an MBean within that MBean server, and a Java interface |
|
43 |
* <code>Intf</code> that describes the management interface of the |
|
44 |
* MBean using the patterns for a Standard MBean or an MXBean, this |
|
45 |
* class can be used to construct a proxy for the MBean. The proxy |
|
46 |
* implements the interface <code>Intf</code> such that all of its |
|
47 |
* methods are forwarded through the MBean server to the MBean.</p> |
|
48 |
* |
|
49 |
* <p>If the {@code InvocationHandler} is for an MXBean, then the parameters of |
|
50 |
* a method are converted from the type declared in the MXBean |
|
51 |
* interface into the corresponding mapped type, and the return value |
|
52 |
* is converted from the mapped type into the declared type. For |
|
53 |
* example, with the method<br> |
|
54 |
||
55 |
* {@code public List<String> reverse(List<String> list);}<br> |
|
56 |
||
57 |
* and given that the mapped type for {@code List<String>} is {@code |
|
58 |
* String[]}, a call to {@code proxy.reverse(someList)} will convert |
|
59 |
* {@code someList} from a {@code List<String>} to a {@code String[]}, |
|
60 |
* call the MBean operation {@code reverse}, then convert the returned |
|
61 |
* {@code String[]} into a {@code List<String>}.</p> |
|
62 |
* |
|
63 |
* <p>The method Object.toString(), Object.hashCode(), or |
|
64 |
* Object.equals(Object), when invoked on a proxy using this |
|
65 |
* invocation handler, is forwarded to the MBean server as a method on |
|
66 |
* the proxied MBean only if it appears in one of the proxy's |
|
67 |
* interfaces. For a proxy created with {@link |
|
68 |
* JMX#newMBeanProxy(MBeanServerConnection, ObjectName, Class) |
|
69 |
* JMX.newMBeanProxy} or {@link |
|
70 |
* JMX#newMXBeanProxy(MBeanServerConnection, ObjectName, Class) |
|
71 |
* JMX.newMXBeanProxy}, this means that the method must appear in the |
|
72 |
* Standard MBean or MXBean interface. Otherwise these methods have |
|
73 |
* the following behavior: |
|
74 |
* <ul> |
|
75 |
* <li>toString() returns a string representation of the proxy |
|
76 |
* <li>hashCode() returns a hash code for the proxy such |
|
77 |
* that two equal proxies have the same hash code |
|
78 |
* <li>equals(Object) |
|
79 |
* returns true if and only if the Object argument is of the same |
|
80 |
* proxy class as this proxy, with an MBeanServerInvocationHandler |
|
81 |
* that has the same MBeanServerConnection and ObjectName; if one |
|
82 |
* of the {@code MBeanServerInvocationHandler}s was constructed with |
|
83 |
* a {@code Class} argument then the other must have been constructed |
|
84 |
* with the same {@code Class} for {@code equals} to return true. |
|
85 |
* </ul> |
|
86 |
* |
|
87 |
* @since 1.5 |
|
88 |
*/ |
|
89 |
public class MBeanServerInvocationHandler implements InvocationHandler { |
|
90 |
/** |
|
91 |
* <p>Invocation handler that forwards methods through an MBean |
|
92 |
* server to a Standard MBean. This constructor may be called |
|
93 |
* instead of relying on {@link |
|
94 |
* JMX#newMBeanProxy(MBeanServerConnection, ObjectName, Class) |
|
95 |
* JMX.newMBeanProxy}, for instance if you need to supply a |
|
96 |
* different {@link ClassLoader} to {@link Proxy#newProxyInstance |
|
97 |
* Proxy.newProxyInstance}.</p> |
|
98 |
* |
|
99 |
* <p>This constructor is not appropriate for an MXBean. Use |
|
100 |
* {@link #MBeanServerInvocationHandler(MBeanServerConnection, |
|
101 |
* ObjectName, boolean)} for that. This constructor is equivalent |
|
102 |
* to {@code new MBeanServerInvocationHandler(connection, |
|
103 |
* objectName, false)}.</p> |
|
104 |
* |
|
105 |
* @param connection the MBean server connection through which all |
|
106 |
* methods of a proxy using this handler will be forwarded. |
|
107 |
* |
|
108 |
* @param objectName the name of the MBean within the MBean server |
|
109 |
* to which methods will be forwarded. |
|
110 |
*/ |
|
111 |
public MBeanServerInvocationHandler(MBeanServerConnection connection, |
|
112 |
ObjectName objectName) { |
|
113 |
||
4156 | 114 |
this(connection, objectName, false); |
2 | 115 |
} |
116 |
||
117 |
/** |
|
118 |
* <p>Invocation handler that can forward methods through an MBean |
|
119 |
* server to a Standard MBean or MXBean. This constructor may be called |
|
120 |
* instead of relying on {@link |
|
121 |
* JMX#newMXBeanProxy(MBeanServerConnection, ObjectName, Class) |
|
122 |
* JMX.newMXBeanProxy}, for instance if you need to supply a |
|
123 |
* different {@link ClassLoader} to {@link Proxy#newProxyInstance |
|
124 |
* Proxy.newProxyInstance}.</p> |
|
125 |
* |
|
126 |
* @param connection the MBean server connection through which all |
|
127 |
* methods of a proxy using this handler will be forwarded. |
|
128 |
* |
|
129 |
* @param objectName the name of the MBean within the MBean server |
|
130 |
* to which methods will be forwarded. |
|
131 |
* |
|
132 |
* @param isMXBean if true, the proxy is for an {@link MXBean}, and |
|
133 |
* appropriate mappings will be applied to method parameters and return |
|
134 |
* values. |
|
135 |
* |
|
136 |
* @since 1.6 |
|
137 |
*/ |
|
138 |
public MBeanServerInvocationHandler(MBeanServerConnection connection, |
|
139 |
ObjectName objectName, |
|
140 |
boolean isMXBean) { |
|
141 |
if (connection == null) { |
|
142 |
throw new IllegalArgumentException("Null connection"); |
|
143 |
} |
|
31701 | 144 |
if (Proxy.isProxyClass(connection.getClass())) { |
145 |
if (MBeanServerInvocationHandler.class.isAssignableFrom( |
|
146 |
Proxy.getInvocationHandler(connection).getClass())) { |
|
147 |
throw new IllegalArgumentException("Wrapping MBeanServerInvocationHandler"); |
|
148 |
} |
|
149 |
} |
|
2 | 150 |
if (objectName == null) { |
151 |
throw new IllegalArgumentException("Null object name"); |
|
152 |
} |
|
153 |
this.connection = connection; |
|
154 |
this.objectName = objectName; |
|
4156 | 155 |
this.isMXBean = isMXBean; |
2 | 156 |
} |
157 |
||
158 |
/** |
|
159 |
* <p>The MBean server connection through which the methods of |
|
160 |
* a proxy using this handler are forwarded.</p> |
|
161 |
* |
|
162 |
* @return the MBean server connection. |
|
163 |
* |
|
164 |
* @since 1.6 |
|
165 |
*/ |
|
166 |
public MBeanServerConnection getMBeanServerConnection() { |
|
167 |
return connection; |
|
168 |
} |
|
169 |
||
170 |
/** |
|
171 |
* <p>The name of the MBean within the MBean server to which methods |
|
172 |
* are forwarded. |
|
173 |
* |
|
174 |
* @return the object name. |
|
175 |
* |
|
176 |
* @since 1.6 |
|
177 |
*/ |
|
178 |
public ObjectName getObjectName() { |
|
179 |
return objectName; |
|
180 |
} |
|
181 |
||
182 |
/** |
|
183 |
* <p>If true, the proxy is for an MXBean, and appropriate mappings |
|
184 |
* are applied to method parameters and return values. |
|
185 |
* |
|
186 |
* @return whether the proxy is for an MXBean. |
|
187 |
* |
|
188 |
* @since 1.6 |
|
189 |
*/ |
|
190 |
public boolean isMXBean() { |
|
4156 | 191 |
return isMXBean; |
2 | 192 |
} |
193 |
||
194 |
/** |
|
195 |
* <p>Return a proxy that implements the given interface by |
|
196 |
* forwarding its methods through the given MBean server to the |
|
197 |
* named MBean. As of 1.6, the methods {@link |
|
198 |
* JMX#newMBeanProxy(MBeanServerConnection, ObjectName, Class)} and |
|
199 |
* {@link JMX#newMBeanProxy(MBeanServerConnection, ObjectName, Class, |
|
200 |
* boolean)} are preferred to this method.</p> |
|
201 |
* |
|
202 |
* <p>This method is equivalent to {@link Proxy#newProxyInstance |
|
203 |
* Proxy.newProxyInstance}<code>(interfaceClass.getClassLoader(), |
|
204 |
* interfaces, handler)</code>. Here <code>handler</code> is the |
|
205 |
* result of {@link #MBeanServerInvocationHandler new |
|
206 |
* MBeanServerInvocationHandler(connection, objectName)}, and |
|
207 |
* <code>interfaces</code> is an array that has one element if |
|
208 |
* <code>notificationBroadcaster</code> is false and two if it is |
|
209 |
* true. The first element of <code>interfaces</code> is |
|
210 |
* <code>interfaceClass</code> and the second, if present, is |
|
211 |
* <code>NotificationEmitter.class</code>. |
|
212 |
* |
|
213 |
* @param connection the MBean server to forward to. |
|
214 |
* @param objectName the name of the MBean within |
|
215 |
* <code>connection</code> to forward to. |
|
216 |
* @param interfaceClass the management interface that the MBean |
|
217 |
* exports, which will also be implemented by the returned proxy. |
|
218 |
* @param notificationBroadcaster make the returned proxy |
|
219 |
* implement {@link NotificationEmitter} by forwarding its methods |
|
220 |
* via <code>connection</code>. A call to {@link |
|
221 |
* NotificationBroadcaster#addNotificationListener} on the proxy will |
|
222 |
* result in a call to {@link |
|
223 |
* MBeanServerConnection#addNotificationListener(ObjectName, |
|
224 |
* NotificationListener, NotificationFilter, Object)}, and likewise |
|
225 |
* for the other methods of {@link NotificationBroadcaster} and {@link |
|
226 |
* NotificationEmitter}. |
|
227 |
* |
|
228 |
* @param <T> allows the compiler to know that if the {@code |
|
229 |
* interfaceClass} parameter is {@code MyMBean.class}, for example, |
|
230 |
* then the return type is {@code MyMBean}. |
|
231 |
* |
|
232 |
* @return the new proxy instance. |
|
233 |
* |
|
18805
b359f8adc8ad
8010285: Enforce the requirement of Management Interfaces being public
jbachorik
parents:
18213
diff
changeset
|
234 |
* @see JMX#newMBeanProxy(MBeanServerConnection, ObjectName, Class, boolean) |
2 | 235 |
*/ |
236 |
public static <T> T newProxyInstance(MBeanServerConnection connection, |
|
237 |
ObjectName objectName, |
|
238 |
Class<T> interfaceClass, |
|
239 |
boolean notificationBroadcaster) { |
|
18213
45c8ed869a1b
8008982: Adjust JMX for underlying interface changes
jbachorik
parents:
5506
diff
changeset
|
240 |
return JMX.newMBeanProxy(connection, objectName, interfaceClass, notificationBroadcaster); |
2 | 241 |
} |
242 |
||
243 |
public Object invoke(Object proxy, Method method, Object[] args) |
|
244 |
throws Throwable { |
|
1510 | 245 |
final Class<?> methodClass = method.getDeclaringClass(); |
2 | 246 |
|
247 |
if (methodClass.equals(NotificationBroadcaster.class) |
|
248 |
|| methodClass.equals(NotificationEmitter.class)) |
|
249 |
return invokeBroadcasterMethod(proxy, method, args); |
|
250 |
||
251 |
// local or not: equals, toString, hashCode |
|
252 |
if (shouldDoLocally(proxy, method)) |
|
253 |
return doLocally(proxy, method, args); |
|
254 |
||
255 |
try { |
|
687 | 256 |
if (isMXBean()) { |
2 | 257 |
MXBeanProxy p = findMXBeanProxy(methodClass); |
258 |
return p.invoke(connection, objectName, method, args); |
|
259 |
} else { |
|
260 |
final String methodName = method.getName(); |
|
1510 | 261 |
final Class<?>[] paramTypes = method.getParameterTypes(); |
262 |
final Class<?> returnType = method.getReturnType(); |
|
2 | 263 |
|
264 |
/* Inexplicably, InvocationHandler specifies that args is null |
|
265 |
when the method takes no arguments rather than a |
|
266 |
zero-length array. */ |
|
267 |
final int nargs = (args == null) ? 0 : args.length; |
|
268 |
||
269 |
if (methodName.startsWith("get") |
|
270 |
&& methodName.length() > 3 |
|
271 |
&& nargs == 0 |
|
272 |
&& !returnType.equals(Void.TYPE)) { |
|
273 |
return connection.getAttribute(objectName, |
|
274 |
methodName.substring(3)); |
|
275 |
} |
|
276 |
||
277 |
if (methodName.startsWith("is") |
|
278 |
&& methodName.length() > 2 |
|
279 |
&& nargs == 0 |
|
280 |
&& (returnType.equals(Boolean.TYPE) |
|
281 |
|| returnType.equals(Boolean.class))) { |
|
282 |
return connection.getAttribute(objectName, |
|
283 |
methodName.substring(2)); |
|
284 |
} |
|
285 |
||
286 |
if (methodName.startsWith("set") |
|
287 |
&& methodName.length() > 3 |
|
288 |
&& nargs == 1 |
|
289 |
&& returnType.equals(Void.TYPE)) { |
|
290 |
Attribute attr = new Attribute(methodName.substring(3), args[0]); |
|
291 |
connection.setAttribute(objectName, attr); |
|
292 |
return null; |
|
293 |
} |
|
294 |
||
295 |
final String[] signature = new String[paramTypes.length]; |
|
296 |
for (int i = 0; i < paramTypes.length; i++) |
|
297 |
signature[i] = paramTypes[i].getName(); |
|
298 |
return connection.invoke(objectName, methodName, |
|
299 |
args, signature); |
|
300 |
} |
|
301 |
} catch (MBeanException e) { |
|
302 |
throw e.getTargetException(); |
|
303 |
} catch (RuntimeMBeanException re) { |
|
304 |
throw re.getTargetException(); |
|
305 |
} catch (RuntimeErrorException rre) { |
|
306 |
throw rre.getTargetError(); |
|
307 |
} |
|
308 |
/* The invoke may fail because it can't get to the MBean, with |
|
309 |
one of the these exceptions declared by |
|
310 |
MBeanServerConnection.invoke: |
|
311 |
- RemoteException: can't talk to MBeanServer; |
|
312 |
- InstanceNotFoundException: objectName is not registered; |
|
313 |
- ReflectionException: objectName is registered but does not |
|
314 |
have the method being invoked. |
|
315 |
In all of these cases, the exception will be wrapped by the |
|
316 |
proxy mechanism in an UndeclaredThrowableException unless |
|
317 |
it happens to be declared in the "throws" clause of the |
|
318 |
method being invoked on the proxy. |
|
319 |
*/ |
|
320 |
} |
|
321 |
||
4156 | 322 |
private static MXBeanProxy findMXBeanProxy(Class<?> mxbeanInterface) { |
2 | 323 |
synchronized (mxbeanProxies) { |
4156 | 324 |
WeakReference<MXBeanProxy> proxyRef = |
325 |
mxbeanProxies.get(mxbeanInterface); |
|
326 |
MXBeanProxy p = (proxyRef == null) ? null : proxyRef.get(); |
|
327 |
if (p == null) { |
|
328 |
try { |
|
329 |
p = new MXBeanProxy(mxbeanInterface); |
|
330 |
} catch (IllegalArgumentException e) { |
|
331 |
String msg = "Cannot make MXBean proxy for " + |
|
332 |
mxbeanInterface.getName() + ": " + e.getMessage(); |
|
333 |
IllegalArgumentException iae = |
|
334 |
new IllegalArgumentException(msg, e.getCause()); |
|
335 |
iae.setStackTrace(e.getStackTrace()); |
|
336 |
throw iae; |
|
337 |
} |
|
338 |
mxbeanProxies.put(mxbeanInterface, |
|
339 |
new WeakReference<MXBeanProxy>(p)); |
|
2 | 340 |
} |
341 |
return p; |
|
342 |
} |
|
343 |
} |
|
4156 | 344 |
private static final WeakHashMap<Class<?>, WeakReference<MXBeanProxy>> |
345 |
mxbeanProxies = new WeakHashMap<Class<?>, WeakReference<MXBeanProxy>>(); |
|
2 | 346 |
|
347 |
private Object invokeBroadcasterMethod(Object proxy, Method method, |
|
348 |
Object[] args) throws Exception { |
|
349 |
final String methodName = method.getName(); |
|
350 |
final int nargs = (args == null) ? 0 : args.length; |
|
351 |
||
352 |
if (methodName.equals("addNotificationListener")) { |
|
353 |
/* The various throws of IllegalArgumentException here |
|
354 |
should not happen, since we know what the methods in |
|
355 |
NotificationBroadcaster and NotificationEmitter |
|
356 |
are. */ |
|
357 |
if (nargs != 3) { |
|
358 |
final String msg = |
|
359 |
"Bad arg count to addNotificationListener: " + nargs; |
|
360 |
throw new IllegalArgumentException(msg); |
|
361 |
} |
|
362 |
/* Other inconsistencies will produce ClassCastException |
|
363 |
below. */ |
|
364 |
||
365 |
NotificationListener listener = (NotificationListener) args[0]; |
|
366 |
NotificationFilter filter = (NotificationFilter) args[1]; |
|
367 |
Object handback = args[2]; |
|
368 |
connection.addNotificationListener(objectName, |
|
369 |
listener, |
|
370 |
filter, |
|
371 |
handback); |
|
372 |
return null; |
|
373 |
||
374 |
} else if (methodName.equals("removeNotificationListener")) { |
|
375 |
||
376 |
/* NullPointerException if method with no args, but that |
|
377 |
shouldn't happen because removeNL does have args. */ |
|
378 |
NotificationListener listener = (NotificationListener) args[0]; |
|
379 |
||
380 |
switch (nargs) { |
|
381 |
case 1: |
|
382 |
connection.removeNotificationListener(objectName, listener); |
|
383 |
return null; |
|
384 |
||
385 |
case 3: |
|
386 |
NotificationFilter filter = (NotificationFilter) args[1]; |
|
387 |
Object handback = args[2]; |
|
388 |
connection.removeNotificationListener(objectName, |
|
389 |
listener, |
|
390 |
filter, |
|
391 |
handback); |
|
392 |
return null; |
|
393 |
||
394 |
default: |
|
395 |
final String msg = |
|
396 |
"Bad arg count to removeNotificationListener: " + nargs; |
|
397 |
throw new IllegalArgumentException(msg); |
|
398 |
} |
|
399 |
||
400 |
} else if (methodName.equals("getNotificationInfo")) { |
|
401 |
||
402 |
if (args != null) { |
|
403 |
throw new IllegalArgumentException("getNotificationInfo has " + |
|
404 |
"args"); |
|
405 |
} |
|
406 |
||
407 |
MBeanInfo info = connection.getMBeanInfo(objectName); |
|
408 |
return info.getNotifications(); |
|
409 |
||
410 |
} else { |
|
411 |
throw new IllegalArgumentException("Bad method name: " + |
|
412 |
methodName); |
|
413 |
} |
|
414 |
} |
|
415 |
||
416 |
private boolean shouldDoLocally(Object proxy, Method method) { |
|
417 |
final String methodName = method.getName(); |
|
418 |
if ((methodName.equals("hashCode") || methodName.equals("toString")) |
|
419 |
&& method.getParameterTypes().length == 0 |
|
420 |
&& isLocal(proxy, method)) |
|
421 |
return true; |
|
422 |
if (methodName.equals("equals") |
|
423 |
&& Arrays.equals(method.getParameterTypes(), |
|
1510 | 424 |
new Class<?>[] {Object.class}) |
2 | 425 |
&& isLocal(proxy, method)) |
426 |
return true; |
|
31701 | 427 |
if (methodName.equals("finalize") |
428 |
&& method.getParameterTypes().length == 0) { |
|
429 |
return true; |
|
430 |
} |
|
2 | 431 |
return false; |
432 |
} |
|
433 |
||
434 |
private Object doLocally(Object proxy, Method method, Object[] args) { |
|
435 |
final String methodName = method.getName(); |
|
436 |
||
437 |
if (methodName.equals("equals")) { |
|
438 |
||
439 |
if (this == args[0]) { |
|
440 |
return true; |
|
441 |
} |
|
442 |
||
443 |
if (!(args[0] instanceof Proxy)) { |
|
444 |
return false; |
|
445 |
} |
|
446 |
||
447 |
final InvocationHandler ihandler = |
|
448 |
Proxy.getInvocationHandler(args[0]); |
|
449 |
||
450 |
if (ihandler == null || |
|
451 |
!(ihandler instanceof MBeanServerInvocationHandler)) { |
|
452 |
return false; |
|
453 |
} |
|
454 |
||
455 |
final MBeanServerInvocationHandler handler = |
|
456 |
(MBeanServerInvocationHandler)ihandler; |
|
457 |
||
458 |
return connection.equals(handler.connection) && |
|
459 |
objectName.equals(handler.objectName) && |
|
460 |
proxy.getClass().equals(args[0].getClass()); |
|
461 |
} else if (methodName.equals("toString")) { |
|
687 | 462 |
return (isMXBean() ? "MX" : "M") + "BeanProxy(" + |
2 | 463 |
connection + "[" + objectName + "])"; |
464 |
} else if (methodName.equals("hashCode")) { |
|
465 |
return objectName.hashCode()+connection.hashCode(); |
|
31700 | 466 |
} else if (methodName.equals("finalize")) { |
467 |
// ignore the finalizer invocation via proxy |
|
468 |
return null; |
|
2 | 469 |
} |
470 |
||
471 |
throw new RuntimeException("Unexpected method name: " + methodName); |
|
472 |
} |
|
473 |
||
474 |
private static boolean isLocal(Object proxy, Method method) { |
|
475 |
final Class<?>[] interfaces = proxy.getClass().getInterfaces(); |
|
476 |
if(interfaces == null) { |
|
477 |
return true; |
|
478 |
} |
|
479 |
||
480 |
final String methodName = method.getName(); |
|
481 |
final Class<?>[] params = method.getParameterTypes(); |
|
482 |
for (Class<?> intf : interfaces) { |
|
483 |
try { |
|
484 |
intf.getMethod(methodName, params); |
|
485 |
return false; // found method in one of our interfaces |
|
486 |
} catch (NoSuchMethodException nsme) { |
|
487 |
// OK. |
|
488 |
} |
|
489 |
} |
|
490 |
||
491 |
return true; // did not find in any interface |
|
492 |
} |
|
493 |
||
494 |
private final MBeanServerConnection connection; |
|
495 |
private final ObjectName objectName; |
|
4156 | 496 |
private final boolean isMXBean; |
2 | 497 |
} |