23 * have any questions. |
23 * have any questions. |
24 */ |
24 */ |
25 |
25 |
26 package com.sun.jmx.remote.util; |
26 package com.sun.jmx.remote.util; |
27 |
27 |
|
28 import com.sun.jmx.defaults.JmxProperties; |
28 import com.sun.jmx.event.EventClientFactory; |
29 import com.sun.jmx.event.EventClientFactory; |
29 |
30 |
30 import java.lang.reflect.InvocationHandler; |
31 import java.lang.reflect.InvocationHandler; |
31 import java.lang.reflect.InvocationTargetException; |
32 import java.lang.reflect.InvocationTargetException; |
32 import java.lang.reflect.Method; |
33 import java.lang.reflect.Method; |
43 import javax.management.NotificationFilter; |
44 import javax.management.NotificationFilter; |
44 import javax.management.NotificationListener; |
45 import javax.management.NotificationListener; |
45 import javax.management.ObjectName; |
46 import javax.management.ObjectName; |
46 import javax.management.event.EventClient; |
47 import javax.management.event.EventClient; |
47 import javax.management.event.EventClientDelegate; |
48 import javax.management.event.EventClientDelegate; |
|
49 import javax.management.namespace.JMXNamespaces; |
48 |
50 |
49 /** |
51 /** |
50 * Class EventClientConnection - a {@link Proxy} that wraps an |
52 * Class EventClientConnection - a {@link Proxy} that wraps an |
51 * {@link MBeanServerConnection} and an {@link EventClient}. |
53 * {@link MBeanServerConnection} and an {@link EventClient}. |
52 * All methods are routed to the underlying {@code MBeanServerConnection}, |
54 * All methods are routed to the underlying {@code MBeanServerConnection}, |
61 EventClientFactory { |
63 EventClientFactory { |
62 |
64 |
63 /** |
65 /** |
64 * A logger for this class. |
66 * A logger for this class. |
65 **/ |
67 **/ |
66 private static final Logger LOG = |
68 private static final Logger LOG = JmxProperties.NOTIFICATION_LOGGER; |
67 Logger.getLogger(EventClientConnection.class.getName()); |
69 |
68 |
|
69 private static final String NAMESPACE_SEPARATOR = "//"; |
|
70 private static final int NAMESPACE_SEPARATOR_LENGTH = |
70 private static final int NAMESPACE_SEPARATOR_LENGTH = |
71 NAMESPACE_SEPARATOR.length(); |
71 JMXNamespaces.NAMESPACE_SEPARATOR.length(); |
72 |
72 |
73 /** |
73 /** |
74 * Creates a new {@code EventClientConnection}. |
74 * Creates a new {@code EventClientConnection}. |
75 * @param connection The underlying MBeanServerConnection. |
75 * @param connection The underlying MBeanServerConnection. |
76 */ |
76 */ |
210 "Bad arg count: " + nargs; |
210 "Bad arg count: " + nargs; |
211 throw new IllegalArgumentException(msg); |
211 throw new IllegalArgumentException(msg); |
212 } |
212 } |
213 |
213 |
214 final ObjectName mbean = (ObjectName) args[0]; |
214 final ObjectName mbean = (ObjectName) args[0]; |
215 final EventClient client = getEventClient(); |
215 final EventClient evtClient = getEventClient(); |
216 |
216 |
217 // Fails if client is null AND the MBean we try to listen to is |
217 // Fails if evtClient is null AND the MBean we try to listen to is |
218 // in a subnamespace. We fail here because we know this will not |
218 // in a subnamespace. We fail here because we know this will not |
219 // work. |
219 // work. |
220 // |
220 // |
221 // Note that if the wrapped MBeanServerConnection points to a an |
221 // Note that if the wrapped MBeanServerConnection points to a an |
222 // earlier agent (JDK 1.6 or earlier), then the EventClient will |
222 // earlier agent (JDK 1.6 or earlier), then the EventClient will |
223 // be null (we can't use the event service with earlier JDKs). |
223 // be null (we can't use the event service with earlier JDKs). |
224 // |
224 // |
225 // In principle a null client indicates that the remote VM is of |
225 // In principle a null evtClient indicates that the remote VM is of |
226 // an earlier version, in which case it shouldn't contain any namespace. |
226 // an earlier version, in which case it shouldn't contain any namespace. |
227 // |
227 // |
228 // So having a null client AND an MBean contained in a namespace is |
228 // So having a null evtClient AND an MBean contained in a namespace is |
229 // clearly an error case. |
229 // clearly an error case. |
230 // |
230 // |
231 if (client == null) { |
231 if (evtClient == null) { |
232 final String domain = mbean.getDomain(); |
232 final String domain = mbean.getDomain(); |
233 final int index = domain.indexOf(NAMESPACE_SEPARATOR); |
233 final int index = domain.indexOf(JMXNamespaces.NAMESPACE_SEPARATOR); |
234 if (index > -1 && index < |
234 if (index > -1 && index < |
235 (domain.length()-NAMESPACE_SEPARATOR_LENGTH)) { |
235 (domain.length()-NAMESPACE_SEPARATOR_LENGTH)) { |
236 throw new UnsupportedOperationException(method.getName()+ |
236 throw new UnsupportedOperationException(method.getName()+ |
237 " on namespace "+domain.substring(0,index+ |
237 " on namespace "+domain.substring(0,index+ |
238 NAMESPACE_SEPARATOR_LENGTH)); |
238 NAMESPACE_SEPARATOR_LENGTH)); |
254 |
254 |
255 final NotificationListener listener = (NotificationListener) args[1]; |
255 final NotificationListener listener = (NotificationListener) args[1]; |
256 final NotificationFilter filter = (NotificationFilter) args[2]; |
256 final NotificationFilter filter = (NotificationFilter) args[2]; |
257 final Object handback = args[3]; |
257 final Object handback = args[3]; |
258 |
258 |
259 if (client != null) { |
259 if (evtClient != null) { |
260 // general case |
260 // general case |
261 client.addNotificationListener(mbean,listener,filter,handback); |
261 evtClient.addNotificationListener(mbean,listener,filter,handback); |
262 } else { |
262 } else { |
263 // deprecated case. Only works for mbean in local namespace. |
263 // deprecated case. Only works for mbean in local namespace. |
264 connection.addNotificationListener(mbean,listener,filter, |
264 connection.addNotificationListener(mbean,listener,filter, |
265 handback); |
265 handback); |
266 } |
266 } |
272 shouldn't happen because removeNL does have args. */ |
272 shouldn't happen because removeNL does have args. */ |
273 NotificationListener listener = (NotificationListener) args[1]; |
273 NotificationListener listener = (NotificationListener) args[1]; |
274 |
274 |
275 switch (nargs) { |
275 switch (nargs) { |
276 case 2: |
276 case 2: |
277 if (client != null) { |
277 if (evtClient != null) { |
278 // general case |
278 // general case |
279 client.removeNotificationListener(mbean,listener); |
279 evtClient.removeNotificationListener(mbean,listener); |
280 } else { |
280 } else { |
281 // deprecated case. Only works for mbean in local namespace. |
281 // deprecated case. Only works for mbean in local namespace. |
282 connection.removeNotificationListener(mbean, listener); |
282 connection.removeNotificationListener(mbean, listener); |
283 } |
283 } |
284 return null; |
284 return null; |
285 |
285 |
286 case 4: |
286 case 4: |
287 NotificationFilter filter = (NotificationFilter) args[2]; |
287 NotificationFilter filter = (NotificationFilter) args[2]; |
288 Object handback = args[3]; |
288 Object handback = args[3]; |
289 if (client != null) { |
289 if (evtClient != null) { |
290 client.removeNotificationListener(mbean, |
290 evtClient.removeNotificationListener(mbean, |
291 listener, |
291 listener, |
292 filter, |
292 filter, |
293 handback); |
293 handback); |
294 } else { |
294 } else { |
295 connection.removeNotificationListener(mbean, |
295 connection.removeNotificationListener(mbean, |