From 5588717cc48fdb82e2f6c23f4ff61d7553e5be51 Mon Sep 17 00:00:00 2001
From: Eamonn McManus Each {@code @NotificationInfo} produces an {@link
@@ -64,6 +74,13 @@ import java.lang.annotation.Target;
* several {@code @NotificationInfo} annotations into a containing
* {@link NotificationInfos @NotificationInfos} annotation.
*
+ * The {@code @NotificationInfo} and {@code @NotificationInfos} annotations
+ * are ignored on an MBean that is not a {@linkplain JMX#isNotificationSource
+ * notification source} or that implements {@link NotificationBroadcaster} and
+ * returns a non-empty array from its {@link
+ * NotificationBroadcaster#getNotificationInfo() getNotificationInfo()}
+ * method. The {@code NotificationInfo} and {@code NotificationInfos}
* annotations can be applied to the MBean implementation class, or to
* any parent class or interface. These annotations on a class take
@@ -71,7 +88,8 @@ import java.lang.annotation.Target;
* If an MBean does not have these annotations on its class or any
* superclass, then superinterfaces are examined. It is an error for
* more than one superinterface to have these annotations, unless one
- * of them is a child of all the others.
@@ -52,7 +58,11 @@ import java.lang.annotation.Target;
* {@link MBean @MBean}
* {@code @NotificationInfo}(types={"com.example.notifs.create",
* "com.example.notifs.destroy"})
- * public class Cache {...}
+ * public class Cache {
+ * {@code @Resource}
+ * private volatile SendNotification sendNotification;
+ * ...
+ * }
*
*
*
Descriptor constructor taking an XML String.
+ *Descriptor constructor taking an XML String or a + * fieldName=fieldValue format String. The String parameter is + * parsed as XML if it begins with a '<' character.
* *The format of the XML string is not defined, but an * implementation must ensure that the string returned by @@ -244,17 +245,20 @@ public class DescriptorSupport * programmer will have to reset or convert these fields * correctly.
* - * @param inStr An XML-formatted string used to populate this - * Descriptor. The format is not defined, but any + * @param inStr An XML-format or a fieldName=fieldValue formatted string + * used to populate this Descriptor. The XML format is not defined, but any * implementation must ensure that the string returned by * method {@link #toXMLString toXMLString} on an existing * descriptor can be used to instantiate an equivalent * descriptor when instantiated using this constructor. * - * @exception RuntimeOperationsException If the String inStr - * passed in parameter is null + * @exception RuntimeOperationsException If the String inStr passed in + * parameter is null or, when it is not an XML string, if the field name or + * field value is illegal. If inStr is not an XML string then it must + * contain an "=". "fieldValue", "fieldName", and "fieldValue" are illegal. + * FieldName cannot be empty. "fieldName=" will cause the value to be empty. * @exception XMLParseException XML parsing problem while parsing - * the input String + * the XML-format input String * @exception MBeanException Wraps a distributed communication Exception. */ /* At some stage we should rewrite this code to be cleverer. Using @@ -283,14 +287,27 @@ public class DescriptorSupport throw new RuntimeOperationsException(iae, msg); } + // parse parameter string into structures + + init(null); + + if(!inStr.startsWith("<")) { + parseNamesValues(inStr); + if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) { + MODELMBEAN_LOGGER.logp(Level.FINEST, + DescriptorSupport.class.getName(), + "Descriptor(name=value)", "Exit"); + } + return; + } + final String lowerInStr = inStr.toLowerCase(); if (!lowerInStr.startsWith("Options to apply to an MBean proxy or to an instance of {@link * StandardMBean}.
diff --git a/jdk/src/share/classes/javax/management/MBeanAttributeInfo.java b/jdk/src/share/classes/javax/management/MBeanAttributeInfo.java index 2566c3e48a2..b4bcfaf4585 100644 --- a/jdk/src/share/classes/javax/management/MBeanAttributeInfo.java +++ b/jdk/src/share/classes/javax/management/MBeanAttributeInfo.java @@ -186,8 +186,10 @@ public class MBeanAttributeInfo extends MBeanFeatureInfo implements Cloneable { (getter != null), (setter != null), isIs(getter), - ImmutableDescriptor.union(Introspector.descriptorForElement(getter), - Introspector.descriptorForElement(setter))); + ImmutableDescriptor.union(Introspector. + descriptorForElement(getter, false), + Introspector.descriptorForElement(setter, + true))); } /** diff --git a/jdk/src/share/classes/javax/management/MBeanConstructorInfo.java b/jdk/src/share/classes/javax/management/MBeanConstructorInfo.java index 872c723e3af..e3e210318d8 100644 --- a/jdk/src/share/classes/javax/management/MBeanConstructorInfo.java +++ b/jdk/src/share/classes/javax/management/MBeanConstructorInfo.java @@ -67,7 +67,7 @@ public class MBeanConstructorInfo extends MBeanFeatureInfo implements Cloneable public MBeanConstructorInfo(String description, Constructor> constructor) { this(constructor.getName(), description, constructorSignature(constructor), - Introspector.descriptorForElement(constructor)); + Introspector.descriptorForElement(constructor, false)); } /** diff --git a/jdk/src/share/classes/javax/management/MBeanOperationInfo.java b/jdk/src/share/classes/javax/management/MBeanOperationInfo.java index 006fc345d93..c3ee5382612 100644 --- a/jdk/src/share/classes/javax/management/MBeanOperationInfo.java +++ b/jdk/src/share/classes/javax/management/MBeanOperationInfo.java @@ -113,7 +113,7 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable { methodSignature(method), method.getReturnType().getName(), UNKNOWN, - Introspector.descriptorForElement(method)); + Introspector.descriptorForElement(method, false)); } /** diff --git a/jdk/test/javax/management/Introspector/ExceptionsDescriptorTest.java b/jdk/test/javax/management/Introspector/ExceptionsDescriptorTest.java new file mode 100644 index 00000000000..5b931ba7294 --- /dev/null +++ b/jdk/test/javax/management/Introspector/ExceptionsDescriptorTest.java @@ -0,0 +1,245 @@ +/* + * 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 6250014 + * @summary Test that Exceptions are added to the MbeanInfo + * @author Jean-Francois Denise + * @run main/othervm ExceptionsDescriptorTest + */ +import java.lang.management.ManagementFactory; +import java.util.HashSet; +import java.util.Set; +import javax.management.Descriptor; +import javax.management.JMX; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanConstructorInfo; +import javax.management.MBeanInfo; +import javax.management.MBeanOperationInfo; +import javax.management.ObjectName; + +public class ExceptionsDescriptorTest { + + private static final ObjectName OBJECT_NAME = ObjectName.valueOf(":type=Foo"); + final static String EXCEPTION_NAME = Exception.class.getName(); + final static String ILLEGAL_ARGUMENT_EXCEPTION_NAME = + IllegalArgumentException.class.getName(); + final static SetOptions to apply to an MBean proxy or to an instance of {@link * StandardMBean}.
diff --git a/jdk/src/share/classes/javax/management/MBeanServer.java b/jdk/src/share/classes/javax/management/MBeanServer.java index e6d79e5bd94..e82650288bb 100644 --- a/jdk/src/share/classes/javax/management/MBeanServer.java +++ b/jdk/src/share/classes/javax/management/MBeanServer.java @@ -351,11 +351,14 @@ public interface MBeanServer extends MBeanServerConnection { /** *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.
+ * MBeanRegistration#preRegister preRegister} method; or by defining + * an {@code objectNameTemplate} field in its {@link Descriptor}, + * typically using the {@link ObjectNameTemplate @ObjectNameTemplate} + * annotation. * *If this method successfully registers an MBean, a notification * is sent as described above.
diff --git a/jdk/src/share/classes/javax/management/MBeanServerConnection.java b/jdk/src/share/classes/javax/management/MBeanServerConnection.java index fadebc10730..add96cfcb94 100644 --- a/jdk/src/share/classes/javax/management/MBeanServerConnection.java +++ b/jdk/src/share/classes/javax/management/MBeanServerConnection.java @@ -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. + * MBeanRegistration#preRegister preRegister} method; or by defining + * an {@code objectNameTemplate} field in its {@link Descriptor}, + * typically using the {@link ObjectNameTemplate @ObjectNameTemplate} + * annotation. * *This method is equivalent to {@link * #createMBean(String,ObjectName,Object[],String[]) @@ -117,13 +120,16 @@ public interface MBeanServerConnection extends NotificationManager { /** *
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.
+ * MBeanRegistration#preRegister preRegister} method; or by defining + * an {@code objectNameTemplate} field in its {@link Descriptor}, + * typically using the {@link ObjectNameTemplate @ObjectNameTemplate} + * annotation. * *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.
* * @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 + *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.
* * @param className The class name of the MBean to be instantiated. * @param name The object name of the MBean. May be null. diff --git a/jdk/src/share/classes/javax/management/ObjectNameTemplate.java b/jdk/src/share/classes/javax/management/ObjectNameTemplate.java new file mode 100644 index 00000000000..97e0c900fb3 --- /dev/null +++ b/jdk/src/share/classes/javax/management/ObjectNameTemplate.java @@ -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: + *The value of this annotation is used to build the ObjectName
+ * when instances of the annotated type are registered in
+ * an MBeanServer and no explicit name is given to the
+ * {@code createMBean} or {@code registerMBean} method (the {@code ObjectName}
+ * is {@code null}).
For Dynamic MBeans, which define their own {@code MBeanInfo}, you can + * produce the same effect as this annotation by including a field + * {@code objectNameTemplate} + * in the {@link Descriptor} for the {@code MBeanInfo} returned by + * {@link DynamicMBean#getMBeanInfo()}.
+ * + *For Standard MBeans and MXBeans, this annotation automatically produces + * an {@code objectNameTemplate} field in the {@code Descriptor}.
+ * + *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
+ * {attribute name}. For example, to make an MBean name
+ * depend on the Name attribute, use the variable
+ * {Name}. Attribute names are case sensitive.
+ * Naming attributes can be of any type. The String returned by
+ * toString() is included in the constructed name.
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, @ObjectNameTemplate("java.lang:type=MemoryPool,name=\"{Name}\""),
+ * quotes the Name attribute value. You can notice the "\"
+ * character needed to escape a quote within a String. A name
+ * produced by this template might look like
+ * {@code java.lang:type=MemoryPool,name="Code Cache"}.
Variables can be used anywhere in the String.
+ * Be sure to make the template derived name comply with
+ * {@link ObjectName ObjectName} syntax.
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 preRegister method.
+ * Similarly,
+ * if the MBean uses resource
+ * injection to discover its name, it is the computed name that will
+ * be injected.
All of the above can be used with the {@link StandardMBean} class and + * the annotation is effective in that case too.
+ *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
+ * NotCompliantMBeanException.
Some ObjectName template examples: + *
Name attribute is retrieved to compose the name
+ * key value.InstanceName and InstanceId attributes are
+ * retrieved to compose respectively
+ * the name and id key values.ComplexName attribute is retrieved to compose the
+ * name key quoted value.TypeKey attribute is retrieved to compose the
+ * first key name.Domain attribute is retrieved to compose the
+ * management domain.Naming attribute is retrieved to compose the
+ * complete name.Construct an {@code Options} object where all options have @@ -177,15 +178,56 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { this.wrappedVisible = visible; } - // Canonical objects for each of (MXBean,!MXBean) x (WVisible,!WVisible) + /** + *
Defines whether the {@link MBeanRegistration MBeanRegistration} + * callbacks are forwarded to the wrapped object.
+ * + *If this option is true, then + * {@link #preRegister(MBeanServer, ObjectName) preRegister}, + * {@link #postRegister(Boolean) postRegister}, + * {@link #preDeregister preDeregister} and + * {@link #postDeregister postDeregister} methods are forwarded + * to the wrapped object, in addition to the behaviour specified + * for the StandardMBean instance itself. + * The default value is false for compatibility reasons, but true + * is a better value for most new code.
+ * + * @return true if theMBeanRegistration callbacks
+ * are forwarded to the wrapped object.
+ */
+ public boolean isMBeanRegistrationForwarded() {
+ return this.forwardRegistration;
+ }
+
+ /**
+ * Set the + * {@link #isMBeanRegistrationForwarded MBeanRegistrationForwarded} + * option to the given value.
+ * @param forward the new value. + */ + public void setMBeanRegistrationForwarded(boolean forward) { + this.forwardRegistration = forward; + } + + // Canonical objects for each of + // (MXBean,!MXBean) x (WVisible,!WVisible) x (Forward,!Forward) private static final Options[] CANONICALS = { new Options(), new Options(), new Options(), new Options(), + new Options(), new Options(), new Options(), new Options(), }; static { CANONICALS[1].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT); CANONICALS[2].setWrappedObjectVisible(true); CANONICALS[3].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT); CANONICALS[3].setWrappedObjectVisible(true); + CANONICALS[4].setMBeanRegistrationForwarded(true); + CANONICALS[5].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT); + CANONICALS[5].setMBeanRegistrationForwarded(true); + CANONICALS[6].setWrappedObjectVisible(true); + CANONICALS[6].setMBeanRegistrationForwarded(true); + CANONICALS[7].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT); + CANONICALS[7].setWrappedObjectVisible(true); + CANONICALS[7].setMBeanRegistrationForwarded(true); } @Override MBeanOptions[] canonicals() { @@ -195,7 +237,8 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { @Override boolean same(MBeanOptions opts) { return (super.same(opts) && opts instanceof Options && - ((Options) opts).wrappedVisible == wrappedVisible); + ((Options) opts).wrappedVisible == wrappedVisible && + ((Options) opts).forwardRegistration ==forwardRegistration); } } @@ -477,7 +520,9 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { * * @exception IllegalArgumentException if the given * implementation is null. - * + * @exception IllegalStateException if the + * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded} + * option is true. * @exception NotCompliantMBeanException if the given * implementation does not implement the * Standard MBean (or MXBean) interface that was @@ -490,6 +535,12 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { if (implementation == null) throw new IllegalArgumentException("implementation is null"); + + if(options instanceof Options && + ((Options) options).isMBeanRegistrationForwarded()) + throw new IllegalStateException("Implementation can't be changed " + + "because MBeanRegistrationForwarded option is true"); + setImplementation2(implementation); } @@ -1273,10 +1324,14 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { * registered in the MBean server. * *The default implementation of this method returns the {@code name} - * parameter. It does nothing else for - * Standard MBeans. For MXBeans, it records the {@code MBeanServer} - * and {@code ObjectName} parameters so they can be used to translate - * inter-MXBean references.
+ * parameter. If the + * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded} + * option is set to true, then this method is forwarded to the object + * returned by the {@link #getImplementation getImplementation()} method. + * The name returned by this call is then returned by this method. + * It does nothing else for Standard MBeans. For MXBeans, it records + * the {@code MBeanServer} and {@code ObjectName} parameters so they can + * be used to translate inter-MXBean references. * *It is good practice for a subclass that overrides this method * to call the overridden method via {@code super.preRegister(...)}. @@ -1311,6 +1366,11 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { */ public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { + // Forward preRegister before to call register and + // inject parameters. + if(shouldForwardMBeanRegistration()) + name = ((MBeanRegistration)getImplementation()). + preRegister(server, name); mbean.register(server, name); MBeanInjector.inject(mbean.getWrappedObject(), server, name); return name; @@ -1320,7 +1380,11 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { *
Allows the MBean to perform any operations needed after having been * registered in the MBean server or after the registration has failed.
* - *The default implementation of this method does nothing for + *
If the + * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded} + * option is set to true, then this method is forwarded to the object + * returned by the {@link #getImplementation getImplementation()} method. + * The default implementation of this method does nothing else for * Standard MBeans. For MXBeans, it undoes any work done by * {@link #preRegister preRegister} if registration fails.
* @@ -1338,16 +1402,24 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { public void postRegister(Boolean registrationDone) { if (!registrationDone) mbean.unregister(); + if(shouldForwardMBeanRegistration()) + ((MBeanRegistration)getImplementation()). + postRegister(registrationDone); } /** *Allows the MBean to perform any operations it needs before * being unregistered by the MBean server.
* - *The default implementation of this method does nothing.
+ *If the + * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded} + * option is set to true, then this method is forwarded to the object + * returned by the {@link #getImplementation getImplementation()} method. + * Other than that, the default implementation of this method does nothing. + *
* *It is good practice for a subclass that overrides this method - * to call the overridden method via {@code super.preDeegister(...)}.
+ * to call the overridden method via {@code super.preDeregister(...)}. * * @throws Exception no checked exceptions are throw by this method * but {@code Exception} is declared so that subclasses can override @@ -1356,13 +1428,19 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { * @since 1.6 */ public void preDeregister() throws Exception { + if(shouldForwardMBeanRegistration()) + ((MBeanRegistration)getImplementation()).preDeregister(); } /** *Allows the MBean to perform any operations needed after having been * unregistered in the MBean server.
* - *The default implementation of this method does nothing for + *
If the + * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded} + * option is set to true, then this method is forwarded to the object + * returned by the {@link #getImplementation getImplementation()} method. + * The default implementation of this method does nothing else for * Standard MBeans. For MXBeans, it removes any information that * was recorded by the {@link #preRegister preRegister} method.
* @@ -1375,8 +1453,15 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { */ public void postDeregister() { mbean.unregister(); + if(shouldForwardMBeanRegistration()) + ((MBeanRegistration)getImplementation()).postDeregister(); } + private boolean shouldForwardMBeanRegistration() { + return (getImplementation() instanceof MBeanRegistration) && + (options instanceof Options && + ((Options) options).isMBeanRegistrationForwarded()); + } // // MBeanInfo immutability // diff --git a/jdk/src/share/classes/javax/management/monitor/MonitorNotification.java b/jdk/src/share/classes/javax/management/monitor/MonitorNotification.java index 744d7434f1f..f0d65c6da17 100644 --- a/jdk/src/share/classes/javax/management/monitor/MonitorNotification.java +++ b/jdk/src/share/classes/javax/management/monitor/MonitorNotification.java @@ -201,7 +201,7 @@ public class MonitorNotification extends javax.management.Notification { * @param derGauge The derived gauge. * @param trigger The threshold/string (depending on the monitor type) that triggered the notification. */ - MonitorNotification(String type, Object source, long sequenceNumber, long timeStamp, String msg, + public MonitorNotification(String type, Object source, long sequenceNumber, long timeStamp, String msg, ObjectName obsObj, String obsAtt, Object derGauge, Object trigger) { super(type, source, sequenceNumber, timeStamp, msg); diff --git a/jdk/test/javax/management/monitor/InstantiateMonitorNotificationTest.java b/jdk/test/javax/management/monitor/InstantiateMonitorNotificationTest.java new file mode 100644 index 00000000000..ae16858d241 --- /dev/null +++ b/jdk/test/javax/management/monitor/InstantiateMonitorNotificationTest.java @@ -0,0 +1,52 @@ + +import javax.management.ObjectName; +import javax.management.monitor.MonitorNotification; + +/* + * 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 + * @bug 6373143 + * @summary Test MonitorNotification public constructor + * @author JFDenise + * @run clean InstantiateMonitorNotificationTest + * @run build InstantiateMonitorNotificationTest + * @run main InstantiateMonitorNotificationTest + */ + +public class InstantiateMonitorNotificationTest { + + public static void main(String[] args) throws Exception { + MonitorNotification notif = new MonitorNotification("com.foo.test", + ObjectName.valueOf(":type=Monitor"), + 999, + 999, + "A message", + ObjectName.valueOf(":type=Observed"), + "MyAttribute", + Integer.valueOf(14), + Integer.valueOf(15)); + System.out.println("Test passed"); + } +} diff --git a/jdk/test/javax/management/standardmbean/RegistrationTest.java b/jdk/test/javax/management/standardmbean/RegistrationTest.java new file mode 100644 index 00000000000..9ca0c464f00 --- /dev/null +++ b/jdk/test/javax/management/standardmbean/RegistrationTest.java @@ -0,0 +1,91 @@ +/* + * 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 + * @bug 6450834 + * @summary Forward MBeanRegistration calls + * @author JF Denise + * @run main RegistrationTest + */ + +import java.io.Serializable; +import java.lang.management.ManagementFactory; +import javax.management.*; + +public class RegistrationTest { + static boolean preRegisterCalled; + static boolean postRegisterCalled; + static boolean preDeregisterCalled; + static boolean postDeregisterCalled; + + static void checkResult(boolean expected) throws Exception { + if((preRegisterCalled != expected || + postRegisterCalled != expected || + preDeregisterCalled != expected || + postDeregisterCalled != expected)) + throw new Exception("Mismatch preRegisterCalled = " + + preRegisterCalled + ", postRegisterCalled = " + + postRegisterCalled + ", preDeregisterCalled = " + + preDeregisterCalled + ", postDeregisterCalled = " + + postDeregisterCalled); + } + static class Wrapped implements MBeanRegistration,Serializable { + + public ObjectName preRegister(MBeanServer server, ObjectName name) + throws Exception { + preRegisterCalled = true; + return name; + } + + public void postRegister(Boolean registrationDone) { + postRegisterCalled = true; + } + + public void preDeregister() throws Exception { + preDeregisterCalled = true; + } + + public void postDeregister() { + postDeregisterCalled = true; + } + + } + + public static void main(String[] args) throws Exception { + StandardMBean std = new StandardMBean(new Wrapped(), + Serializable.class); + ObjectName name = ObjectName.valueOf(":type=Test"); + ManagementFactory.getPlatformMBeanServer().registerMBean(std,name); + ManagementFactory.getPlatformMBeanServer().unregisterMBean(name); + checkResult(false); + StandardMBean.Options opt = new StandardMBean.Options(); + opt.setMBeanRegistrationForwarded(true); + std = new StandardMBean(new Wrapped(), + Serializable.class, opt ); + ManagementFactory.getPlatformMBeanServer().registerMBean(std,name); + ManagementFactory.getPlatformMBeanServer().unregisterMBean(name); + checkResult(true); + System.out.println("Test OK"); + } +} From 85e1e1e290ef9d63bc05988e8796cce21826d7f3 Mon Sep 17 00:00:00 2001 From: Jean-Francois DeniseMethods
+ * located in the mbeanInterface MBean interface that
+ * correspond to the attr MBeanAttributeInfo
+ * parameter.
+ * @param mbeanInterface the management interface.
+ * Can be a standard MBean or MXBean interface, or a Java class
+ * annotated with {@link MBean @MBean} or {@link MXBean @MXBean}.
+ * @param attr The attribute we want the accessors for.
+ * @return The set of accessors.
+ * @throws java.lang.NoSuchMethodException if no accessor exists
+ * for the given {@link MBeanAttributeInfo MBeanAttributeInfo}.
+ * @throws java.lang.IllegalArgumentException if at least one
+ * of the two parameters is null.
+ * @throws java.lang.ClassNotFoundException if the class named in the
+ * attribute type is not found.
+ * @throws java.lang.SecurityException if this exception is
+ * encountered while introspecting the MBean interface.
+ */
+ public static SetMethod
+ * located in the mbeanInterface MBean interface that
+ * corresponds to the provided op
+ * MBeanOperationInfo parameter.
+ * @param mbeanInterface the management interface.
+ * Can be a standard MBean or MXBean interface, or a Java class
+ * annotated with {@link MBean @MBean} or {@link MXBean @MXBean}.
+ * @param op The operation we want the method for.
+ * @return the method corresponding to the provided MBeanOperationInfo.
+ * @throws java.lang.NoSuchMethodException if no method exists
+ * for the given {@link MBeanOperationInfo MBeanOperationInfo}.
+ * @throws java.lang.IllegalArgumentException if at least one
+ * of the two parameters is null.
+ * @throws java.lang.ClassNotFoundException if one of the
+ * classes named in the operation signature array is not found.
+ * @throws java.lang.SecurityException if this exception is
+ * encountered while introspecting the MBean interface.
+ */
+ public static Method findOperationMethod(Class> mbeanInterface,
+ MBeanOperationInfo op)
+ throws ClassNotFoundException, NoSuchMethodException {
+ if (mbeanInterface == null || op == null) {
+ throw new IllegalArgumentException("mbeanInterface or op " +
+ "parameter is null");
+ }
+ ListAllows the MBean to perform any operations it needs before
* being registered in the MBean server. If the name of the MBean
diff --git a/jdk/test/javax/management/standardmbean/FindMethodTest.java b/jdk/test/javax/management/standardmbean/FindMethodTest.java
new file mode 100644
index 00000000000..b568d70ac88
--- /dev/null
+++ b/jdk/test/javax/management/standardmbean/FindMethodTest.java
@@ -0,0 +1,384 @@
+/*
+ * 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
+ * @bug 6287328
+ * @summary Add methods to StandardMBean to retrieve a method based on
+ * MBean{Attribute|Operation}Info
+ * @author Jean-Francois Denise
+ * @run main FindMethodTest
+ */
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+import java.lang.management.ThreadMXBean;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.management.MBean;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.MBeanServer;
+import javax.management.ManagedAttribute;
+import javax.management.ManagedOperation;
+import javax.management.ObjectName;
+import javax.management.StandardMBean;
+
+public class FindMethodTest {
+
+ private static MBeanServer server =
+ ManagementFactory.getPlatformMBeanServer();
+
+ private static Map (Listeners may be invoked in the same thread as the caller of
+ * {@code sender.sendNotification}.) A field to be injected must not be static. It is recommended that
* such fields be declared {@code volatile}.name,
+ * Additionally, for each MBean n that matches name,
* if the caller's permissions do not imply {@link
* MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
- * MBeanPermission(mbeanServerName, className, null, name, "queryMBeans")}, the
- * MBean server will behave as if that MBean did not exist.
Certain query elements perform operations on the MBean server. * If the caller does not have the required permissions for a given diff --git a/jdk/src/share/classes/javax/management/event/EventClient.java b/jdk/src/share/classes/javax/management/event/EventClient.java index a2f6bc617fe..2688b94937f 100644 --- a/jdk/src/share/classes/javax/management/event/EventClient.java +++ b/jdk/src/share/classes/javax/management/event/EventClient.java @@ -187,9 +187,10 @@ public class EventClient implements EventConsumer, NotificationManager { * forwarded by the {@link EventClientDelegateMBean}. If {@code null}, a * {@link FetchingEventRelay} object will be used. * @param distributingExecutor Used to distribute notifications to local - * listeners. If {@code null}, the thread that calls {@link - * EventReceiver#receive EventReceiver.receive} from the {@link EventRelay} - * object is used. + * listeners. Only one job at a time will be submitted to this Executor. + * If {@code distributingExecutor} is {@code null}, the thread that calls + * {@link EventReceiver#receive EventReceiver.receive} from the {@link + * EventRelay} object is used. * @param leaseScheduler An object that will be used to schedule the * periodic {@linkplain EventClientDelegateMBean#lease lease updates}. * If {@code null}, a default scheduler will be used. @@ -545,7 +546,7 @@ public class EventClient implements EventConsumer, NotificationManager { * *
The method returns the listeners which were added successfully. The * elements in the returned collection are a subset of the elements in - * {@code infoList}. If all listeners were added successfully, the two + * {@code listeners}. If all listeners were added successfully, the two * collections are the same. If no listener was added successfully, the * returned collection is empty.
* diff --git a/jdk/src/share/classes/javax/management/event/FetchingEventRelay.java b/jdk/src/share/classes/javax/management/event/FetchingEventRelay.java index e4c8d81d87b..cbec8aa82be 100644 --- a/jdk/src/share/classes/javax/management/event/FetchingEventRelay.java +++ b/jdk/src/share/classes/javax/management/event/FetchingEventRelay.java @@ -39,10 +39,18 @@ import javax.management.MBeanException; import javax.management.remote.NotificationResult; /** - * This class is an implementation of the {@link EventRelay} interface. It calls + *This class is an implementation of the {@link EventRelay} interface. It calls * {@link EventClientDelegateMBean#fetchNotifications * fetchNotifications(String, long, int, long)} to get - * notifications and then forwards them to an {@link EventReceiver} object. + * notifications and then forwards them to an {@link EventReceiver} object.
+ * + *A {@code fetchExecutor} parameter can be specified when creating a + * {@code FetchingEventRelay}. That is then the {@code Executor} that will + * be used to perform the {@code fetchNotifications} operation. Only one + * job at a time will be submitted to this {@code Executor}. The behavior + * is unspecified if {@link Executor#execute} throws an exception, including + * {@link java.util.concurrent.RejectedExecutionException + * RejectedExecutionException}. * * @since JMX 2.0 */