KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > mx > util > MBeanProxyExt


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.mx.util;
23
24 import java.io.Externalizable JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.ObjectInput JavaDoc;
27 import java.io.ObjectOutput JavaDoc;
28 import java.lang.reflect.InvocationHandler JavaDoc;
29 import java.lang.reflect.Method JavaDoc;
30 import java.lang.reflect.Proxy JavaDoc;
31 import java.security.AccessController JavaDoc;
32 import java.security.PrivilegedAction JavaDoc;
33 import java.util.HashMap JavaDoc;
34
35 import javax.management.Attribute JavaDoc;
36 import javax.management.MBeanAttributeInfo JavaDoc;
37 import javax.management.MBeanInfo JavaDoc;
38 import javax.management.MBeanServer JavaDoc;
39 import javax.management.MBeanServerConnection JavaDoc;
40 import javax.management.MalformedObjectNameException JavaDoc;
41 import javax.management.ObjectName JavaDoc;
42
43 /**
44  * A factory for producing MBean proxies.
45  *
46  * <p>Created proxies will also implement {@link org.jboss.mx.util.MBeanProxyInstance}
47  * allowing access to the proxies configuration.
48  * @author <a HREF="mailto:rickard.oberg@telkel.com">Rickard Oberg</a>.
49  * @author <a HREF="mailto:jason@planet57.com">Jason Dillon</a>.
50  * @author <a HREF="mailto:adrian.brock@happeningtimes.com">Adrian Brock</a>.
51  * @author <a HREF="mailto:dimitris@jboss.org">Dimitris Andreadis</a>.
52  * @version <tt>$Revision: 42126 $</tt>
53  */

54 public class MBeanProxyExt
55    implements InvocationHandler JavaDoc, MBeanProxyInstance, Externalizable JavaDoc
56 {
57    /** The serialVersionUID */
58    private static final long serialVersionUID = -2942844863242742655L;
59
60    /**
61     * The remote MBeanServerConnection
62     */

63    public static MBeanServerConnection JavaDoc remote;
64    
65    /**
66     * The server to proxy invoke calls to.
67     */

68    private MBeanServerConnection JavaDoc server;
69
70    /**
71     * The name of the object to invoke.
72     */

73    private ObjectName JavaDoc name;
74
75    /**
76     * The MBean's attributes
77     */

78    private transient final HashMap JavaDoc attributeMap = new HashMap JavaDoc();
79    /**
80     * Have the attributes been retrieved
81     */

82    private transient boolean inited = false;
83
84    /**
85     * For externalizable
86     */

87    public MBeanProxyExt()
88    {
89    }
90    
91    /**
92     * Construct an MBeanProxy.
93     */

94    MBeanProxyExt(final ObjectName JavaDoc name, final MBeanServer JavaDoc server, boolean lazyInit)
95    {
96       this.name = name;
97       this.server = server;
98       if (lazyInit == false)
99          init();
100    }
101
102    /**
103     * Used when args is null.
104     */

105    private static final Object JavaDoc EMPTY_ARGS[] = {};
106
107    /**
108     * Invoke the configured MBean via the target MBeanServer and decode any
109     * resulting JMX exceptions that are thrown.
110     */

111    public Object JavaDoc invoke(final Object JavaDoc proxy,
112       final Method JavaDoc method,
113       final Object JavaDoc[] args)
114       throws Throwable JavaDoc
115    {
116       // if the method belongs to ProxyInstance, then invoke locally
117
Class JavaDoc type = method.getDeclaringClass();
118       if (type == MBeanProxyInstance.class || type == Object JavaDoc.class)
119       {
120          return method.invoke(this, args);
121       }
122
123       String JavaDoc methodName = method.getName();
124
125       // Get attribute
126
if (methodName.startsWith("get") && args == null)
127       {
128          if (inited == false)
129             init();
130
131          String JavaDoc attrName = methodName.substring(3);
132          MBeanAttributeInfo JavaDoc info = (MBeanAttributeInfo JavaDoc) attributeMap.get(attrName);
133          if (info != null)
134          {
135             String JavaDoc retType = method.getReturnType().getName();
136             if (retType.equals(info.getType()))
137             {
138                try
139                {
140                   return server.getAttribute(name, attrName);
141                }
142                catch (Exception JavaDoc e)
143                {
144                   throw JMXExceptionDecoder.decode(e);
145                }
146             }
147          }
148       }
149
150       // Is attribute
151
else if (methodName.startsWith("is") && args == null)
152       {
153          if (inited == false)
154             init();
155
156          String JavaDoc attrName = methodName.substring(2);
157          MBeanAttributeInfo JavaDoc info = (MBeanAttributeInfo JavaDoc) attributeMap.get(attrName);
158          if (info != null && info.isIs())
159          {
160             Class JavaDoc retType = method.getReturnType();
161             if (retType.equals(Boolean JavaDoc.class) || retType.equals(Boolean.TYPE))
162             {
163                try
164                {
165                   return server.getAttribute(name, attrName);
166                }
167                catch (Exception JavaDoc e)
168                {
169                   throw JMXExceptionDecoder.decode(e);
170                }
171             }
172          }
173       }
174
175       // Set attribute
176
else if (methodName.startsWith("set") && args != null && args.length == 1)
177       {
178          if (inited == false)
179             init();
180
181          String JavaDoc attrName = methodName.substring(3);
182          MBeanAttributeInfo JavaDoc info = (MBeanAttributeInfo JavaDoc) attributeMap.get(attrName);
183          if (info != null && method.getReturnType() == Void.TYPE)
184          {
185             try
186             {
187                server.setAttribute(name, new Attribute JavaDoc(attrName, args[0]));
188                return null;
189             }
190             catch (Exception JavaDoc e)
191             {
192                throw JMXExceptionDecoder.decode(e);
193             }
194          }
195       }
196
197       // Operation
198

199       // convert the parameter types to strings for JMX
200
Class JavaDoc[] types = method.getParameterTypes();
201       String JavaDoc[] sig = new String JavaDoc[types.length];
202       for (int i = 0; i < types.length; i++)
203       {
204          sig[i] = types[i].getName();
205       }
206
207       // invoke the server and decode JMX exceptions
208
try
209       {
210          return server.invoke(name, methodName, args == null ? EMPTY_ARGS : args, sig);
211       }
212       catch (Exception JavaDoc e)
213       {
214          throw JMXExceptionDecoder.decode(e);
215       }
216    }
217
218
219    ///////////////////////////////////////////////////////////////////////////
220
// MBeanProxyInstance //
221
///////////////////////////////////////////////////////////////////////////
222

223    public final ObjectName JavaDoc getMBeanProxyObjectName()
224    {
225       return name;
226    }
227
228    public final MBeanServer JavaDoc getMBeanProxyMBeanServer()
229    {
230       if (server instanceof MBeanServer JavaDoc == false)
231          throw new IllegalStateException JavaDoc("This operation is not available for an MBeanServerConnection");
232       return (MBeanServer JavaDoc) server;
233    }
234
235    public final MBeanServerConnection JavaDoc getMBeanProxyMBeanServerConnection()
236    {
237       return server;
238    }
239
240    ///////////////////////////////////////////////////////////////////////////
241
// Object Overrides //
242
///////////////////////////////////////////////////////////////////////////
243

244    /**
245     * We need to override this because by default equals returns false when
246     * called on the proxy object and then relayed here.
247     */

248    public boolean equals(Object JavaDoc that)
249    {
250       if (that == null) return false;
251       if (that == this) return true;
252       
253       // check if 'that' is an MBeanProxyExt or a Proxy instance
254
// that implements the MBeanProxyInstance interface
255
if (that instanceof MBeanProxyInstance)
256       {
257          MBeanProxyInstance proxy = (MBeanProxyInstance) that;
258          
259          // assume equality if both the MBeanServer and ObjectName match
260
if (name.equals(proxy.getMBeanProxyObjectName()) &&
261             server.equals(proxy.getMBeanProxyMBeanServer()))
262          {
263             return true;
264          }
265       }
266       return false;
267    }
268
269    /**
270     * As with equals, use the MBeanServer + ObjectName to calculate the
271     * hashCode
272     */

273    public int hashCode()
274    {
275       return name.hashCode() * 31 + server.hashCode();
276    }
277
278    /**
279     * avoid the default printout, e.g. org.jboss.mx.util.MBeanProxyExt@120540c
280     */

281    public String JavaDoc toString()
282    {
283       StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc(128);
284
285       sbuf.append("MBeanProxyExt[").append(name.toString()).append(']');
286
287       return sbuf.toString();
288    }
289
290    ///////////////////////////////////////////////////////////////////////////
291
// Factory Methods //
292
///////////////////////////////////////////////////////////////////////////
293

294    /**
295     * Create an MBean proxy.
296     * @param intf The interface which the proxy will implement.
297     * @param name A string used to construct the ObjectName of the MBean to
298     * proxy to.
299     * @return A MBean proxy.
300     * @throws javax.management.MalformedObjectNameException Invalid object
301     * name.
302     */

303    public static Object JavaDoc create(final Class JavaDoc intf, final String JavaDoc name)
304       throws MalformedObjectNameException JavaDoc
305    {
306       return create(intf, new ObjectName JavaDoc(name));
307    }
308
309    /**
310     * Create an MBean proxy.
311     * @param intf The interface which the proxy will implement.
312     * @param name A string used to construct the ObjectName of the MBean to
313     * proxy to.
314     * @param server The MBeanServer that contains the MBean to proxy to.
315     * @return A MBean proxy.
316     * @throws javax.management.MalformedObjectNameException Invalid object
317     * name.
318     */

319    public static Object JavaDoc create(final Class JavaDoc intf,
320       final String JavaDoc name,
321       final MBeanServer JavaDoc server)
322       throws MalformedObjectNameException JavaDoc
323    {
324       return create(intf, new ObjectName JavaDoc(name), server);
325    }
326
327    /**
328     * Create an MBean proxy.
329     * @param intf The interface which the proxy will implement.
330     * @param name The name of the MBean to proxy invocations to.
331     * @return A MBean proxy.
332     */

333    public static Object JavaDoc create(final Class JavaDoc intf, final ObjectName JavaDoc name)
334    {
335       return create(intf, name, MBeanServerLocator.locateJBoss());
336    }
337
338    /**
339     * Create an MBean proxy.
340     * @param intf The interface which the proxy will implement.
341     * @param name The name of the MBean to proxy invocations to.
342     * @param server The MBeanServer that contains the MBean to proxy to.
343     * @return A MBean proxy.
344     */

345    public static Object JavaDoc create(final Class JavaDoc intf,
346       final ObjectName JavaDoc name,
347       final MBeanServer JavaDoc server)
348    {
349       return create(intf, name, server, false);
350    }
351
352    /**
353     * Create an MBean proxy.
354     * @param intf The interface which the proxy will implement.
355     * @param name The name of the MBean to proxy invocations to.
356     * @param server The MBeanServer that contains the MBean to proxy to.
357     * @param lazyInit - a flag indicating if the mbean attribute info should
358     * be retrieved when the proxy is created.
359     * @return A MBean proxy.
360     */

361    public static Object JavaDoc create(final Class JavaDoc intf, final ObjectName JavaDoc name,
362       final MBeanServer JavaDoc server, boolean lazyInit)
363    {
364       // CL which delegates to MBeanProxyInstance's cl for it's class resolution
365
PrivilegedAction JavaDoc action = new PrivilegedAction JavaDoc()
366       {
367          public Object JavaDoc run()
368          {
369             ClassLoader JavaDoc cl = new ClassLoader JavaDoc(intf.getClassLoader())
370             {
371                public Class JavaDoc loadClass(final String JavaDoc className) throws ClassNotFoundException JavaDoc
372                {
373                   try
374                   {
375                      return super.loadClass(className);
376                   }
377                   catch (ClassNotFoundException JavaDoc e)
378                   {
379                      // only allow loading of MBeanProxyInstance from this loader
380
if (className.equals(MBeanProxyInstance.class.getName()))
381                      {
382                         return MBeanProxyInstance.class.getClassLoader().loadClass(className);
383                      }
384                      // was some other classname, throw the CNFE
385
throw e;
386                   }
387                }
388             };
389             return cl;
390          }
391       };
392       ClassLoader JavaDoc cl = (ClassLoader JavaDoc) AccessController.doPrivileged(action);
393       Class JavaDoc[] ifaces = {MBeanProxyInstance.class, intf};
394       InvocationHandler JavaDoc handler = new MBeanProxyExt(name, server, lazyInit);
395       return Proxy.newProxyInstance(cl, ifaces, handler);
396    }
397
398    /**
399     * Retrieve the mbean MBeanAttributeInfo
400     */

401    private synchronized void init()
402    {
403       // The MBean's attributes
404
inited = true;
405       try
406       {
407          MBeanInfo JavaDoc info = server.getMBeanInfo(name);
408          MBeanAttributeInfo JavaDoc[] attributes = info.getAttributes();
409
410          for (int i = 0; i < attributes.length; ++i)
411             attributeMap.put(attributes[i].getName(), attributes[i]);
412       }
413       catch (Exception JavaDoc e)
414       {
415          throw new RuntimeException JavaDoc("Error creating MBeanProxy: " + name, e);
416       }
417    }
418
419    public void readExternal(ObjectInput JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc
420    {
421       name = (ObjectName JavaDoc) in.readObject();
422       server = (MBeanServerConnection JavaDoc) in.readObject();
423    }
424
425
426    public void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc
427    {
428       out.writeObject(name);
429       if (remote != null)
430          out.writeObject(remote);
431       else
432          out.writeObject(server); // This will fail for a normal MBeanServer
433
}
434 }
435
Popular Tags