1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.archive.hcc;
24
25 import java.lang.reflect.InvocationHandler;
26 import java.lang.reflect.Method;
27 import java.util.HashMap;
28 import java.util.Map;
29 import java.util.logging.Level;
30 import java.util.logging.Logger;
31
32 import javax.management.Attribute;
33 import javax.management.AttributeList;
34 import javax.management.MBeanServerConnection;
35 import javax.management.Notification;
36 import javax.management.NotificationFilter;
37 import javax.management.NotificationListener;
38 import javax.management.ObjectName;
39
40 /***
41 * This invocation handler is responsible for proxying calls to and
42 * remote notifications from remote mbean instances.
43 * @author Daniel Bernstein (dbernstein@archive.org)
44 */
45 public class RemoteMBeanInvocationHandler implements
46 InvocationHandler {
47
48 private static Logger log =
49 Logger.getLogger(RemoteMBeanInvocationHandler.class.getName());
50
51 private ObjectName remoteObjectName;
52
53 private MBeanServerConnection connection;
54
55 private ObjectName proxyObjectName;
56
57 private NotificationListener spyListener;
58
59 private Map<NotificationListener, NotificationListener> notificationProxyMap =
60 new HashMap<NotificationListener, NotificationListener>();
61
62 /***
63 * Constructs a remote mbean invocation handler.
64 * @param remoteObjectName
65 * @param proxyObjectName
66 * @param connection
67 * @param notificationInterceptor
68 */
69 public RemoteMBeanInvocationHandler(
70 ObjectName remoteObjectName,
71 ObjectName proxyObjectName,
72 MBeanServerConnection connection,
73 NotificationListener notificationInterceptor) {
74 this.remoteObjectName = remoteObjectName;
75 this.proxyObjectName = proxyObjectName;
76 this.connection = connection;
77 this.spyListener = notificationInterceptor;
78 }
79
80 public ObjectName getRemoteObjectName() {
81 return remoteObjectName;
82 }
83
84 /***
85 * Invokes the specified method on the remote mbean. If the method doesn't
86 * match a method on the DynamicMBean or NotificationEmitter, the method is
87 * invoked on the remote invocation handler directly (ie equals and
88 * hashCode);
89 * @param proxy
90 * @param method
91 * @param args
92 * @return Result object.
93 * @throws Throwable
94 */
95 public Object invoke(Object proxy, Method method, Object[] args)
96 throws Throwable {
97
98 if (log.isLoggable(Level.FINER)) {
99 log.finer("method=" + method);
100 }
101 if (method.getName().equals("invoke")) {
102 return this.connection.invoke(
103 this.remoteObjectName,
104 (String) args[0],
105 (Object[]) args[1],
106 (String[]) args[2]);
107 } else if (method.getName().equals("getMBeanInfo")) {
108 return this.connection.getMBeanInfo(this.remoteObjectName);
109 } else if (method.getName().equals("getAttributes")) {
110 return this.connection.getAttributes(
111 this.remoteObjectName,
112 (String[]) args[0]);
113 } else if (method.getName().equals("getAttribute")) {
114 return this.connection.getAttribute(
115 this.remoteObjectName,
116 (String) args[0]);
117 } else if (method.getName().equals("setAttributes")) {
118 return this.connection.setAttributes(
119 this.remoteObjectName,
120 (AttributeList) args[0]);
121 } else if (method.getName().equals("setAttribute")) {
122 this.connection.setAttribute(
123 this.remoteObjectName,
124 (Attribute) args[0]);
125 return null;
126 } else if (method.getName().equals("addNotificationListener")) {
127
128
129 final NotificationListener clientListener =
130 (NotificationListener) args[0];
131
132
133
134 NotificationListener interceptingListener =
135 new NotificationListener() {
136 public void handleNotification(
137 javax.management.Notification notification,
138 Object handback) {
139 notification.setSource(getProxyObjectName());
140
141 spyListener.handleNotification(notification, handback);
142
143
144 clientListener.handleNotification(notification, handback);
145 };
146 };
147
148 this.notificationProxyMap.put(clientListener, interceptingListener);
149
150
151
152
153 NotificationFilter interceptingFilter = null;
154
155 if (args[1] != null) {
156 final NotificationFilter clientFilter =
157 (NotificationFilter) args[1];
158 interceptingFilter =
159 new NotificationFilter() {
160 public boolean isNotificationEnabled(
161 Notification notification) {
162 Notification n = new Notification(notification
163 .getType(), proxyObjectName, notification
164 .getSequenceNumber(), notification
165 .getTimeStamp(), notification.getMessage());
166
167 n.setUserData(notification.getUserData());
168 return clientFilter.isNotificationEnabled(n);
169 }
170 };
171 }
172
173 this.connection.addNotificationListener(
174 this.remoteObjectName,
175 interceptingListener,
176 interceptingFilter,
177 (Object) args[2]);
178 return null;
179
180 } else if (method.getName().equals("removeNotificationListener")) {
181 final NotificationListener clientListener =
182 (NotificationListener) args[0];
183 this.notificationProxyMap.remove(clientListener);
184 this.connection.removeNotificationListener(
185 this.remoteObjectName,
186 clientListener);
187 } else if (method.getName().equals("getNotificationInfo()")) {
188 return this.connection
189 .getMBeanInfo(this.remoteObjectName)
190 .getNotifications();
191 }
192
193 Method m = this.getClass().getMethod(
194 method.getName(),
195 method.getParameterTypes());
196 return m.invoke(this, args);
197 }
198
199 public ObjectName getProxyObjectName() {
200 return proxyObjectName;
201 }
202 }