KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > oddjob > jmx > server > OddjobMBean


1 package org.oddjob.jmx.server;
2
3 import java.rmi.RemoteException JavaDoc;
4 import java.util.Iterator JavaDoc;
5
6 import javax.management.Attribute JavaDoc;
7 import javax.management.AttributeList JavaDoc;
8 import javax.management.DynamicMBean JavaDoc;
9 import javax.management.JMException JavaDoc;
10 import javax.management.MBeanException JavaDoc;
11 import javax.management.MBeanInfo JavaDoc;
12 import javax.management.MBeanNotificationInfo JavaDoc;
13 import javax.management.Notification JavaDoc;
14 import javax.management.NotificationBroadcasterSupport JavaDoc;
15 import javax.management.ObjectName JavaDoc;
16 import javax.management.ReflectionException JavaDoc;
17
18 import org.apache.log4j.Logger;
19 import org.oddjob.jmx.SharedConstants;
20 import org.oddjob.jmx.Utils;
21
22 /**
23  * A MBean which wraps an object providing an Oddjob management interface to the
24  * object.
25  * <p>
26  * Once the bean is created it will sit and wait for clients to interrigate it. When
27  * a client accesses the bean it should call the resync method which will cause the
28  * bean to resend the notifications necessary to recreate in the client, the state
29  * of the bean. During the resync the InterfaceHandlers should block any any more
30  * changes until the resync has completed.
31  *
32  *
33  * @author Rob Gordon.
34  */

35
36 public class OddjobMBean extends NotificationBroadcasterSupport JavaDoc implements
37         DynamicMBean JavaDoc {
38     private static final Logger logger = Logger.getLogger(OddjobMBean.class);
39
40     public static final String JavaDoc RESYNC_PREFIX = "resync.";
41     
42     /** The resync started type */
43     public static final String JavaDoc RESYNC_STARTED_NOTIF_TYPE
44         = RESYNC_PREFIX + "org.oddjob.resyncstarted";
45
46     /** the resync finished type. */
47     public static final String JavaDoc RESYNC_FINISHED_NOTIF_TYPE
48         = RESYNC_PREFIX + "org.oddjob.resyncfinished";
49     
50     /** The server node this object represents. */
51     private final Object JavaDoc node;
52
53     /** The server context for this OddjobMBean. */
54     private final ServerContext srvcon;
55     
56     /** The notification sequenceNumber */
57     private int sequenceNumber = 0;
58
59     /** The factory for adding and removing beans. */
60     private final OddjobMBeanFactory factory;
61
62     /** The interface manager. */
63     private final InterfaceManager iManager;
64         
65     /** Used to ensure that no fresh notificatons are sent during a resync. */
66     private final Object JavaDoc resyncLock = new Object JavaDoc();
67
68     /**
69      * Constructor.
70      *
71      * @param node The job this is shodowing.
72      * @param factory The factory for creating child OddjobMBeans. May be null only
73      * if this MBean will never have children.
74      * @param srvcon The server context The server context. Must not be null.
75      *
76      * @throws RemoteException
77      */

78     public OddjobMBean(Object JavaDoc node, OddjobMBeanFactory factory,
79             ServerContext srvcon) {
80         if (node == null) {
81             throw new NullPointerException JavaDoc("Component must not be null");
82         }
83         if (srvcon == null) {
84             throw new NullPointerException JavaDoc("Server Context must not be null");
85         }
86         this.node = node;
87         this.factory = factory;
88         this.srvcon = srvcon;
89
90         InterfaceManagerFactory imf = srvcon.getInterfaceManagerFactory();
91         iManager = imf.create(node, this);
92     }
93
94     /*
95      * (non-Javadoc)
96      * @see javax.management.DynamicMBean#getAttribute(java.lang.String)
97      */

98     public Object JavaDoc getAttribute(String JavaDoc attribute)
99     throws ReflectionException JavaDoc, MBeanException JavaDoc {
100         logger.debug("getAttribute(" + attribute + ")");
101         return invoke("get", new Object JavaDoc[] { attribute },
102                 new String JavaDoc[] { String JavaDoc.class.getName() });
103     }
104
105     /*
106      * (non-Javadoc)
107      * @see javax.management.DynamicMBean#setAttribute(javax.management.Attribute)
108      */

109     public void setAttribute(Attribute JavaDoc attribute)
110     throws ReflectionException JavaDoc, MBeanException JavaDoc {
111         logger.debug("setAttribute(" + attribute.getName() + ")");
112         invoke("set", new Object JavaDoc[] { attribute.getClass(), attribute.getValue() },
113                 new String JavaDoc[] { String JavaDoc.class.getName(), Object JavaDoc.class.getName() });
114     }
115
116     /*
117      * (non-Javadoc)
118      * @see javax.management.DynamicMBean#getAttributes(java.lang.String[])
119      */

120     public AttributeList JavaDoc getAttributes(String JavaDoc[] attributes) {
121         AttributeList JavaDoc al = new AttributeList JavaDoc();
122         for (int i = 0; i < attributes.length; ++i) {
123             String JavaDoc attribute = attributes[i];
124             Attribute JavaDoc attr;
125             try {
126                 attr = new Attribute JavaDoc(attribute, getAttribute(attribute));
127                 al.add(attr);
128             } catch (ReflectionException JavaDoc e) {
129                 logger.debug(e);
130             } catch (MBeanException JavaDoc e) {
131                 logger.debug(e);
132             }
133         }
134         return al;
135     }
136
137     /*
138      * (non-Javadoc)
139      * @see javax.management.DynamicMBean#setAttributes(javax.management.AttributeList)
140      */

141     public AttributeList JavaDoc setAttributes(AttributeList JavaDoc attributes) {
142         AttributeList JavaDoc al = new AttributeList JavaDoc();
143         for (Iterator JavaDoc it = attributes.iterator(); it.hasNext();) {
144             Attribute JavaDoc attribute = (Attribute JavaDoc) it.next();
145             try {
146                 setAttribute(attribute);
147                 al.add(attribute);
148             } catch (ReflectionException JavaDoc e) {
149                 logger.debug(e);
150             } catch (MBeanException JavaDoc e) {
151                 logger.debug(e);
152             }
153         }
154         return al;
155     }
156
157     /**
158      * Utility function to build a method name from the invoke method arguments.
159      *
160      * @return A String method description.
161      */

162     static String JavaDoc methodDescription(final String JavaDoc actionName, String JavaDoc[] signature) {
163         // build an incredibly converluted debug message.
164
StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
165         buf.append(actionName);
166         buf.append('(');
167         for (int j = 0; j < signature.length; ++j) {
168             buf.append(j== 0 ? "" : ", ");
169             buf.append(signature[j]);
170         }
171         buf.append(")");
172         return buf.toString();
173     }
174     
175     /*
176      * (non-Javadoc)
177      * @see javax.management.DynamicMBean#invoke(java.lang.String, java.lang.Object[], java.lang.String[])
178      */

179     public Object JavaDoc invoke(final String JavaDoc actionName, final Object JavaDoc[] params, String JavaDoc[] signature)
180             throws MBeanException JavaDoc, ReflectionException JavaDoc {
181         String JavaDoc methodDescription = methodDescription(actionName, signature);
182         if (logger.isDebugEnabled()) {
183             logger.debug("Invoking [" +
184                     methodDescription + "] on [" + node + "]");
185         }
186         
187         ////////////////// Log Methods ///////////////////////////////////////////
188

189         if (SharedConstants.RETRIEVE_LOG_EVENTS_METHOD.equals(actionName)
190                 && signature.length == 2
191                 && Long JavaDoc.class.getName().equals(signature[0])
192                 && Integer JavaDoc.class.getName().equals(signature[1])) {
193             return LogArchiverHelper.retrieveLogEvents(node, srvcon,
194                     (Long JavaDoc)params[0], (Integer JavaDoc)params[1]);
195         }
196         else if (SharedConstants.RETRIEVE_CONSOLE_EVENTS_METHOD.equals(actionName) && signature.length == 2
197                 && Long JavaDoc.class.getName().equals(signature[0])
198                 && Integer JavaDoc.class.getName().equals(signature[1])) {
199             return LogArchiverHelper.retrieveConsoleEvents(node, srvcon,
200                     (Long JavaDoc)params[0], (Integer JavaDoc)params[1]);
201         }
202         
203         ////////////////////////////////////////////////////////////
204

205         // anything else - pass to the interface manager.
206
Object JavaDoc[] imported = null;
207         imported = Utils.importResolve(params, srvcon.getComponentRegistry());
208         Object JavaDoc result = iManager.invoke(actionName, imported, signature);
209         return Utils.export(result);
210     }
211
212     /*
213      * (non-Javadoc)
214      * @see javax.management.DynamicMBean#getMBeanInfo()
215      */

216     public MBeanInfo JavaDoc getMBeanInfo() {
217         return iManager.getMBeanInfo();
218     }
219
220     /**
221      * Used by handlers which send notification to get the next notification
222      * number.
223      *
224      * @return The next notification number.
225      */

226     public int getNextNotificationNumber() {
227         synchronized(resyncLock) {
228             return sequenceNumber++;
229         }
230     }
231
232     /**
233      * Synchronize this MBean with a client that has requested it. This is
234      * achieved by resending the last notifications again, with a special
235      * notification type so that they will only be processed by that client
236      * (or clients) which is waiting for the resync.
237      *
238      */

239     void resync() {
240         synchronized (resyncLock) {
241             logger.debug("resync Started");
242             Notification JavaDoc notification = new Notification JavaDoc(
243                     RESYNC_STARTED_NOTIF_TYPE, OddjobMBean.this,
244                     sequenceNumber++);
245             sendNotification(notification);
246             debugSentNotification(notification);
247             Notification JavaDoc[] notifications = iManager.getLastNotifications();
248             for (int i = 0; i < notifications.length; ++i) {
249                 Notification JavaDoc oldNot = notifications[i];
250                 Notification JavaDoc newNot = new Notification JavaDoc(
251                         RESYNC_PREFIX + oldNot.getType(),
252                         oldNot.getSource(),
253                         sequenceNumber++,
254                         oldNot.getTimeStamp(),
255                         oldNot.getMessage());
256                 newNot.setUserData(oldNot.getUserData());
257                 sendNotification(newNot);
258                 debugSentNotification(newNot);
259             }
260             notification = new Notification JavaDoc(RESYNC_FINISHED_NOTIF_TYPE,
261                     OddjobMBean.this, sequenceNumber++);
262             sendNotification(notification);
263             debugSentNotification(notification);
264             logger.debug("resync Finished");
265         }
266     }
267
268     private static void debugSentNotification(Notification JavaDoc notification) {
269         if (!logger.isDebugEnabled()) {
270             return;
271         }
272         logger.debug("Sent notification [" + notification.getType()
273                 + "] sequence [" + notification.getSequenceNumber() + "]");
274     }
275     
276     /**
277      *
278      */

279     ServerInfo serverSideInfo() {
280         return new ServerInfo(
281                 srvcon.getId(),
282                 srvcon.getUrl(),
283                 LogArchiverHelper.consoleId(node, srvcon),
284                 iManager.interfaces(),
285                 srvcon.isRegistryOwner(),
286                 srvcon.getChildId());
287     }
288     
289     /**
290      * Destroy this node. Notify all remote listeners their peer is dead.
291      */

292     void destroy() {
293         logger.debug("Destroying OddjobMBean for [" + node + "]");
294         iManager.destroy();
295     }
296
297     /*
298      * (non-Javadoc)
299      * @see javax.management.NotificationBroadcaster#getNotificationInfo()
300      */

301     public MBeanNotificationInfo JavaDoc[] getNotificationInfo() {
302         return iManager.getMBeanInfo().getNotifications();
303     }
304
305     /**
306      * Used by handlers to execute functionallity while
307      * holding the resync lock.
308      *
309      * @param runnable The functionality to run.
310      */

311     public void runSynchronized(Runnable JavaDoc runnable) {
312         synchronized (resyncLock) {
313             runnable.run();
314         }
315     }
316     
317     /**
318      * Used by handlers to add a child MBean.
319      *
320      * @param child The child.
321      * @return The ObjectName of the child.
322      */

323     public ObjectName JavaDoc addChild(Object JavaDoc child, ServerContext childContext) {
324         ObjectName JavaDoc childName = null;
325         try {
326             childName = factory.createMBeanFor(child, childContext);
327         } catch (JMException JavaDoc ex) {
328             logger.error("Failed to add child MBean", ex);
329         }
330         return childName;
331     }
332     
333     /**
334      * Used by the handlers to remove a child MBean.
335      *
336      * @param childName The child ObjectName to remove.
337      */

338     public void removeChild(ObjectName JavaDoc childName) {
339         try {
340             factory.destroy(childName);
341         } catch (JMException JavaDoc ex) {
342             logger.error("Failed to remove child MBean", ex);
343         }
344     }
345     
346     /**
347      * Gives handlers access to the server context.
348      *
349      * @return The server context for this MBean.
350      */

351     public ServerContext getContext() {
352         return srvcon;
353     }
354     
355 }
Popular Tags