1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  
19  package org.apache.commons.modeler.demo;
20  
21  
22  import java.io.InputStream;
23  import java.net.URL;
24  import java.util.Iterator;
25  
26  import javax.management.Attribute;
27  import javax.management.Descriptor;
28  import javax.management.MBeanAttributeInfo;
29  import javax.management.MBeanConstructorInfo;
30  import javax.management.MBeanException;
31  import javax.management.MBeanNotificationInfo;
32  import javax.management.MBeanOperationInfo;
33  import javax.management.MBeanServer;
34  import javax.management.MBeanServerFactory;
35  import javax.management.Notification;
36  import javax.management.NotificationListener;
37  import javax.management.ObjectInstance;
38  import javax.management.ObjectName;
39  import javax.management.modelmbean.ModelMBean;
40  import javax.management.modelmbean.ModelMBeanInfo;
41  
42  import org.apache.commons.modeler.ManagedBean;
43  import org.apache.commons.modeler.Registry;
44  
45  
46  /***
47   * <p>Demonstration program for the Modeller package.  Instantiates a set
48   * of simple managed objects, and a set of corresponding MBeans, then
49   * manipulates the objects through the MBean interfaces.
50   *
51   * @author Craig R. McClanahan
52   * @version $Revision: 480402 $ $Date: 2006-11-29 04:43:23 +0000 (Wed, 29 Nov 2006) $
53   */
54  
55  public class Demo implements NotificationListener {
56  
57  
58      // ----------------------------------------------------- Instance Variables
59  
60  
61      // ------------------------------------------------------- Instance Methods
62  
63  
64      /***
65       * Handle the notification of a JMX event.
66       *
67       * @param notification The event that has occurred
68       * @param handback The handback object for this event
69       */
70      public void handleNotification(Notification notification,
71                                     Object handback) {
72  
73          System.out.println("NOTIFICATION=" + notification +
74                             ", HANDBACK=" + handback);
75  
76      }
77  
78  
79      // ------------------------------------------------------- Static Variables
80  
81  
82      /***
83       * The attribute notification listener.
84       */
85      private static Demo demo = null;
86  
87  
88      /***
89       * The configuration information registry for our managed beans.
90       */
91      private static Registry registry = null;
92  
93  
94      /***
95       * The <code>MBeanServer</code> for this application.
96       */
97      private static MBeanServer server = null;
98  
99  
100     /***
101      * The managed object tree.
102      */
103     private static Server tree = null;
104 
105 
106     // ----------------------------------------------------------- Main Program
107 
108 
109     /***
110      * The main program for this demonstration.
111      *
112      * @param args Command line arguments
113      */
114     public static void main(String arg[]) {
115 
116         createRegistry();
117         createServer();
118         createTree();
119         createMBeans();
120         listMBeans();
121         dumpServer();
122         updateServer();
123 
124     }
125 
126 
127     // -------------------------------------------------------- Support Methods
128 
129 
130     /***
131      * Create the MBeans that correspond to every node of our tree.
132      */
133     private static void createMBeans() {
134 
135         try {
136 
137             // NOTE:  JMXRI crashes on server.setAttribute() unless there has
138             // been an attribute change listener registered at some point
139             // on every ModelMBean. :-(
140             // NOTE:  Despite the documentation, you cannot register an
141             // attribute change listener for all attributes.  :-(
142             Demo demo = new Demo();
143 
144             System.out.println("Creating MBeans ...");
145 
146             // Create the MBean for the top-level Server object
147             String domain = server.getDefaultDomain();
148             ManagedBean managed = registry.findManagedBean("StandardServer");
149             ModelMBean mm = managed.createMBean(tree);
150             mm.addAttributeChangeNotificationListener(demo, "shutdown", tree);
151             mm.addAttributeChangeNotificationListener(demo, "port", tree);
152             server.registerMBean(mm, createName(domain, tree));
153 
154             // Create the MBean for each associated Service and friendes
155             Service services[] = tree.findServices();
156             for (int i = 0; i < services.length; i++) {
157 
158                 // The MBean for the Service itself
159                 managed = registry.findManagedBean("StandardService");
160                 mm = managed.createMBean(services[i]);
161                 mm.addAttributeChangeNotificationListener(demo, "name",
162                                                           services[i]);
163                 server.registerMBean(mm, createName(domain, services[i]));
164 
165                 // The MBean for the corresponding Engine
166                 managed = registry.findManagedBean("StandardEngine");
167                 Engine container = (Engine) services[i].getContainer();
168                 mm = managed.createMBean(container);
169                 mm.addAttributeChangeNotificationListener(demo, "name",
170                                                           container);
171                 server.registerMBean(mm, createName(domain, container));
172 
173                 // The MBeans for the corresponding Connectors
174                 managed = registry.findManagedBean("HttpConnector");
175                 Connector connectors[] = services[i].findConnectors();
176                 for (int j = 0; j < connectors.length; j++) {
177                     mm = managed.createMBean(connectors[j]);
178                     mm.addAttributeChangeNotificationListener(demo, "port",
179                                                               connectors[j]);
180                     server.registerMBean
181                         (mm, createName(domain, connectors[j]));
182                 }
183 
184             }
185 
186         } catch (MBeanException t) {
187 
188             Exception e = t.getTargetException();
189             if (e == null)
190                 e = t;
191             System.out.println(e.getMessage());
192             e.printStackTrace(System.out);
193 
194         } catch (Throwable t) {
195 
196             System.out.println(t.getMessage());
197             t.printStackTrace(System.out);
198 
199         }
200 
201     }
202 
203 
204     /***
205      * Create an <code>ObjectName</code> for this object.
206      *
207      * @param domain Domain in which this name is to be created
208      * @param connector The Connector to be named
209      */
210     private static ObjectName createName(String domain, Connector connector) {
211 
212         ObjectName name = null;
213         try {
214             name = new ObjectName(domain + ":type=Connector,port=" +
215                                   connector.getPort() + ",service=" +
216                                   connector.getService().getName());
217         } catch (Throwable t) {
218             System.out.println("Creating name for " + connector);
219             t.printStackTrace(System.out);
220             System.exit(1);
221         }
222         return (name);
223 
224     }
225 
226 
227     /***
228      * Create an <code>ObjectName</code> for this object.
229      *
230      * @param domain Domain in which this name is to be created
231      * @param engine The Engine to be named
232      */
233     private static ObjectName createName(String domain, Engine engine) {
234 
235         ObjectName name = null;
236         try {
237             name = new ObjectName(domain + ":type=Engine,service=" +
238                                   engine.getService().getName());
239         } catch (Throwable t) {
240             System.out.println("Creating name for " + engine);
241             t.printStackTrace(System.out);
242             System.exit(1);
243         }
244         return (name);
245 
246     }
247 
248 
249     /***
250      * Create an <code>ObjectName</code> for this object.
251      *
252      * @param domain Domain in which this name is to be created
253      * @param server The Server to be named
254      */
255     private static ObjectName createName(String domain, Server server) {
256 
257         ObjectName name = null;
258         try {
259             name = new ObjectName(domain + ":type=Server");
260         } catch (Throwable t) {
261             System.out.println("Creating name for " + server);
262             t.printStackTrace(System.out);
263             System.exit(1);
264         }
265         return (name);
266 
267     }
268 
269 
270     /***
271      * Create an <code>ObjectName</code> for this object.
272      *
273      * @param domain Domain in which this name is to be created
274      * @param service The Service to be named
275      */
276     private static ObjectName createName(String domain, Service service) {
277 
278         ObjectName name = null;
279         try {
280             name = new ObjectName(domain + ":type=Service,name=" +
281                                   service.getName());
282         } catch (Throwable t) {
283             System.out.println("Creating name for " + server);
284             t.printStackTrace(System.out);
285             System.exit(1);
286         }
287         return (name);
288 
289     }
290 
291 
292     /***
293      * Create and configure the registry of managed objects.
294      */
295     private static void createRegistry() {
296 
297         System.out.println("Create configuration registry ...");
298         try {
299             URL url = Demo.class.getResource
300                 ("/org/apache/commons/modeler/demo/mbeans-descriptors.xml");
301             InputStream stream = url.openStream();
302             Registry.loadRegistry(stream);
303             stream.close();
304             registry = Registry.getRegistry();
305         } catch (Throwable t) {
306             t.printStackTrace(System.out);
307             System.exit(1);
308         }
309 
310     }
311 
312 
313     /***
314      * Create the <code>MBeanServer</code> with which we will be
315      * registering our <code>ModelMBean</code> implementations.
316      */
317     private static void createServer() {
318 
319         System.out.println("Creating MBeanServer ...");
320         try {
321             //            System.setProperty("LEVEL_TRACE", "true");
322             server = MBeanServerFactory.createMBeanServer();
323         } catch (Throwable t) {
324             t.printStackTrace(System.out);
325             System.exit(1);
326         }
327 
328     }
329 
330 
331     /***
332      * Create the tree of managed objects.
333      */
334     private static void createTree() {
335 
336         System.out.println("Create managed object tree ...");
337         tree = new Server(8005, "SHUTDOWN");
338 
339         Service service = new Service("Standard Service", tree);
340         tree.addService(service);
341 
342         Engine engine = new Engine("Standard Engine", "localhost", service);
343         service.setContainer(engine);
344 
345         Connector conn1 = new Connector(8080, "http", false,
346                                         service, engine);
347         service.addConnector(conn1);
348         Connector conn2 = new Connector(8443, "https", true,
349                                         service, engine);
350         service.addConnector(conn2);
351 
352     }
353 
354 
355     /***
356      * Dump known information about the "Server" we are managing.
357      */
358     private static void dumpServer() {
359 
360         try {
361 
362             System.out.println("Dump ModelMBeanInfo for Server:");
363             ObjectName name =
364                 new ObjectName(server.getDefaultDomain() + ":type=Server");
365 
366             // Return static ModelMBeanInfo information
367             ModelMBeanInfo info = (ModelMBeanInfo) server.getMBeanInfo(name);
368             System.out.println("  className=" + info.getClassName());
369             System.out.println("  description=" + info.getDescription());
370             System.out.println("  mbeanDescriptor=" + info.getMBeanDescriptor());
371             MBeanAttributeInfo attrs[] = info.getAttributes();
372             for (int i = 0; i < attrs.length; i++)
373                 System.out.println("  AttributeInfo=" + attrs[i]);
374             MBeanConstructorInfo consts[] = info.getConstructors();
375             for (int i = 0; i < consts.length; i++)
376                 System.out.println("  ConstructorInfo=" + consts[i]);
377             Descriptor descs[] = info.getDescriptors(null);
378             for (int i = 0; i < descs.length; i++)
379                 System.out.println("  Descriptor=" + descs[i]);
380             MBeanNotificationInfo notifs[] = info.getNotifications();
381             for (int i = 0; i < notifs.length; i++)
382                 System.out.println("  Notification=" + notifs[i]);
383             MBeanOperationInfo opers[] = info.getOperations();
384             for (int i = 0; i < opers.length; i++)
385                 System.out.println("  Operation=" + opers[i]);
386 
387         } catch (MBeanException t) {
388 
389             Exception e = t.getTargetException();
390             if (e == null)
391                 e = t;
392             System.out.println(e.getMessage());
393             e.printStackTrace(System.out);
394 
395         } catch (Throwable t) {
396 
397             System.out.println(t.getMessage());
398             t.printStackTrace(System.out);
399 
400         }
401 
402 
403     }
404 
405 
406     /***
407      * List information about all registered MBeans.
408      */
409     private static void listMBeans() {
410 
411         System.out.println("There are " + server.getMBeanCount().intValue() +
412                            " registered MBeans");
413         Iterator instances = server.queryMBeans(null, null).iterator();
414         while (instances.hasNext()) {
415             ObjectInstance instance = (ObjectInstance) instances.next();
416             System.out.println("  objectName=" + instance.getObjectName() +
417                                ", className=" + instance.getClassName());
418         }
419 
420 
421     }
422 
423 
424     /***
425      * Test updating an attribute through the JMX interfaces.
426      */
427     private static void updateServer() {
428 
429         try {
430 
431             System.out.println("===========================================");
432 
433             System.out.println("Test updating Server properties ...");
434             ObjectName name =
435                 new ObjectName(server.getDefaultDomain() + ":type=Server");
436 
437             System.out.println("  Retrieving current value of 'shutdown'");
438             String value = (String) server.getAttribute(name, "shutdown");
439             if (!"SHUTDOWN".equals(value))
440                 throw new IllegalStateException("Current shutdown value is '" +
441                                                 value + "'");
442 
443             System.out.println("  Setting new value of 'shutdown'");
444             server.setAttribute(name,
445                                 new Attribute("shutdown", "NEW VALUE"));
446 
447             System.out.println("  Checking new value of 'shutdown'");
448             value = (String) server.getAttribute(name, "shutdown");
449             if (!"NEW VALUE".equals(value))
450                 throw new IllegalStateException("New shutdown value is '" +
451                                                 value + "'");
452 
453             System.out.println("===========================================");
454 
455             System.out.println("Test updating Server properties ...");
456 
457             System.out.println("  Retrieving current value of 'port'");
458             Integer ivalue = (Integer) server.getAttribute(name, "port");
459             if (ivalue.intValue() != 8005)
460                 throw new IllegalStateException("Current port value is '" +
461                                                 ivalue + "'");
462 
463             System.out.println("  Setting new value of 'port'");
464             server.setAttribute(name,
465                                 new Attribute("port", new Integer(8765)));
466             /*
467             server.invoke(name, "setPort",
468                           new Object[] { new java.lang.Integer(8765) },
469                           new String[] { "int" });
470 
471             */
472             System.out.println("  Checking new value of 'port'");
473             ivalue = (Integer) server.getAttribute(name, "port");
474             if (ivalue.intValue() != 8765)
475                 throw new IllegalStateException("New port value is '" +
476                                                 ivalue + "'");
477 
478         } catch (MBeanException t) {
479 
480             Exception e = t.getTargetException();
481             if (e == null)
482                 e = t;
483             System.out.println(e.getMessage());
484             e.printStackTrace(System.out);
485 
486         } catch (Throwable t) {
487 
488             System.out.println(t.getMessage());
489             t.printStackTrace(System.out);
490 
491         }
492 
493 
494     }
495 
496 
497 }