Browse files

Expand collection name generation support

Add ObjecNameFunction for collection bindings
Add MapNamingFunction and MapObjectNameFunction for building names based on key and value
  • Loading branch information...
1 parent 062b867 commit 337f4cf6feaca5b16b5a560aaebe287f00705751 @dain committed Jul 24, 2012
View
2 pom.xml
@@ -31,7 +31,7 @@
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
- <version>5.14.2</version>
+ <version>6.2.1</version>
<scope>test</scope>
</dependency>
View
59 src/main/java/org/weakref/jmx/MBeanExporter.java
@@ -32,13 +32,12 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-
-import static java.lang.String.format;
+import java.util.Map.Entry;
public class MBeanExporter
{
private final MBeanServer server;
- private final Map<String, Object> exportedObjects;
+ private final Map<ObjectName, Object> exportedObjects;
MBeanExporter()
{
@@ -57,19 +56,27 @@ public void export(String name, Object object)
ObjectName objectName;
try {
objectName = new ObjectName(name);
+ }
+ catch (MalformedObjectNameException e) {
+ throw new JmxException(Reason.MALFORMED_OBJECT_NAME, e.getMessage());
+ }
+
+ export(objectName, object);
+ }
+
+ public void export(ObjectName objectName, Object object)
+ {
+ try {
MBeanBuilder builder = new MBeanBuilder(object);
MBean mbean = builder.build();
synchronized(exportedObjects) {
- exportedObjects.put(name, object);
+ exportedObjects.put(objectName, object);
server.registerMBean(mbean, objectName);
}
}
- catch (MalformedObjectNameException e) {
- throw new JmxException(Reason.MALFORMED_OBJECT_NAME, e.getMessage());
- }
catch (InstanceAlreadyExistsException e) {
- throw new JmxException(JmxException.Reason.INSTANCE_ALREADY_EXISTS, e.getMessage());
+ throw new JmxException(Reason.INSTANCE_ALREADY_EXISTS, e.getMessage());
}
catch (MBeanRegistrationException e) {
throw new JmxException(Reason.MBEAN_REGISTRATION, e.getMessage(), e.getCause());
@@ -86,20 +93,27 @@ public void unexport(String name)
try {
objectName = new ObjectName(name);
+ }
+ catch (MalformedObjectNameException e) {
+ throw new JmxException(Reason.MALFORMED_OBJECT_NAME, e.getMessage());
+ }
+ unexport(objectName);
+ }
+
+ public void unexport(ObjectName objectName)
+ {
+ try {
synchronized(exportedObjects) {
server.unregisterMBean(objectName);
- exportedObjects.remove(name);
+ exportedObjects.remove(objectName);
}
}
- catch (MalformedObjectNameException e) {
- throw new JmxException(Reason.MALFORMED_OBJECT_NAME, e.getMessage());
- }
catch (MBeanRegistrationException e) {
- throw new JmxException(JmxException.Reason.MBEAN_REGISTRATION, e.getMessage(), e.getCause());
+ throw new JmxException(Reason.MBEAN_REGISTRATION, e.getMessage(), e.getCause());
}
catch (InstanceNotFoundException e) {
- throw new JmxException(JmxException.Reason.INSTANCE_NOT_FOUND, e.getMessage());
+ throw new JmxException(Reason.INSTANCE_NOT_FOUND, e.getMessage());
}
}
@@ -122,22 +136,19 @@ public void unexportAll()
Map<String, Exception> errors = new HashMap<String, Exception>();
synchronized(exportedObjects) {
- List<String> toRemove = new ArrayList<String>(exportedObjects.size());
- for (String objectName : exportedObjects.keySet()) {
+ List<ObjectName> toRemove = new ArrayList<ObjectName>(exportedObjects.size());
+ for (ObjectName objectName : exportedObjects.keySet()) {
try {
- server.unregisterMBean(new ObjectName(objectName));
+ server.unregisterMBean(objectName);
toRemove.add(objectName);
}
catch(InstanceNotFoundException e) {
// ignore ... mbean has already been unregistered elsewhere
toRemove.add(objectName);
}
- catch (MalformedObjectNameException e) {
- throw new IllegalStateException(format("Found a malformed object name [%s]. This should never happen", objectName), e);
- }
catch (MBeanRegistrationException e) {
//noinspection ThrowableResultOfMethodCallIgnored
- errors.put(objectName, e);
+ errors.put(objectName.toString(), e);
}
}
@@ -150,7 +161,11 @@ public void unexportAll()
public Map<String, Object> getExportedObjects()
{
synchronized (exportedObjects) {
- return ImmutableMap.copyOf(exportedObjects);
+ ImmutableMap.Builder<String,Object> builder = ImmutableMap.builder();
+ for (Entry<ObjectName, Object> entry : exportedObjects.entrySet()) {
+ builder.put(entry.getKey().toString(), entry.getValue());
+ }
+ return builder.build();
}
}
View
18 src/main/java/org/weakref/jmx/guice/GuiceMBeanExporter.java
@@ -15,13 +15,13 @@
*/
package org.weakref.jmx.guice;
-import java.util.Map;
-import java.util.Set;
-
-import org.weakref.jmx.MBeanExporter;
-
import com.google.inject.Inject;
import com.google.inject.Injector;
+import org.weakref.jmx.MBeanExporter;
+
+import javax.management.ObjectName;
+import java.util.Map;
+import java.util.Set;
class GuiceMBeanExporter
{
@@ -42,12 +42,12 @@ public GuiceMBeanExporter(Set<Mapping> mappings,
private <K, V> void exportMaps(Set<MapMapping<K, V>> mapMappings, MBeanExporter exporter, Injector injector)
{
for (MapMapping<K, V> mapping : mapMappings) {
- NamingFunction<Map.Entry<K, V>> namingFunction = mapping.getNamingFunction();
+ ObjectNameFunction<Map.Entry<K, V>> namingFunction = mapping.getObjectNameFunction();
Map<K, V> map = injector.getInstance(mapping.getKey());
for (Map.Entry<K, V> entry : map.entrySet()) {
- String name = namingFunction.name(entry);
+ ObjectName name = namingFunction.name(entry);
exporter.export(name, entry.getValue());
}
}
@@ -56,12 +56,12 @@ public GuiceMBeanExporter(Set<Mapping> mappings,
private <T> void exportSets(Set<SetMapping<T>> setMappings, MBeanExporter exporter, Injector injector)
{
for (SetMapping<T> mapping : setMappings) {
- NamingFunction<T> namingFunction = mapping.getNamingFunction();
+ ObjectNameFunction<T> objectNameFunction = mapping.getObjectNameFunction();
Set<T> set = injector.getInstance(mapping.getKey());
for (T instance : set) {
- String name = namingFunction.name(instance);
+ ObjectName name = objectNameFunction.name(instance);
exporter.export(name, instance);
}
}
View
7 src/main/java/org/weakref/jmx/guice/MBeanModule.java
@@ -15,11 +15,13 @@
*/
package org.weakref.jmx.guice;
-import static com.google.inject.multibindings.Multibinder.newSetBinder;
-
import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.Key;
+import com.google.inject.Scopes;
+import org.weakref.jmx.MBeanExporter;
+
+import static com.google.inject.multibindings.Multibinder.newSetBinder;
public class MBeanModule
extends AbstractModule
@@ -32,6 +34,7 @@ protected final void configure()
builder = newExporter(binder());
bind(GuiceMBeanExporter.class).asEagerSingleton();
+ bind(MBeanExporter.class).in(Scopes.SINGLETON);
configureMBeans();
}
View
63 src/main/java/org/weakref/jmx/guice/MapExportBinder.java
@@ -1,8 +1,11 @@
package org.weakref.jmx.guice;
+import com.google.common.base.Throwables;
import com.google.inject.multibindings.Multibinder;
import org.weakref.jmx.ObjectNames;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
import java.util.Map;
public class MapExportBinder<K, V>
@@ -20,15 +23,65 @@
public void withGeneratedName(final NamingFunction<V> valueNamingFunction)
{
- NamingFunction<Map.Entry<K, V>> entryNamingFunction = new NamingFunction<Map.Entry<K, V>>()
+ ObjectNameFunction<Map.Entry<K, V>> objectNameFunction = new ObjectNameFunction<Map.Entry<K, V>>()
{
- public String name(Map.Entry<K, V> entry)
+ public ObjectName name(Map.Entry<K, V> entry)
{
- String itemName = valueNamingFunction.name(entry.getValue());
- return ObjectNames.generatedNameOf(valueClass, itemName);
+ try {
+ String itemName = valueNamingFunction.name(entry.getValue());
+ return new ObjectName(ObjectNames.generatedNameOf(valueClass, itemName));
+ }
+ catch (MalformedObjectNameException e) {
+ throw Throwables.propagate(e);
+ }
}
};
- binder.addBinding().toInstance(new MapMapping<K, V>(keyClass, valueClass, entryNamingFunction));
+ binder.addBinding().toInstance(new MapMapping<K, V>(keyClass, valueClass, objectNameFunction));
+ }
+
+ public void withGeneratedName(final ObjectNameFunction<V> valueNamingFunction)
+ {
+ ObjectNameFunction<Map.Entry<K, V>> objectNameFunction = new ObjectNameFunction<Map.Entry<K, V>>()
+ {
+ public ObjectName name(Map.Entry<K, V> entry)
+ {
+ return valueNamingFunction.name(entry.getValue());
+ }
+ };
+
+ binder.addBinding().toInstance(new MapMapping<K, V>(keyClass, valueClass, objectNameFunction));
+ }
+
+ public void withGeneratedName(final MapNamingFunction<K, V> valueNamingFunction)
+ {
+ ObjectNameFunction<Map.Entry<K, V>> objectNameFunction = new ObjectNameFunction<Map.Entry<K, V>>()
+ {
+ public ObjectName name(Map.Entry<K, V> entry)
+ {
+ try {
+ String itemName = valueNamingFunction.name(entry.getKey(), entry.getValue());
+ return new ObjectName(ObjectNames.generatedNameOf(valueClass, itemName));
+ }
+ catch (MalformedObjectNameException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+ };
+
+ binder.addBinding().toInstance(new MapMapping<K, V>(keyClass, valueClass, objectNameFunction));
+ }
+
+ public void withGeneratedName(final MapObjectNameFunction<K, V> valueNamingFunction)
+ {
+ ObjectNameFunction<Map.Entry<K, V>> objectNameFunction = new ObjectNameFunction<Map.Entry<K, V>>()
+ {
+ public ObjectName name(Map.Entry<K, V> entry)
+ {
+ return valueNamingFunction.name(entry.getKey(), entry.getValue());
+ }
+ };
+
+ binder.addBinding().toInstance(new MapMapping<K, V>(keyClass, valueClass, objectNameFunction));
}
}
View
11 src/main/java/org/weakref/jmx/guice/MapMapping.java
@@ -6,23 +6,24 @@
import java.lang.reflect.Type;
import java.util.Map;
+import java.util.Map.Entry;
class MapMapping<K, V>
{
- private final NamingFunction<Map.Entry<K, V>> namingFunction;
+ private final ObjectNameFunction<Entry<K, V>> objectNameFunction;
private final Class<K> keyClass;
private final Class<V> valueClass;
- MapMapping(Class<K> keyClass, Class<V> valueClass, NamingFunction<Map.Entry<K, V>> namingFunction)
+ MapMapping(Class<K> keyClass, Class<V> valueClass, ObjectNameFunction<Map.Entry<K, V>> objectNameFunction)
{
this.keyClass = keyClass;
this.valueClass = valueClass;
- this.namingFunction = namingFunction;
+ this.objectNameFunction = objectNameFunction;
}
- public NamingFunction<Map.Entry<K, V>> getNamingFunction()
+ public ObjectNameFunction<Map.Entry<K, V>> getObjectNameFunction()
{
- return namingFunction;
+ return objectNameFunction;
}
public Key<Map<K, V>> getKey()
View
6 src/main/java/org/weakref/jmx/guice/MapNamingFunction.java
@@ -0,0 +1,6 @@
+package org.weakref.jmx.guice;
+
+public interface MapNamingFunction<K, V>
+{
+ String name(K key, V value);
+}
View
8 src/main/java/org/weakref/jmx/guice/MapObjectNameFunction.java
@@ -0,0 +1,8 @@
+package org.weakref.jmx.guice;
+
+import javax.management.ObjectName;
+
+public interface MapObjectNameFunction<K, V>
+{
+ ObjectName name(K key, V value);
+}
View
8 src/main/java/org/weakref/jmx/guice/ObjectNameFunction.java
@@ -0,0 +1,8 @@
+package org.weakref.jmx.guice;
+
+import javax.management.ObjectName;
+
+public interface ObjectNameFunction<T>
+{
+ ObjectName name(T object);
+}
View
32 src/main/java/org/weakref/jmx/guice/SetExportBinder.java
@@ -1,8 +1,12 @@
package org.weakref.jmx.guice;
+import com.google.common.base.Throwables;
import com.google.inject.multibindings.Multibinder;
import org.weakref.jmx.ObjectNames;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
public class SetExportBinder<T>
{
private final Multibinder<SetMapping<?>> binder;
@@ -16,15 +20,33 @@
public void withGeneratedName(final NamingFunction<T> itemNamingFunction)
{
- NamingFunction<T> namingFunction = new NamingFunction<T>()
+ ObjectNameFunction<T> objectNameFunction = new ObjectNameFunction<T>()
+ {
+ public ObjectName name(T object)
+ {
+ try {
+ String itemName = itemNamingFunction.name(object);
+ return new ObjectName(ObjectNames.generatedNameOf(clazz, itemName));
+ }
+ catch (MalformedObjectNameException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+ };
+
+ binder.addBinding().toInstance(new SetMapping<T>(clazz, objectNameFunction));
+ }
+
+ public void withGeneratedName(final ObjectNameFunction<T> itemNamingFunction)
+ {
+ ObjectNameFunction<T> objectNameFunction = new ObjectNameFunction<T>()
{
- public String name(T object)
+ public ObjectName name(T object)
{
- String itemName = itemNamingFunction.name(object);
- return ObjectNames.generatedNameOf(clazz, itemName);
+ return itemNamingFunction.name(object);
}
};
- binder.addBinding().toInstance(new SetMapping<T>(clazz, namingFunction));
+ binder.addBinding().toInstance(new SetMapping<T>(clazz, objectNameFunction));
}
}
View
10 src/main/java/org/weakref/jmx/guice/SetMapping.java
@@ -9,18 +9,18 @@
class SetMapping<T>
{
- private final NamingFunction<T> namingFunction;
+ private final ObjectNameFunction<T> objectNameFunction;
private final Class<T> clazz;
- SetMapping(Class<T> key, NamingFunction<T> namingFunction)
+ SetMapping(Class<T> key, ObjectNameFunction<T> objectNameFunction)
{
this.clazz = key;
- this.namingFunction = namingFunction;
+ this.objectNameFunction = objectNameFunction;
}
- public NamingFunction<T> getNamingFunction()
+ public ObjectNameFunction<T> getObjectNameFunction()
{
- return namingFunction;
+ return objectNameFunction;
}
public Key<Set<T>> getKey()
View
15 src/main/java/org/weakref/jmx/guice/StringMapExportBinder.java
@@ -1,9 +1,13 @@
package org.weakref.jmx.guice;
+import com.google.common.base.Throwables;
import com.google.inject.multibindings.Multibinder;
import org.weakref.jmx.ObjectNames;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
import java.util.Map;
+import java.util.Map.Entry;
public class StringMapExportBinder<V>
extends MapExportBinder<String, V>
@@ -18,11 +22,16 @@
public void withGeneratedName()
{
- NamingFunction<Map.Entry<String, V>> namingFunction = new NamingFunction<Map.Entry<String, V>>()
+ ObjectNameFunction<Entry<String, V>> namingFunction = new ObjectNameFunction<Map.Entry<String, V>>()
{
- public String name(Map.Entry<String, V> entry)
+ public ObjectName name(Map.Entry<String, V> entry)
{
- return ObjectNames.generatedNameOf(valueClass, entry.getKey());
+ try {
+ return new ObjectName(ObjectNames.generatedNameOf(valueClass, entry.getKey()));
+ }
+ catch (MalformedObjectNameException e) {
+ throw Throwables.propagate(e);
+ }
}
};
View
24 src/test/java/org/weakref/jmx/guice/TestMBeanModule.java
@@ -53,6 +53,9 @@ public void testExportedInDevelopmentStageToo()
@Override
protected void configure()
{
+ binder().requireExplicitBindings();
+ binder().disableCircularProxies();
+
bind(SimpleObject.class).asEagerSingleton();
bind(MBeanServer.class).toInstance(ManagementFactory.getPlatformMBeanServer());
ExportBinder.newExporter(binder()).export(SimpleObject.class).as(name.getCanonicalName());
@@ -74,6 +77,9 @@ public void testBasic()
@Override
protected void configure()
{
+ binder().requireExplicitBindings();
+ binder().disableCircularProxies();
+
bind(SimpleObject.class).asEagerSingleton();
bind(MBeanServer.class).toInstance(ManagementFactory.getPlatformMBeanServer());
ExportBinder.newExporter(binder()).export(SimpleObject.class).as(name.getCanonicalName());
@@ -97,6 +103,9 @@ public void testGeneratedNames()
@Override
protected void configure()
{
+ binder().requireExplicitBindings();
+ binder().disableCircularProxies();
+
bind(SimpleObject.class).asEagerSingleton();
bind(MBeanServer.class).toInstance(ManagementFactory.getPlatformMBeanServer());
ExportBinder.newExporter(binder()).export(SimpleObject.class).withGeneratedName();
@@ -121,6 +130,9 @@ public void testGeneratedNameOnNamedAnnotation()
@Override
protected void configure()
{
+ binder().requireExplicitBindings();
+ binder().disableCircularProxies();
+
bind(SimpleObject.class).annotatedWith(named("hello")).toInstance(new SimpleObject());
bind(MBeanServer.class).toInstance(ManagementFactory.getPlatformMBeanServer());
ExportBinder.newExporter(binder()).export(SimpleObject.class).annotatedWith(named("hello")).withGeneratedName();
@@ -144,6 +156,9 @@ public void testAnnotation()
@Override
protected void configure()
{
+ binder().requireExplicitBindings();
+ binder().disableCircularProxies();
+
bind(SimpleObject.class).annotatedWith(TestAnnotation.class).toInstance(new SimpleObject());
bind(MBeanServer.class).toInstance(ManagementFactory.getPlatformMBeanServer());
ExportBinder.newExporter(binder()).export(SimpleObject.class).annotatedWith(TestAnnotation.class).as(objectName.getCanonicalName());
@@ -168,6 +183,9 @@ public void testNamedAnnotations()
@Override
protected void configure()
{
+ binder().requireExplicitBindings();
+ binder().disableCircularProxies();
+
bind(SimpleObject.class).annotatedWith(Names.named("1")).toInstance(new SimpleObject());
bind(SimpleObject.class).annotatedWith(Names.named("2")).toInstance(new SimpleObject());
bind(MBeanServer.class).toInstance(ManagementFactory.getPlatformMBeanServer());
@@ -199,6 +217,9 @@ public void testExportKey()
@Override
protected void configure()
{
+ binder().requireExplicitBindings();
+ binder().disableCircularProxies();
+
bind(MBeanServer.class).toInstance(ManagementFactory.getPlatformMBeanServer());
bind(SimpleObject.class).toInstance(new SimpleObject());
bind(SimpleObject.class).annotatedWith(Names.named("1")).toInstance(new SimpleObject());
@@ -234,6 +255,9 @@ public void testSet()
@Override
protected void configure()
{
+ binder().requireExplicitBindings();
+ binder().disableCircularProxies();
+
Multibinder<SimpleObject> multibinder = Multibinder.newSetBinder(binder(), SimpleObject.class);
SimpleObject object1 = new SimpleObject();

0 comments on commit 337f4cf

Please sign in to comment.