KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > mx > remoting > JMXSubsystemInvocationHandler


1 /***************************************
2  * *
3  * JBoss: The OpenSource J2EE WebOS *
4  * *
5  * Distributable under LGPL license. *
6  * See terms of license at gnu.org. *
7  * *
8  ***************************************/

9 package org.jboss.mx.remoting;
10
11 import java.lang.reflect.InvocationTargetException JavaDoc;
12 import java.lang.reflect.Method JavaDoc;
13 import java.lang.reflect.UndeclaredThrowableException JavaDoc;
14 import java.util.Map JavaDoc;
15 import javax.management.Attribute JavaDoc;
16 import javax.management.AttributeList JavaDoc;
17 import javax.management.MBeanException JavaDoc;
18 import javax.management.MBeanServer JavaDoc;
19 import javax.management.NotificationFilter JavaDoc;
20 import javax.management.ObjectName JavaDoc;
21 import org.jboss.logging.Logger;
22 import org.jboss.remoting.InvocationRequest;
23 import org.jboss.remoting.callback.InvokerCallbackHandler;
24 import org.jboss.remoting.InvokerLocator;
25 import org.jboss.remoting.ServerInvocationHandler;
26 import org.jboss.remoting.ServerInvoker;
27 import org.jboss.remoting.ident.Identity;
28 import org.jboss.remoting.invocation.NameBasedInvocation;
29
30 /**
31  * JMXSubsystemInvocationHandler is a ServerInvocationHandler that will forward requests to the
32  * MBeanServer and return the results from the MBeanServer.
33  *
34  * @author <a HREF="mailto:jhaynie@vocalocity.net">Jeff Haynie</a>
35  * @version $Revision: 33894 $
36  */

37 public class JMXSubsystemInvocationHandler implements ServerInvocationHandler
38 {
39    private static final Logger log = Logger.getLogger(JMXSubsystemInvocationHandler.class);
40    private MBeanServer JavaDoc server;
41    private MBeanNotificationCache notificationCache;
42    private ServerInvoker invoker;
43    private Identity identity;
44
45    private static Method JavaDoc getObjectInstance;
46    private static Method JavaDoc isRegistered;
47    private static Method JavaDoc getAttribute;
48    private static Method JavaDoc getAttributes;
49    private static Method JavaDoc setAttribute;
50    private static Method JavaDoc setAttributes;
51    private static Method JavaDoc invoke;
52    private static Method JavaDoc getMBeanInfo;
53
54    static
55    {
56       try
57       {
58          Class JavaDoc LObject = (new Object JavaDoc[0]).getClass();
59          Class JavaDoc LString = (new String JavaDoc[0]).getClass();
60
61          Class JavaDoc[] Sig_ObjectName =
62                new Class JavaDoc[]{ObjectName JavaDoc.class};
63          Class JavaDoc[] Sig_ObjectName_String =
64                new Class JavaDoc[]{ObjectName JavaDoc.class, String JavaDoc.class};
65          Class JavaDoc[] Sig_ObjectName_LString =
66                new Class JavaDoc[]{ObjectName JavaDoc.class, LString};
67          Class JavaDoc[] Sig_ObjectName_Attribute =
68                new Class JavaDoc[]{ObjectName JavaDoc.class, Attribute JavaDoc.class};
69          Class JavaDoc[] Sig_ObjectName_AttributeList =
70                new Class JavaDoc[]{ObjectName JavaDoc.class, AttributeList JavaDoc.class};
71          Class JavaDoc[] Sig_ObjectName_String_LObject_LString =
72                new Class JavaDoc[]{ObjectName JavaDoc.class, String JavaDoc.class, LObject, LString};
73
74          getObjectInstance = MBeanServer JavaDoc.class.getMethod("getObjectInstance", Sig_ObjectName);
75          isRegistered = MBeanServer JavaDoc.class.getMethod("isRegistered", Sig_ObjectName);
76          getAttribute = MBeanServer JavaDoc.class.getMethod("getAttribute", Sig_ObjectName_String);
77          getAttributes = MBeanServer JavaDoc.class.getMethod("getAttributes", Sig_ObjectName_LString);
78          setAttribute = MBeanServer JavaDoc.class.getMethod("setAttribute", Sig_ObjectName_Attribute);
79          setAttributes = MBeanServer JavaDoc.class.getMethod("setAttributes", Sig_ObjectName_AttributeList);
80          invoke = MBeanServer JavaDoc.class.getMethod("invoke", Sig_ObjectName_String_LObject_LString);
81          getMBeanInfo = MBeanServer JavaDoc.class.getMethod("getMBeanInfo", Sig_ObjectName);
82       }
83       catch(Exception JavaDoc e)
84       {
85          throw new RuntimeException JavaDoc("Error resolving methods", e);
86       }
87    }
88
89    public JMXSubsystemInvocationHandler()
90    {
91       super();
92    }
93
94    /**
95     * set the invoker that owns this handler
96     *
97     * @param invoker
98     */

99    public void setInvoker(ServerInvoker invoker)
100    {
101       this.invoker = invoker;
102    }
103
104    /**
105     * set the mbean server that the handler can reference
106     *
107     * @param server
108     */

109    public void setMBeanServer(MBeanServer JavaDoc server)
110    {
111       this.server = server;
112       identity = Identity.get(server);
113       // make sure our local server is set
114
MBeanTransportPreference.setLocalServer(server, identity);
115       if(log.isTraceEnabled())
116       {
117          log.trace("setMBeanServer called with: " + server + " with identity: " + identity);
118       }
119    }
120
121    /**
122     * method is called to destroy the handler and remove all pending notifications and listeners
123     * from the notification cache
124     */

125    public synchronized void destroy()
126    {
127       if(notificationCache != null)
128       {
129          notificationCache.destroy();
130          notificationCache = null;
131       }
132    }
133
134    protected void finalize() throws Throwable JavaDoc
135    {
136       destroy();
137       super.finalize();
138    }
139
140    /**
141     * pull any pending notifications from the queue and place in the return payload
142     *
143     * @param sessionId
144     * @param payload
145     */

146    private void storeNotifications(String JavaDoc sessionId, Map JavaDoc payload)
147    {
148       NotificationQueue q = (notificationCache == null) ? null : notificationCache.getNotifications(sessionId);
149       if(q != null)
150       {
151          payload.put("notifications", q);
152       }
153    }
154
155    public Object JavaDoc invoke(InvocationRequest invocation)
156          throws Throwable JavaDoc
157    {
158       if(this.server == null)
159       {
160          throw new IllegalStateException JavaDoc("invoke called prior to mbean server being set");
161       }
162       try
163       {
164          NameBasedInvocation nbi = (NameBasedInvocation) invocation.getParameter();
165          String JavaDoc methodName = nbi.getMethodName();
166          Object JavaDoc args [] = nbi.getParameters();
167          String JavaDoc signature [] = nbi.getSignature();
168          String JavaDoc sessionId = invocation.getSessionId();
169
170          // this method is called by a polling client for notifications
171
if(methodName.equals("$GetNotifications$")) //FIXME- JGH: make this a little better
172
{
173             // if (notificationCache!=null && notificationCache.isConnectedBidirectionally(invocation.getClientLocator()))
174
// {
175
// return new Boolean(false);
176
// }
177
// just return, since the finally will automatically stick the queue in the
178
// return payload for us.
179
return new Boolean JavaDoc(true);
180          }
181          if(methodName.equals("$NOTIFICATIONS$")) //FIXME- JGH: make this a little better
182
{
183             // we are receiving async notifications from a remote server
184
NotificationQueue queue = (NotificationQueue) args[0];
185             MBeanServerClientInvokerProxy p = MBeanServerClientInvokerProxy.get(queue.getSessionID());
186             if(p != null)
187             {
188                if(log.isTraceEnabled())
189                {
190                   log.trace("received remote notifications for JMX id: " + queue.getSessionID() + ", queue: " + queue);
191                }
192                p.deliverNotifications(queue, true);
193             }
194             else
195             {
196                log.warn("couldn't find a client invoker proxy for mbean serverid: " + queue.getSessionID() + ", dropping notifications [" + queue + "]");
197             }
198             return null;
199          }
200          // add and remove are special cases, handle those accordingly
201
if(methodName.equals("addNotificationListener") && signature.length == 4)
202          {
203             // listener field is always null, since we don't send it across
204
handleAddNotificationListener(invocation.getLocator(), sessionId, (ObjectName JavaDoc) args[0], (NotificationFilter JavaDoc) args[2], args[3]);
205             return null;
206          }
207          else if(methodName.equals("removeNotificationListener") && signature.length == 3)
208          {
209             // listener field is always null, since we don't send it across
210
handleRemoveNotificationListener(invocation.getLocator(), sessionId, (ObjectName JavaDoc) args[0], args[2]);
211             return null;
212          }
213          Object JavaDoc _args[] = (args == null && signature != null) ? new Object JavaDoc[signature.length] : args;
214          // get the mbean server method that's being invoked
215
Method JavaDoc method = getMethod(methodName, signature);
216          // transport against the mbean server
217
return method.invoke(server, _args);
218       }
219       catch(Throwable JavaDoc ex)
220       {
221          if(ex instanceof UndeclaredThrowableException JavaDoc)
222          {
223             UndeclaredThrowableException JavaDoc ut = (UndeclaredThrowableException JavaDoc) ex;
224             Throwable JavaDoc ute = ut.getUndeclaredThrowable();
225             if(ute instanceof Exception JavaDoc)
226             {
227                throw new MBeanException JavaDoc((Exception JavaDoc) ute, ut.getUndeclaredThrowable().getMessage());
228             }
229             else
230             {
231                throw new MBeanException JavaDoc(new Exception JavaDoc(ute.getMessage()), ute.getMessage());
232             }
233          }
234          if(ex instanceof InvocationTargetException JavaDoc)
235          {
236             throw ((InvocationTargetException JavaDoc) ex).getTargetException();
237          }
238          throw ex;
239       }
240       finally
241       {
242          // on each invocation, we go ahead and deliver back
243
// and pending notifications for this session to the remote
244
// end
245
if(notificationCache != null)
246          {
247             storeNotifications(invocation.getSessionId(), invocation.getReturnPayload());
248          }
249       }
250    }
251
252    private synchronized void handleAddNotificationListener(InvokerLocator locator, String JavaDoc sessionId, ObjectName JavaDoc objName, NotificationFilter JavaDoc filter, Object JavaDoc handback)
253          throws Throwable JavaDoc
254    {
255       if(notificationCache == null)
256       {
257          notificationCache = new MBeanNotificationCache(invoker, server);
258       }
259       notificationCache.addNotificationListener(locator, sessionId, objName, filter, handback);
260    }
261
262    private synchronized void handleRemoveNotificationListener(InvokerLocator locator, String JavaDoc sessionId, ObjectName JavaDoc objName, Object JavaDoc key)
263          throws Throwable JavaDoc
264    {
265       if(notificationCache == null)
266       {
267          return;
268       }
269       notificationCache.removeNotificationListener(locator, sessionId, objName, key);
270    }
271
272    /**
273     * convenience method to lookup the Method object for a given method and signature
274     *
275     * @param methodName
276     * @param sig
277     * @return
278     * @throws java.lang.Throwable
279     */

280    private Method JavaDoc getMethod(String JavaDoc methodName, String JavaDoc sig[])
281          throws Throwable JavaDoc
282    {
283       if(methodName.equals("invoke"))
284       {
285          return invoke;
286       }
287       else if(methodName.equals("getAttribute"))
288       {
289          return getAttribute;
290       }
291       else if(methodName.equals("setAttribute"))
292       {
293          return setAttribute;
294       }
295       else if(methodName.equals("getAttributes"))
296       {
297          return getAttributes;
298       }
299       else if(methodName.equals("setAttributes"))
300       {
301          return setAttributes;
302       }
303       else if(methodName.equals("setAttributes"))
304       {
305          return setAttributes;
306       }
307       else if(methodName.equals("getMBeanInfo"))
308       {
309          return getMBeanInfo;
310       }
311       else if(methodName.equals("getObjectInstance"))
312       {
313          return getObjectInstance;
314       }
315       else if(methodName.equals("isRegistered"))
316       {
317          return isRegistered;
318       }
319
320       Class JavaDoc[] params = null;
321       if(sig != null)
322       {
323          params = new Class JavaDoc[sig.length];
324          for(int i = 0; i < sig.length; ++i)
325          {
326             params[i] = Class.forName(sig[i]);
327          }
328       }
329       return MBeanServer JavaDoc.class.getMethod(methodName, params);
330    }
331
332    //NOTE: These were added as part of the new remoting callback,
333
// but not yet implemented (need to compile). JMX remoting should
334
// still work using the old way. -TME
335
public void addListener(InvokerCallbackHandler callbackHandler)
336    {
337       //TODO: Need to implement -TME
338
}
339
340    public void removeListener(InvokerCallbackHandler callbackHandler)
341    {
342       //TODO: Need to implement -TME
343
}
344 }
345
Popular Tags