1 /** 2 * Copyright (C) 2006 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.inject.tools.jmx; 18 19 import com.google.inject.Binding; 20 import com.google.inject.Guice; 21 import com.google.inject.Injector; 22 import com.google.inject.Key; 23 import com.google.inject.Module; 24 25 import java.lang.annotation.Annotation; 26 import java.lang.management.ManagementFactory; 27 28 import javax.management.MBeanServer; 29 import javax.management.MalformedObjectNameException; 30 import javax.management.ObjectName; 31 32 /** 33 * Provides a JMX interface to Guice. 34 * 35 * @author crazybob (at) google.com (Bob Lee) 36 */ 37 public class Manager { 38 39 /** 40 * Registers all the bindings of an Injector with the platform MBean server. 41 * Consider using the name of your root {@link Module} class as the domain. 42 */ 43 public static void manage( 44 String domain, 45 Injector injector) { 46 manage(ManagementFactory.getPlatformMBeanServer(), domain, injector); 47 } 48 49 /** 50 * Registers all the bindings of an Injector with the given MBean server. 51 * Consider using the name of your root {@link Module} class as the domain. 52 */ 53 public static void manage(MBeanServer server, String domain, 54 Injector injector) { 55 // Register each binding independently. 56 for (Binding<?> binding : injector.getBindings().values()) { 57 // Construct the name manually so we can ensure proper ordering of the 58 // key/value pairs. 59 StringBuilder name = new StringBuilder(); 60 name.append(domain).append(":"); 61 Key<?> key = binding.getKey(); 62 name.append("type=").append(quote(key.getTypeLiteral().toString())); 63 Annotation annotation = key.getAnnotation(); 64 if (annotation != null) { 65 name.append(",annotation=").append(quote(annotation.toString())); 66 } 67 else { 68 Class<? extends Annotation> annotationType = key.getAnnotationType(); 69 if (annotationType != null) { 70 name.append(",annotation=") 71 .append(quote("@" + annotationType.getName())); 72 } 73 } 74 75 try { 76 server.registerMBean(new ManagedBinding(binding), 77 new ObjectName(name.toString())); 78 } 79 catch (MalformedObjectNameException e) { 80 throw new RuntimeException("Bad object name: " + name, e); 81 } 82 catch (Exception e) { 83 throw new RuntimeException(e); 84 } 85 } 86 } 87 88 static String quote(String value) { 89 // JMX seems to have a comma bug. 90 return ObjectName.quote(value).replace(',', ';'); 91 } 92 93 /** 94 * Run with no arguments for usage instructions. 95 */ 96 public static void main(String[] args) throws Exception { 97 if (args.length != 1) { 98 System.err.println("Usage: java -Dcom.sun.management.jmxremote " 99 + Manager.class.getName() + " [module class name]"); 100 System.err.println("Then run 'jconsole' to connect."); 101 System.exit(1); 102 } 103 104 Module module = (Module) Class.forName(args[0]).newInstance(); 105 Injector injector = Guice.createInjector(module); 106 107 manage(args[0], injector); 108 109 System.out.println("Press Ctrl+C to exit..."); 110 111 // Sleep forever. 112 Thread.sleep(Long.MAX_VALUE); 113 } 114 } 115