6675526: Define an Annotation to name registered MBeans
Reviewed-by: emcmanus
This commit is contained in:
parent
04950cd846
commit
b14fec6973
@ -919,6 +919,12 @@ public class DefaultMBeanServerInterceptor
|
||||
|
||||
DynamicMBean mbean = Introspector.makeDynamicMBean(object);
|
||||
|
||||
//Access the ObjectName template value only if the provided name is null
|
||||
if(name == null) {
|
||||
name = Introspector.templateToObjectName(mbean.getMBeanInfo().
|
||||
getDescriptor(), mbean);
|
||||
}
|
||||
|
||||
return registerDynamicMBean(classname, mbean, name);
|
||||
}
|
||||
|
||||
|
@ -65,8 +65,12 @@ import java.lang.reflect.Array;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.management.AttributeNotFoundException;
|
||||
import javax.management.JMX;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.ObjectNameTemplate;
|
||||
import javax.management.openmbean.CompositeData;
|
||||
import javax.management.openmbean.MXBeanMappingFactory;
|
||||
|
||||
@ -78,7 +82,13 @@ import javax.management.openmbean.MXBeanMappingFactory;
|
||||
*/
|
||||
public class Introspector {
|
||||
|
||||
|
||||
/**
|
||||
* Pattern used to extract Attribute Names from ObjectNameTemplate Annotation
|
||||
* For example, in the following example, the Name attribute value is
|
||||
* retrieved : ":type=MyType, name={Name}"
|
||||
*/
|
||||
private static Pattern OBJECT_NAME_PATTERN_TEMPLATE =
|
||||
Pattern.compile("(\\{[^\\}]+\\})|(=\"\\{[^\\}]+\\}\")");
|
||||
/*
|
||||
* ------------------------------------------
|
||||
* PRIVATE CONSTRUCTORS
|
||||
@ -392,6 +402,42 @@ public class Introspector {
|
||||
return getStandardMBeanInterface(baseClass);
|
||||
}
|
||||
|
||||
public static ObjectName templateToObjectName(Descriptor descriptor,
|
||||
DynamicMBean mbean)
|
||||
throws NotCompliantMBeanException {
|
||||
String template = (String)
|
||||
descriptor.getFieldValue(JMX.OBJECT_NAME_TEMPLATE);
|
||||
if(template == null) return null;
|
||||
try {
|
||||
Matcher m = OBJECT_NAME_PATTERN_TEMPLATE.matcher(template);
|
||||
while (m.find()){
|
||||
String grp = m.group();
|
||||
System.out.println("GROUP " + grp);
|
||||
String attributeName = null;
|
||||
boolean quote = false;
|
||||
if(grp.startsWith("=\"{")) {
|
||||
attributeName = grp.substring(3, grp.length() - 2);
|
||||
quote = true;
|
||||
} else
|
||||
attributeName = grp.substring(1, grp.length() - 1);
|
||||
|
||||
Object attributeValue = mbean.getAttribute(attributeName);
|
||||
String validValue = quote ?
|
||||
"=" + ObjectName.quote(attributeValue.toString()) :
|
||||
attributeValue.toString();
|
||||
template = template.replace(grp, validValue);
|
||||
}
|
||||
return new ObjectName(template);
|
||||
}catch(Exception ex) {
|
||||
NotCompliantMBeanException ncex = new
|
||||
NotCompliantMBeanException(ObjectNameTemplate.class.
|
||||
getSimpleName() + " annotation value [" + template + "] " +
|
||||
"is invalid. " + ex);
|
||||
ncex.initCause(ex);
|
||||
throw ncex;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ------------------------------------------
|
||||
* PRIVATE METHODS
|
||||
|
@ -245,6 +245,13 @@ import javax.management.openmbean.OpenType;
|
||||
* MXBean, if it was not the {@linkplain MXBeanMappingFactory#DEFAULT default}
|
||||
* one.</td>
|
||||
*
|
||||
* <tr><td id="objectNameTemplate"><i>objectNameTemplate</i>
|
||||
* </td><td>String</td>
|
||||
* <td>MBeanInfo</td>
|
||||
*
|
||||
* <td>The template to use to name this MBean. Its value must be compliant with
|
||||
* the specification of the {@link ObjectNameTemplate} annotation.</td>
|
||||
*
|
||||
* <tr id="openType"><td><i>openType</i><td>{@link OpenType}</td>
|
||||
* <td>MBeanAttributeInfo<br>MBeanOperationInfo<br>MBeanParameterInfo</td>
|
||||
*
|
||||
|
@ -149,6 +149,12 @@ public class JMX {
|
||||
*/
|
||||
public static final String SET_EXCEPTIONS_FIELD = "setExceptions";
|
||||
|
||||
/**
|
||||
* The name of the <a href="Descriptor.html#objectNameTemplate">{@code
|
||||
* objectNameTemplate}</a> field.
|
||||
*/
|
||||
public static final String OBJECT_NAME_TEMPLATE = "objectNameTemplate";
|
||||
|
||||
/**
|
||||
* <p>Options to apply to an MBean proxy or to an instance of {@link
|
||||
* StandardMBean}.</p>
|
||||
|
@ -351,11 +351,14 @@ public interface MBeanServer extends MBeanServerConnection {
|
||||
|
||||
/**
|
||||
* <p>Registers a pre-existing object as an MBean with the MBean
|
||||
* server. If the object name given is null, the MBean must
|
||||
* provide its own name by implementing the {@link
|
||||
* server. If the object name given is null, the
|
||||
* MBean must provide its own name in one or both of two ways: by implementing the {@link
|
||||
* javax.management.MBeanRegistration MBeanRegistration} interface
|
||||
* and returning the name from the {@link
|
||||
* MBeanRegistration#preRegister preRegister} method.</p>
|
||||
* MBeanRegistration#preRegister preRegister} method; or by defining
|
||||
* an {@code objectNameTemplate} field in its {@link Descriptor},
|
||||
* typically using the {@link ObjectNameTemplate @ObjectNameTemplate}
|
||||
* annotation.</p>
|
||||
*
|
||||
* <p>If this method successfully registers an MBean, a notification
|
||||
* is sent as described <a href="#notif">above</a>.</p>
|
||||
|
@ -46,11 +46,14 @@ public interface MBeanServerConnection extends NotificationManager {
|
||||
* MBean server will use its {@link
|
||||
* javax.management.loading.ClassLoaderRepository Default Loader
|
||||
* Repository} to load the class of the MBean. An object name is
|
||||
* associated to the MBean. If the object name given is null, the
|
||||
* MBean must provide its own name by implementing the {@link
|
||||
* associated with the MBean. If the object name given is null, the
|
||||
* MBean must provide its own name in one or both of two ways: by implementing the {@link
|
||||
* javax.management.MBeanRegistration MBeanRegistration} interface
|
||||
* and returning the name from the {@link
|
||||
* MBeanRegistration#preRegister preRegister} method.</p>
|
||||
* MBeanRegistration#preRegister preRegister} method; or by defining
|
||||
* an {@code objectNameTemplate} field in its {@link Descriptor},
|
||||
* typically using the {@link ObjectNameTemplate @ObjectNameTemplate}
|
||||
* annotation.</p>
|
||||
*
|
||||
* <p>This method is equivalent to {@link
|
||||
* #createMBean(String,ObjectName,Object[],String[])
|
||||
@ -117,13 +120,16 @@ public interface MBeanServerConnection extends NotificationManager {
|
||||
/**
|
||||
* <p>Instantiates and registers an MBean in the MBean server. The
|
||||
* class loader to be used is identified by its object name. An
|
||||
* object name is associated to the MBean. If the object name of
|
||||
* object name is associated with the MBean. If the object name of
|
||||
* the loader is null, the ClassLoader that loaded the MBean
|
||||
* server will be used. If the MBean's object name given is null,
|
||||
* the MBean must provide its own name by implementing the {@link
|
||||
* server will be used. If the object name given is null, the
|
||||
* MBean must provide its own name in one or both of two ways: by implementing the {@link
|
||||
* javax.management.MBeanRegistration MBeanRegistration} interface
|
||||
* and returning the name from the {@link
|
||||
* MBeanRegistration#preRegister preRegister} method.</p>
|
||||
* MBeanRegistration#preRegister preRegister} method; or by defining
|
||||
* an {@code objectNameTemplate} field in its {@link Descriptor},
|
||||
* typically using the {@link ObjectNameTemplate @ObjectNameTemplate}
|
||||
* annotation.</p>
|
||||
*
|
||||
* <p>This method is equivalent to {@link
|
||||
* #createMBean(String,ObjectName,ObjectName,Object[],String[])
|
||||
@ -198,11 +204,14 @@ public interface MBeanServerConnection extends NotificationManager {
|
||||
* MBean server will use its {@link
|
||||
* javax.management.loading.ClassLoaderRepository Default Loader
|
||||
* Repository} to load the class of the MBean. An object name is
|
||||
* associated to the MBean. If the object name given is null, the
|
||||
* MBean must provide its own name by implementing the {@link
|
||||
* associated with the MBean. If the object name given is null, the
|
||||
* MBean must provide its own name in one or both of two ways: by implementing the {@link
|
||||
* javax.management.MBeanRegistration MBeanRegistration} interface
|
||||
* and returning the name from the {@link
|
||||
* MBeanRegistration#preRegister preRegister} method.
|
||||
* MBeanRegistration#preRegister preRegister} method; or by defining
|
||||
* an {@code objectNameTemplate} field in its {@link Descriptor},
|
||||
* typically using the {@link ObjectNameTemplate @ObjectNameTemplate}
|
||||
* annotation.</p>
|
||||
*
|
||||
* @param className The class name of the MBean to be instantiated.
|
||||
* @param name The object name of the MBean. May be null.
|
||||
@ -267,15 +276,18 @@ public interface MBeanServerConnection extends NotificationManager {
|
||||
NotCompliantMBeanException, IOException;
|
||||
|
||||
/**
|
||||
* Instantiates and registers an MBean in the MBean server. The
|
||||
* <p>Instantiates and registers an MBean in the MBean server. The
|
||||
* class loader to be used is identified by its object name. An
|
||||
* object name is associated to the MBean. If the object name of
|
||||
* object name is associated with the MBean. If the object name of
|
||||
* the loader is not specified, the ClassLoader that loaded the
|
||||
* MBean server will be used. If the MBean object name given is
|
||||
* null, the MBean must provide its own name by implementing the
|
||||
* {@link javax.management.MBeanRegistration MBeanRegistration}
|
||||
* interface and returning the name from the {@link
|
||||
* MBeanRegistration#preRegister preRegister} method.
|
||||
* MBean server will be used. If the object name given is null, the
|
||||
* MBean must provide its own name in one or both of two ways: by implementing the {@link
|
||||
* javax.management.MBeanRegistration MBeanRegistration} interface
|
||||
* and returning the name from the {@link
|
||||
* MBeanRegistration#preRegister preRegister} method; or by defining
|
||||
* an {@code objectNameTemplate} field in its {@link Descriptor},
|
||||
* typically using the {@link ObjectNameTemplate @ObjectNameTemplate}
|
||||
* annotation.</p>
|
||||
*
|
||||
* @param className The class name of the MBean to be instantiated.
|
||||
* @param name The object name of the MBean. May be null.
|
||||
|
131
jdk/src/share/classes/javax/management/ObjectNameTemplate.java
Normal file
131
jdk/src/share/classes/javax/management/ObjectNameTemplate.java
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
package javax.management;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation to allow an MBean to provide its name.
|
||||
* This annotation can be used on the following types:
|
||||
* <ul>
|
||||
* <li>MBean or MXBean Java interface.</li>
|
||||
* <li>Java class annotated with {@link javax.management.MBean @MBean}</code>
|
||||
* annotation.</li>
|
||||
* <li>Java class annotated with {@link javax.management.MXBean @MXBean}</code>
|
||||
* annotation.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>The value of this annotation is used to build the <code>ObjectName</code>
|
||||
* when instances of the annotated type are registered in
|
||||
* an <code>MBeanServer</code> and no explicit name is given to the
|
||||
* {@code createMBean} or {@code registerMBean} method (the {@code ObjectName}
|
||||
* is {@code null}).</p>
|
||||
*
|
||||
* <p>For Dynamic MBeans, which define their own {@code MBeanInfo}, you can
|
||||
* produce the same effect as this annotation by including a field
|
||||
* <a href="Descriptor.html#objectNameTemplate">{@code objectNameTemplate}</a>
|
||||
* in the {@link Descriptor} for the {@code MBeanInfo} returned by
|
||||
* {@link DynamicMBean#getMBeanInfo()}.</p>
|
||||
*
|
||||
* <p>For Standard MBeans and MXBeans, this annotation automatically produces
|
||||
* an {@code objectNameTemplate} field in the {@code Descriptor}.</p>
|
||||
*
|
||||
* <p>The template can contain variables so that the name of the MBean
|
||||
* depends on the value of one or more of its attributes.
|
||||
* A variable that identifies an MBean attribute is of the form
|
||||
* <code>{<em>attribute name</em>}</code>. For example, to make an MBean name
|
||||
* depend on the <code>Name</code> attribute, use the variable
|
||||
* <code>{Name}</code>. Attribute names are case sensitive.
|
||||
* Naming attributes can be of any type. The <code>String</code> returned by
|
||||
* <code>toString()</code> is included in the constructed name.</p>
|
||||
*
|
||||
* <p>If you need the attribute value to be quoted
|
||||
* by a call to {@link ObjectName#quote(String) ObjectName.quote},
|
||||
* surround the variable with quotes. Quoting only applies to key values.
|
||||
* For example, <code>@ObjectNameTemplate("java.lang:type=MemoryPool,name=\"{Name}\"")</code>,
|
||||
* quotes the <code>Name</code> attribute value. You can notice the "\"
|
||||
* character needed to escape a quote within a <code>String</code>. A name
|
||||
* produced by this template might look like
|
||||
* {@code java.lang:type=MemoryPool,name="Code Cache"}.</p>
|
||||
*
|
||||
* <p>Variables can be used anywhere in the <code>String</code>.
|
||||
* Be sure to make the template derived name comply with
|
||||
* {@link ObjectName ObjectName} syntax.</p>
|
||||
*
|
||||
* <p>If an MBean is registered with a null name and it implements
|
||||
* {@link javax.management.MBeanRegistration MBeanRegistration}, then
|
||||
* the computed name is provided to the <code>preRegister</code> method.
|
||||
* Similarly,
|
||||
* if the MBean uses <a href="MBeanRegistration.html#injection">resource
|
||||
* injection</a> to discover its name, it is the computed name that will
|
||||
* be injected.</p>
|
||||
* <p>All of the above can be used with the {@link StandardMBean} class and
|
||||
* the annotation is effective in that case too.</p>
|
||||
* <p>If any exception occurs (such as unknown attribute, invalid syntax or
|
||||
* exception
|
||||
* thrown by the MBean) when the name is computed it is wrapped in a
|
||||
* <code>NotCompliantMBeanException</code>.</p>
|
||||
* <p>Some ObjectName template examples:
|
||||
* <ul><li>"com.example:type=Memory". Fixed ObjectName. Used to name a
|
||||
* singleton MBean.</li>
|
||||
* <li>"com.example:type=MemoryPool,name={Name}". Variable ObjectName.
|
||||
* <code>Name</code> attribute is retrieved to compose the <code>name</code>
|
||||
* key value.</li>
|
||||
* <li>"com.example:type=SomeType,name={InstanceName},id={InstanceId}".
|
||||
* Variable ObjectName.
|
||||
* <code>InstanceName</code> and <code>InstanceId</code> attributes are
|
||||
* retrieved to compose respectively
|
||||
* the <code>name</code> and <code>id</code> key values.</li>
|
||||
* <li>"com.example:type=OtherType,name=\"{ComplexName}\"". Variable ObjectName.
|
||||
* <code>ComplexName</code> attribute is retrieved to compose the
|
||||
* <code>name</code> key quoted value.</li> </li>
|
||||
* <li>"com.example:{TypeKey}=SomeOtherType". Variable ObjectName.
|
||||
* <code>TypeKey</code> attribute is retrieved to compose the
|
||||
* first key name.</li>
|
||||
* * <li>"{Domain}:type=YetAnotherType". Variable ObjectName.
|
||||
* <code>Domain</code> attribute is retrieved to compose the
|
||||
* management domain.</li>
|
||||
* <li>"{Naming}". Variable ObjectName.
|
||||
* <code>Naming</code> attribute is retrieved to compose the
|
||||
* complete name.</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface ObjectNameTemplate {
|
||||
|
||||
/**
|
||||
* The MBean name template.
|
||||
* @return The MBean name template.
|
||||
*/
|
||||
@DescriptorKey("objectNameTemplate")
|
||||
public String value();
|
||||
}
|
@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test %M% %I%
|
||||
* @bug 6675526
|
||||
* @summary Test MBeans named with @ObjectNameTemplate
|
||||
* @author Jean-Francois Denise
|
||||
* @run main/othervm ObjectNameTemplateTest
|
||||
*/
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.management.Attribute;
|
||||
import javax.management.AttributeList;
|
||||
import javax.management.AttributeNotFoundException;
|
||||
import javax.management.DynamicMBean;
|
||||
import javax.management.ImmutableDescriptor;
|
||||
import javax.management.InvalidAttributeValueException;
|
||||
import javax.management.JMX;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanInfo;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MXBean;
|
||||
import javax.management.MBean;
|
||||
import javax.management.ManagedAttribute;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.ObjectNameTemplate;
|
||||
import javax.management.ReflectionException;
|
||||
import javax.management.StandardMBean;
|
||||
|
||||
public class ObjectNameTemplateTest {
|
||||
|
||||
private static MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||
private static final String NAME_TEMPLATE_MULTI =
|
||||
"com.example:type=MultiStdCache,name={Name}";
|
||||
private static final String NAME_TEMPLATE_MONO =
|
||||
"com.example:{Type}={TypeValue}";
|
||||
private static final String NAME_TEMPLATE_QUOTED =
|
||||
"com.example:type=Quotted,name=\"{Name}\"";
|
||||
private static final String NAME_TEMPLATE_WRAPPED =
|
||||
"com.example:type=MgtInterface,id={Id}";
|
||||
private static final String NAME_TEMPLATE_FULL =
|
||||
"{Naming}";
|
||||
private static final String FULL_NAME = "com.example:type=NotAdvised";
|
||||
private static final String NAME1 = "toto1";
|
||||
private static final String NAME2 = "toto2";
|
||||
private static final String TYPE_KEY = "thisIsTheType";
|
||||
private static final String TYPE_VALUE = "aTypeValue";
|
||||
private static final String INVALID_NAME = "?,=*,\n, ";
|
||||
private static final int ID = 999;
|
||||
private static Object[] EMPTY_PARAMS = {};
|
||||
private static String[] EMPTY_SIGNATURE = {};
|
||||
private static final ObjectName OBJECTNAME_CACHE =
|
||||
ObjectName.valueOf("com.example:type=Cache");
|
||||
private static final ObjectName OBJECTNAME_SUBCACHE =
|
||||
ObjectName.valueOf("com.example:type=SubCache");
|
||||
private static final ObjectName OBJECTNAME_CACHEMX =
|
||||
ObjectName.valueOf("com.example:type=CacheMX");
|
||||
private static final ObjectName OBJECTNAME_SUBCACHEMX =
|
||||
ObjectName.valueOf("com.example:type=SubCacheMX");
|
||||
private static final ObjectName OBJECTNAME_DYNACACHE =
|
||||
ObjectName.valueOf("com.example:type=DynaCache");
|
||||
private static final ObjectName OBJECTNAME_STDCACHE =
|
||||
ObjectName.valueOf("com.example:type=StdCache");
|
||||
private static final ObjectName OBJECTNAME_STDCACHEMX =
|
||||
ObjectName.valueOf("com.example:type=StdCacheMX");
|
||||
private static final ObjectName OBJECTNAME_MULTI_1 =
|
||||
ObjectName.valueOf("com.example:" +
|
||||
"type=MultiStdCache,name=" + NAME1);
|
||||
private static final ObjectName OBJECTNAME_MULTI_2 =
|
||||
ObjectName.valueOf("com.example:" +
|
||||
"type=MultiStdCache,name=" + NAME2);
|
||||
private static final ObjectName OBJECTNAME_MONO =
|
||||
ObjectName.valueOf("com.example:" + TYPE_KEY + "=" +
|
||||
TYPE_VALUE);
|
||||
private static final ObjectName OBJECTNAME_QUOTED =
|
||||
ObjectName.valueOf("com.example:type=Quotted," +
|
||||
"name="+ObjectName.quote(INVALID_NAME));
|
||||
private static final ObjectName OBJECTNAME_WRAPPED_RESOURCE =
|
||||
ObjectName.valueOf("com.example:type=MgtInterface,id=" + ID);
|
||||
private static final ObjectName OBJECTNAME_FULL =
|
||||
ObjectName.valueOf(FULL_NAME);
|
||||
|
||||
private static void test(Class<?> mbean, Object[] params,
|
||||
String[] signature, ObjectName name, String template)
|
||||
throws Exception {
|
||||
mbs.createMBean(mbean.getName(), null, params, signature);
|
||||
test(name, template);
|
||||
List<Class<?>> parameters = new ArrayList<Class<?>>();
|
||||
for (String sig : signature) {
|
||||
parameters.add(Class.forName(sig));
|
||||
}
|
||||
Class<?> classes[] = new Class<?>[parameters.size()];
|
||||
Constructor ctr = mbean.getConstructor(parameters.toArray(classes));
|
||||
Object inst = ctr.newInstance(params);
|
||||
test(inst, name, template);
|
||||
}
|
||||
|
||||
private static void test(Object obj, ObjectName name, String template)
|
||||
throws Exception {
|
||||
mbs.registerMBean(obj, null);
|
||||
test(name, template);
|
||||
}
|
||||
|
||||
private static void test(ObjectName name, String template)
|
||||
throws Exception {
|
||||
if (!mbs.isRegistered(name)) {
|
||||
throw new Exception("Wrong " + name + " name");
|
||||
}
|
||||
if (template != null && !mbs.getMBeanInfo(name).getDescriptor().
|
||||
getFieldValue("objectNameTemplate").equals(template)) {
|
||||
throw new Exception("Invalid Derscriptor");
|
||||
}
|
||||
mbs.unregisterMBean(name);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
test(Cache.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_CACHE,
|
||||
OBJECTNAME_CACHE.toString());
|
||||
|
||||
test(CacheMX.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_CACHEMX,
|
||||
OBJECTNAME_CACHEMX.toString());
|
||||
|
||||
test(SubCache.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_SUBCACHE,
|
||||
OBJECTNAME_SUBCACHE.toString());
|
||||
|
||||
test(SubCacheMX.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_SUBCACHEMX,
|
||||
OBJECTNAME_SUBCACHEMX.toString());
|
||||
|
||||
test(DynaCache.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_DYNACACHE,
|
||||
null);
|
||||
|
||||
test(StdCacheMX.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_STDCACHEMX,
|
||||
OBJECTNAME_STDCACHEMX.toString());
|
||||
|
||||
test(StdCache.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_STDCACHE,
|
||||
OBJECTNAME_STDCACHE.toString());
|
||||
String[] sig = {String.class.getName()};
|
||||
Object[] params = {NAME1};
|
||||
test(MultiStdCache.class, params, sig, OBJECTNAME_MULTI_1,
|
||||
NAME_TEMPLATE_MULTI);
|
||||
Object[] params2 = {NAME2};
|
||||
test(MultiStdCache.class, params2, sig, OBJECTNAME_MULTI_2,
|
||||
NAME_TEMPLATE_MULTI);
|
||||
|
||||
test(MonoStdCache.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_MONO,
|
||||
NAME_TEMPLATE_MONO);
|
||||
|
||||
test(Quoted.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_QUOTED,
|
||||
NAME_TEMPLATE_QUOTED);
|
||||
|
||||
test(new StandardMBean(new WrappedResource(), MgtInterface.class),
|
||||
OBJECTNAME_WRAPPED_RESOURCE, NAME_TEMPLATE_WRAPPED);
|
||||
|
||||
test(FullName.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_FULL,
|
||||
NAME_TEMPLATE_FULL);
|
||||
try {
|
||||
test(Wrong.class, EMPTY_PARAMS, EMPTY_SIGNATURE, null, null);
|
||||
throw new Exception("No treceived expected Exception");
|
||||
} catch (NotCompliantMBeanException ncex) {
|
||||
if (!(ncex.getCause() instanceof AttributeNotFoundException)) {
|
||||
throw new Exception("Invalid initCause");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@MBean
|
||||
@ObjectNameTemplate("{Naming}")
|
||||
public static class FullName {
|
||||
|
||||
@ManagedAttribute
|
||||
public String getNaming() {
|
||||
return FULL_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
@ObjectNameTemplate("com.example:type=MgtInterface,id={Id}")
|
||||
public interface MgtInterface {
|
||||
|
||||
public int getId();
|
||||
}
|
||||
|
||||
public static class WrappedResource implements MgtInterface {
|
||||
|
||||
public int getId() {
|
||||
return ID;
|
||||
}
|
||||
}
|
||||
|
||||
@MBean
|
||||
@ObjectNameTemplate("com.example:type=Cache")
|
||||
public static class Cache {
|
||||
}
|
||||
|
||||
@ObjectNameTemplate("com.example:type=SubCache")
|
||||
public static class SubCache extends Cache {
|
||||
}
|
||||
|
||||
@MXBean
|
||||
@ObjectNameTemplate("com.example:type=CacheMX")
|
||||
public static class CacheMX {
|
||||
}
|
||||
|
||||
@ObjectNameTemplate("com.example:type=SubCacheMX")
|
||||
public static class SubCacheMX extends CacheMX {
|
||||
}
|
||||
|
||||
@ObjectNameTemplate("com.example:type=StdCache")
|
||||
public interface StdCacheMBean {
|
||||
}
|
||||
|
||||
public static class StdCache implements StdCacheMBean {
|
||||
}
|
||||
|
||||
@ObjectNameTemplate("com.example:type=StdCacheMX")
|
||||
public interface StdCacheMXBean {
|
||||
}
|
||||
|
||||
public static class StdCacheMX implements StdCacheMXBean {
|
||||
}
|
||||
|
||||
public static class DynaCache implements DynamicMBean {
|
||||
|
||||
public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
public AttributeList getAttributes(String[] attributes) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
public AttributeList setAttributes(AttributeList attributes) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
public MBeanInfo getMBeanInfo() {
|
||||
ImmutableDescriptor d = new ImmutableDescriptor(JMX.OBJECT_NAME_TEMPLATE + "=com.example:type=DynaCache");
|
||||
|
||||
return new MBeanInfo("DynaCache", "Description", null, null, null, null, d);
|
||||
}
|
||||
}
|
||||
|
||||
@ObjectNameTemplate("com.example:type=MultiStdCache,name={Name}")
|
||||
public interface MultiStdCacheMXBean {
|
||||
|
||||
public String getName();
|
||||
}
|
||||
|
||||
public static class MultiStdCache implements MultiStdCacheMXBean {
|
||||
|
||||
private String name;
|
||||
|
||||
public MultiStdCache(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
@ObjectNameTemplate("com.example:{Type}={TypeValue}")
|
||||
public interface MonoStdCacheMXBean {
|
||||
|
||||
public String getTypeValue();
|
||||
|
||||
public String getType();
|
||||
}
|
||||
|
||||
public static class MonoStdCache implements MonoStdCacheMXBean {
|
||||
|
||||
public String getTypeValue() {
|
||||
return TYPE_VALUE;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return TYPE_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
@ObjectNameTemplate("com.example:type=Quotted,name=\"{Name}\"")
|
||||
public interface QuottedMXBean {
|
||||
|
||||
public String getName();
|
||||
}
|
||||
|
||||
public static class Quoted implements QuottedMXBean {
|
||||
|
||||
public String getName() {
|
||||
return INVALID_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
@ObjectNameTemplate("com.example:{Type}={TypeValue}, name={Name}")
|
||||
public interface WrongMXBean {
|
||||
|
||||
public String getTypeValue();
|
||||
|
||||
public String getType();
|
||||
}
|
||||
|
||||
public static class Wrong implements WrongMXBean {
|
||||
|
||||
public String getTypeValue() {
|
||||
return TYPE_VALUE;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return TYPE_KEY;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user