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