KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jmx > mbeanserver > MBeanSupport


1 /*
2  * @(#)MBeanSupport.java 1.6 05/11/17
3  *
4  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.jmx.mbeanserver;
9
10 import static com.sun.jmx.mbeanserver.Util.*;
11 import java.lang.annotation.Annotation JavaDoc;
12 import java.lang.ref.WeakReference JavaDoc;
13 import java.lang.reflect.Constructor JavaDoc;
14 import java.lang.reflect.GenericArrayType JavaDoc;
15 import java.lang.reflect.InvocationTargetException JavaDoc;
16 import java.lang.reflect.Method JavaDoc;
17 import java.lang.reflect.Type JavaDoc;
18 import java.util.Arrays JavaDoc;
19 import java.util.Collections JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.Map JavaDoc;
23 import java.util.Set JavaDoc;
24 import java.util.WeakHashMap JavaDoc;
25 import javax.management.Attribute JavaDoc;
26 import javax.management.AttributeList JavaDoc;
27 import javax.management.AttributeNotFoundException JavaDoc;
28 import javax.management.Descriptor JavaDoc;
29 import javax.management.DynamicMBean JavaDoc;
30 import javax.management.ImmutableDescriptor JavaDoc;
31 import javax.management.InstanceAlreadyExistsException JavaDoc;
32 import javax.management.InvalidAttributeValueException JavaDoc;
33 import javax.management.JMX JavaDoc;
34 import javax.management.MBeanAttributeInfo JavaDoc;
35 import javax.management.MBeanConstructorInfo JavaDoc;
36 import javax.management.MBeanException JavaDoc;
37 import javax.management.MBeanInfo JavaDoc;
38 import javax.management.MBeanNotificationInfo JavaDoc;
39 import javax.management.MBeanOperationInfo JavaDoc;
40 import javax.management.MBeanParameterInfo JavaDoc;
41 import javax.management.MBeanRegistration JavaDoc;
42 import javax.management.MBeanServer JavaDoc;
43 import javax.management.NotCompliantMBeanException JavaDoc;
44 import javax.management.NotificationBroadcaster JavaDoc;
45 import javax.management.ObjectName JavaDoc;
46 import javax.management.ReflectionException JavaDoc;
47 import javax.management.openmbean.OpenMBeanAttributeInfoSupport JavaDoc;
48 import javax.management.openmbean.OpenMBeanOperationInfoSupport JavaDoc;
49 import javax.management.openmbean.OpenMBeanParameterInfo JavaDoc;
50 import javax.management.openmbean.OpenMBeanParameterInfoSupport JavaDoc;
51 import javax.management.openmbean.OpenType JavaDoc;
52
53 /**
54  * Base class for MBeans. There is one instance of this class for
55  * every Standard MBean and every MXBean. We try to limit the amount
56  * of information per instance so we can handle very large numbers of
57  * MBeans confortably.
58  *
59  * @param <M> either Method or ConvertingMethod, for Standard MBeans
60  * and MXBeans respectively.
61  *
62  * @since 1.6
63  */

64 /*
65  * We maintain a couple of caches to increase sharing between
66  * different MBeans of the same type and also to reduce creation time
67  * for the second and subsequent instances of the same type.
68  *
69  * The first cache maps from an MBean interface to a PerInterface
70  * object containing information parsed out of the interface. The
71  * interface is either a Standard MBean interface or an MXBean
72  * interface, and there is one cache for each case.
73  *
74  * The PerInterface includes an MBeanInfo. This contains the
75  * attributes and operations parsed out of the interface's methods,
76  * plus a basic Descriptor for the interface containing at least the
77  * interfaceClassName field and any fields derived from annotations on
78  * the interface. This MBeanInfo can never be the MBeanInfo for any
79  * actual MBean, because an MBeanInfo's getClassName() is the name of
80  * a concrete class and we don't know what the class will be.
81  * Furthermore a real MBeanInfo may need to add constructors and/or
82  * notifications to the MBeanInfo.
83  *
84  * The PerInterface also contains an MBeanDispatcher which is able to
85  * route getAttribute, setAttribute, and invoke to the appropriate
86  * method of the interface, including doing any necessary translation
87  * of parameters and return values for MXBeans.
88  *
89  * The PerInterface also contains the original Class for the interface.
90  *
91  * We need to be careful about references. When there are no MBeans
92  * with a given interface, there must not be any strong references to
93  * the interface Class. Otherwise it could never be garbage collected,
94  * and neither could its ClassLoader or any other classes loaded by
95  * its ClassLoader. Therefore the cache must wrap the PerInterface
96  * in a WeakReference. Each instance of MBeanSupport has a strong
97  * reference to its PerInterface, which prevents PerInterface instances
98  * from being garbage-collected prematurely.
99  *
100  * The second cache maps from a concrete class and an MBean interface
101  * that that class implements to the MBeanInfo for that class and
102  * interface. (The ability to specify an interface separately comes
103  * from the class StandardMBean. MBeans registered directly in the
104  * MBean Server will always have the same interface here.)
105  *
106  * The MBeanInfo in this second cache will be the MBeanInfo from the
107  * PerInterface cache for the given itnerface, but with the
108  * getClassName() having the concrete class's name, and the public
109  * constructors based on the concrete class's constructors. This
110  * MBeanInfo can be shared between all instances of the concrete class
111  * specifying the same interface, except instances that are
112  * NotificationBroadcasters. NotificationBroadcasters supply the
113  * MBeanNotificationInfo[] in the MBeanInfo based on the instance
114  * method NotificationBroadcaster.getNotificationInfo(), so two
115  * instances of the same concrete class do not necessarily have the
116  * same MBeanNotificationInfo[]. Currently we do not try to detect
117  * when they do, although it would probably be worthwhile doing that
118  * since it is a very common case.
119  *
120  * Standard MBeans additionally have the property that
121  * getNotificationInfo() must in principle be called every time
122  * getMBeanInfo() is called for the MBean, since the returned array is
123  * allowed to change over time. We attempt to reduce the cost of
124  * doing this by detecting when the Standard MBean is a subclass of
125  * NotificationBroadcasterSupport that does not override
126  * getNotificationInfo(), meaning that the MBeanNotificationInfo[] is
127  * the one that was supplied to the constructor. MXBeans do not have
128  * this problem because their getNotificationInfo() method is called
129  * only once.
130  *
131  */

132 public abstract class MBeanSupport<M>
133         implements DynamicMBean2, MBeanRegistration JavaDoc {
134
135     <T> MBeanSupport(T resource, Class JavaDoc<T> mbeanInterface)
136             throws NotCompliantMBeanException JavaDoc {
137     if (mbeanInterface == null)
138         throw new NotCompliantMBeanException JavaDoc("Null MBean interface");
139     if (!mbeanInterface.isInstance(resource)) {
140         final String JavaDoc msg =
141         "Resource class " + resource.getClass().getName() +
142         " is not an instance of " + mbeanInterface.getName();
143         throw new NotCompliantMBeanException JavaDoc(msg);
144     }
145     this.resource = resource;
146         MBeanIntrospector introspector = getMBeanIntrospector();
147         this.perInterface = introspector.getPerInterface(mbeanInterface);
148     this.mbeanInfo = introspector.getMBeanInfo(resource, perInterface);
149     }
150
151     /** Return the appropriate introspector for this type of MBean. */
152     abstract MBeanIntrospector<M> getMBeanIntrospector();
153     
154     /**
155      * Return a cookie for this MBean. This cookie will be passed to
156      * MBean method invocations where it can supply additional information
157      * to the invocation. For example, with MXBeans it can be used to
158      * supply the MXBeanLookup context for resolving inter-MXBean references.
159      */

160     abstract Object JavaDoc getCookie();
161
162     public final boolean isMXBean() {
163     return perInterface.isMXBean();
164     }
165
166     // Methods that javax.management.StandardMBean should call from its
167
// preRegister and postRegister, given that it is not supposed to
168
// call the contained object's preRegister etc methods even if it has them
169
public abstract void register(MBeanServer JavaDoc mbs, ObjectName JavaDoc name)
170             throws Exception JavaDoc;
171     public abstract void unregister();
172
173     public final ObjectName JavaDoc preRegister(MBeanServer JavaDoc server, ObjectName JavaDoc name)
174             throws Exception JavaDoc {
175         if (resource instanceof MBeanRegistration JavaDoc)
176             return ((MBeanRegistration JavaDoc) resource).preRegister(server, name);
177         else
178             return name;
179     }
180     
181     public final void preRegister2(MBeanServer JavaDoc server, ObjectName JavaDoc name)
182             throws Exception JavaDoc {
183         register(server, name);
184     }
185     
186     public final void registerFailed() {
187         unregister();
188     }
189
190     public final void postRegister(Boolean JavaDoc registrationDone) {
191         if (resource instanceof MBeanRegistration JavaDoc)
192             ((MBeanRegistration JavaDoc) resource).postRegister(registrationDone);
193     }
194     
195     public final void preDeregister() throws Exception JavaDoc {
196         if (resource instanceof MBeanRegistration JavaDoc)
197             ((MBeanRegistration JavaDoc) resource).preDeregister();
198     }
199
200     public final void postDeregister() {
201         // Undo any work from registration. We do this in postDeregister
202
// not preDeregister, because if the user preDeregister throws an
203
// exception then the MBean is not unregistered.
204
try {
205             unregister();
206         } finally {
207             if (resource instanceof MBeanRegistration JavaDoc)
208                 ((MBeanRegistration JavaDoc) resource).postDeregister();
209         }
210     }
211
212     public final Object JavaDoc getAttribute(String JavaDoc attribute)
213         throws AttributeNotFoundException JavaDoc,
214            MBeanException JavaDoc,
215            ReflectionException JavaDoc {
216     return perInterface.getAttribute(resource, attribute, getCookie());
217     }
218
219     public final AttributeList JavaDoc getAttributes(String JavaDoc[] attributes) {
220     final AttributeList JavaDoc result = new AttributeList JavaDoc(attributes.length);
221     for (String JavaDoc attrName : attributes) {
222         try {
223         final Object JavaDoc attrValue = getAttribute(attrName);
224         result.add(new Attribute JavaDoc(attrName, attrValue));
225         } catch (Exception JavaDoc e) {
226         // OK: attribute is not included in returned list, per spec
227
// XXX: log the exception
228
}
229     }
230     return result;
231     }
232
233     public final void setAttribute(Attribute JavaDoc attribute)
234         throws AttributeNotFoundException JavaDoc,
235            InvalidAttributeValueException JavaDoc,
236            MBeanException JavaDoc,
237            ReflectionException JavaDoc {
238     final String JavaDoc name = attribute.getName();
239     final Object JavaDoc value = attribute.getValue();
240     perInterface.setAttribute(resource, name, value, getCookie());
241     }
242
243     public final AttributeList JavaDoc setAttributes(AttributeList JavaDoc attributes) {
244     final AttributeList JavaDoc result = new AttributeList JavaDoc(attributes.size());
245     for (Object JavaDoc attrObj : attributes) {
246         // We can't use AttributeList.asList because it has side-effects
247
Attribute JavaDoc attr = (Attribute JavaDoc) attrObj;
248         try {
249         setAttribute(attr);
250         result.add(new Attribute JavaDoc(attr.getName(), attr.getValue()));
251         } catch (Exception JavaDoc e) {
252         // OK: attribute is not included in returned list, per spec
253
// XXX: log the exception
254
}
255     }
256     return result;
257     }
258
259     public final Object JavaDoc invoke(String JavaDoc operation, Object JavaDoc[] params,
260              String JavaDoc[] signature)
261         throws MBeanException JavaDoc, ReflectionException JavaDoc {
262     return perInterface.invoke(resource, operation, params, signature,
263                    getCookie());
264     }
265
266     // Overridden by StandardMBeanSupport
267
public MBeanInfo JavaDoc getMBeanInfo() {
268     return mbeanInfo;
269     }
270     
271     public final String JavaDoc getClassName() {
272         return resource.getClass().getName();
273     }
274
275     public final Object JavaDoc getResource() {
276     return resource;
277     }
278     
279     public final Class JavaDoc<?> getMBeanInterface() {
280         return perInterface.getMBeanInterface();
281     }
282
283     private final MBeanInfo JavaDoc mbeanInfo;
284     private final Object JavaDoc resource;
285     private final PerInterface<M> perInterface;
286 }
287
Popular Tags