# HG changeset patch # User jbachorik # Date 1443011102 -7200 # Node ID d2a313368ccbaa1a3ce8276ead68461d08a7593e # Parent 8db7e6cffaf4d024e64dc2c25056ccb913c85b67 7199353: Define ConstructorProperties annotation type for MXBeans Reviewed-by: duke diff -r 8db7e6cffaf4 -r d2a313368ccb jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java --- a/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java Thu Oct 08 09:40:31 2015 +0200 +++ b/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java Wed Sep 23 14:25:02 2015 +0200 @@ -60,6 +60,7 @@ import javax.management.JMX; import javax.management.ObjectName; +import javax.management.ConstructorProperties; import javax.management.openmbean.ArrayType; import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeDataInvocationHandler; @@ -1141,10 +1142,19 @@ super(targetClass, itemNames); } + private String[] getConstPropValues(Constructor ctr) { + // is constructor annotated by javax.management.ConstructorProperties ? + ConstructorProperties ctrProps = ctr.getAnnotation(ConstructorProperties.class); + if (ctrProps != null) { + return ctrProps.value(); + } else { + // try the legacy java.beans.ConstructorProperties annotation + String[] vals = JavaBeansAccessor.getConstructorPropertiesValue(ctr); + return vals; + } + } + String applicable(Method[] getters) throws InvalidObjectException { - if (!JavaBeansAccessor.isAvailable()) - return "@ConstructorProperties annotation not available"; - Class targetClass = getTargetClass(); Constructor[] constrs = targetClass.getConstructors(); @@ -1152,7 +1162,7 @@ List> annotatedConstrList = newList(); for (Constructor constr : constrs) { if (Modifier.isPublic(constr.getModifiers()) - && JavaBeansAccessor.getConstructorPropertiesValue(constr) != null) + && getConstPropValues(constr) != null) annotatedConstrList.add(constr); } @@ -1181,7 +1191,7 @@ // so we can test unambiguity. Set getterIndexSets = newSet(); for (Constructor constr : annotatedConstrList) { - String[] propertyNames = JavaBeansAccessor.getConstructorPropertiesValue(constr); + String[] propertyNames = getConstPropValues(constr); Type[] paramTypes = constr.getGenericParameterTypes(); if (paramTypes.length != propertyNames.length) { diff -r 8db7e6cffaf4 -r d2a313368ccb jdk/src/java.management/share/classes/javax/management/ConstructorProperties.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.management/share/classes/javax/management/ConstructorProperties.java Wed Sep 23 14:25:02 2015 +0200 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2006, 2015 Oracle and/or its affiliates. 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.management; + +import java.lang.annotation.*; +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +/** + *

+ * An annotation on a constructor that shows how the parameters of + * that constructor correspond to the constructed object's getter + * methods. For example: +*

+ *
+ *
+ *         public class MemoryUsage {
+ *             // standard JavaBean conventions with getters
+ *             @ConstructorProperties({"init", "used", "committed", "max"})
+ *             public MemoryUsage(long init, long used,
+ *                                long committed, long max) {...}
+ *             long getInit() {...}
+ *             long getUsed() {...}
+ *             long getCommitted() {...}
+ *             long getMax() {...}
+ *         }
+ *     
+ *
+ *

+ * The annotation shows that the first parameter of the constructor + * can be retrieved with the {@code getInit()} method, the second one with + * the {@code getUsed()} method, and so on. Since parameter names are not in + * general available at runtime, without the annotation there would be + * no way of knowing which parameter corresponds to which property. + *

+ *

+ * If a constructor is annotated by the both {@code @java.beans.ConstructorProperties} + * and {@code @javax.management.annotation.ConstructorProperties} annotations + * the JMX introspection will give an absolute precedence to the later one. + *

+ * + * @since 1.9 + */ +@Documented @Target(CONSTRUCTOR) @Retention(RUNTIME) +public @interface ConstructorProperties { + /** +

The getter names.

+ @return the getter names corresponding to the parameters in the + annotated constructor. + */ + String[] value(); +} diff -r 8db7e6cffaf4 -r d2a313368ccb jdk/src/java.management/share/classes/javax/management/MXBean.java --- a/jdk/src/java.management/share/classes/javax/management/MXBean.java Thu Oct 08 09:40:31 2015 +0200 +++ b/jdk/src/java.management/share/classes/javax/management/MXBean.java Wed Sep 23 14:25:02 2015 +0200 @@ -168,8 +168,8 @@

The definitions are the same in the two cases, except that with the MXBean, MemoryUsage no longer needs to be marked Serializable (though it can be). On - the other hand, we have added a {@code @ConstructorProperties} annotation - to link the constructor parameters to the corresponding getters. + the other hand, we have added a {@link ConstructorProperties @ConstructorProperties} + annotation to link the constructor parameters to the corresponding getters. We will see more about this below.

MemoryUsage is a model-specific class. @@ -850,10 +850,16 @@ J.

  • Otherwise, if J has at least one public - constructor with a {@link java.beans.ConstructorProperties - ConstructorProperties} annotation, then one - of those constructors (not necessarily always the same one) - will be called to reconstruct an instance of J. + constructor with either {@link javax.management.ConstructorProperties + @javax.management.ConstructorProperties} or + {@code @java.beans.ConstructoProperties} annotation, then one of those + constructors (not necessarily always the same one) will be called to + reconstruct an instance of J. + If a constructor is annotated with both + {@code @javax.management.ConstructorProperties} and + {@code @java.beans.ConstructorProperties}, + {@code @javax.management.ConstructorProperties} will be used and + {@code @java.beans.ConstructorProperties} will be ignored. Every such annotation must list as many strings as the constructor has parameters; each string must name a property corresponding to a getter of J; and the type of this @@ -909,8 +915,9 @@

  • Otherwise, J is not reconstructible.

  • -

    Rule 2 is not applicable to subset Profiles of Java SE that do not - include the {@code java.beans} package. When targeting a runtime that does +

    When {@code @java.beans.ConstructorProperties} is used then rule 2 is not + applicable to subset Profiles of Java SE that do not include the + {@code java.beans} package. When targeting a runtime that does not include the {@code java.beans} package, and where there is a mismatch between the compile-time and runtime environment whereby J is compiled with a public constructor and the {@code ConstructorProperties} diff -r 8db7e6cffaf4 -r d2a313368ccb jdk/test/javax/management/Introspector/AnnotationSecurityTest.java --- a/jdk/test/javax/management/Introspector/AnnotationSecurityTest.java Thu Oct 08 09:40:31 2015 +0200 +++ b/jdk/test/javax/management/Introspector/AnnotationSecurityTest.java Wed Sep 23 14:25:02 2015 +0200 @@ -27,8 +27,7 @@ * @summary Test that having a security manager doesn't trigger a * NotCompliantMBeanException * @author Daniel Fuchs, Yves Joan - * @modules java.desktop - * java.management + * @modules java.management * @run clean AnnotationSecurityTest Described UnDescribed DescribedMBean * UnDescribedMBean SqeDescriptorKey DescribedMX DescribedMXBean * @run build AnnotationSecurityTest Described UnDescribed DescribedMBean @@ -40,13 +39,8 @@ import java.io.File; import java.io.IOException; -import java.lang.annotation.Annotation; import java.lang.management.ManagementFactory; -import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; -import java.lang.reflect.UndeclaredThrowableException; - -import javax.management.JMException; import javax.management.MBeanServer; import javax.management.ObjectName; /** diff -r 8db7e6cffaf4 -r d2a313368ccb jdk/test/javax/management/Introspector/Described.java --- a/jdk/test/javax/management/Introspector/Described.java Thu Oct 08 09:40:31 2015 +0200 +++ b/jdk/test/javax/management/Introspector/Described.java Wed Sep 23 14:25:02 2015 +0200 @@ -25,7 +25,7 @@ * * Used by AnnotationSecurityTest.java **/ -import java.beans.ConstructorProperties; +import javax.management.ConstructorProperties; /** * An MBean used by AnnotationSecurityTest.java diff -r 8db7e6cffaf4 -r d2a313368ccb jdk/test/javax/management/Introspector/DescribedMX.java --- a/jdk/test/javax/management/Introspector/DescribedMX.java Thu Oct 08 09:40:31 2015 +0200 +++ b/jdk/test/javax/management/Introspector/DescribedMX.java Wed Sep 23 14:25:02 2015 +0200 @@ -25,7 +25,7 @@ * * Used by AnnotationSecurityTest.java **/ -import java.beans.ConstructorProperties; +import javax.management.ConstructorProperties; /** * An MXBean used by AnnotationSecurityTest.java diff -r 8db7e6cffaf4 -r d2a313368ccb jdk/test/javax/management/Introspector/LegacyConstructorPropertiesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/management/Introspector/LegacyConstructorPropertiesTest.java Wed Sep 23 14:25:02 2015 +0200 @@ -0,0 +1,105 @@ + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.beans.ConstructorProperties; +import javax.management.MBeanServer; +import javax.management.MBeanServerFactory; +import javax.management.ObjectName; + +/* + * @test + * @bug 7199353 + * @summary Asserts that 'java.beans.ConstructorProperties' annotation is still + * recognized and properly handled for custom types mapped to open types. + * Also, makes sure that if the same constructor is annotated by both + * j.b.ConstructorProperties and j.m.ConstructorProperties annotations + * only j.m.ConstructorProperties annotation is considered. + * @author Jaroslav Bachorik + * @modules java.management + * java.desktop + * @run main LegacyConstructorPropertiesTest + */ + +public class LegacyConstructorPropertiesTest { + public static class CustomType { + private String name; + private int value; + @ConstructorProperties({"name", "value"}) + public CustomType(String name, int value) { + this.name = name; + this.value = value; + } + + // if @java.beans.ConstructorProperties would be used + // the introspector would choke on this + @ConstructorProperties("noname") + @javax.management.ConstructorProperties("name") + public CustomType(String name) { + this.name = name; + this.value = -1; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + } + + public static interface CustomMXBean { + public CustomType getProp(); + public void setProp(CustomType prop); + } + + public static final class Custom implements CustomMXBean { + private CustomType prop; + + @Override + public CustomType getProp() { + return prop; + } + + @Override + public void setProp(CustomType prop) { + this.prop = prop; + } + } + + public static void main(String[] args) throws Exception { + MBeanServer mbs = MBeanServerFactory.createMBeanServer(); + CustomMXBean mbean = new Custom(); + + mbs.registerMBean(mbean, ObjectName.getInstance("test:type=Custom")); + } +} diff -r 8db7e6cffaf4 -r d2a313368ccb jdk/test/javax/management/mxbean/AmbiguousConstructorTest.java --- a/jdk/test/javax/management/mxbean/AmbiguousConstructorTest.java Thu Oct 08 09:40:31 2015 +0200 +++ b/jdk/test/javax/management/mxbean/AmbiguousConstructorTest.java Wed Sep 23 14:25:02 2015 +0200 @@ -26,15 +26,13 @@ * @bug 6175517 6278707 * @summary Test that ambiguous ConstructorProperties annotations are detected. * @author Eamonn McManus - * @modules java.desktop - * java.management + * @modules java.management * @run clean AmbiguousConstructorTest * @run build AmbiguousConstructorTest * @run main AmbiguousConstructorTest */ -import java.beans.ConstructorProperties; -import java.io.InvalidObjectException; +import javax.management.ConstructorProperties; import javax.management.*; public class AmbiguousConstructorTest { diff -r 8db7e6cffaf4 -r d2a313368ccb jdk/test/javax/management/mxbean/ExceptionDiagnosisTest.java --- a/jdk/test/javax/management/mxbean/ExceptionDiagnosisTest.java Thu Oct 08 09:40:31 2015 +0200 +++ b/jdk/test/javax/management/mxbean/ExceptionDiagnosisTest.java Wed Sep 23 14:25:02 2015 +0200 @@ -26,11 +26,10 @@ * @bug 6713777 * @summary Test that exception messages include all relevant information * @author Eamonn McManus - * @modules java.desktop - * java.management + * @modules java.management */ -import java.beans.ConstructorProperties; +import javax.management.ConstructorProperties; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; diff -r 8db7e6cffaf4 -r d2a313368ccb jdk/test/javax/management/mxbean/LeakTest.java --- a/jdk/test/javax/management/mxbean/LeakTest.java Thu Oct 08 09:40:31 2015 +0200 +++ b/jdk/test/javax/management/mxbean/LeakTest.java Wed Sep 23 14:25:02 2015 +0200 @@ -25,8 +25,7 @@ * @bug 6482247 * @summary Test that creating MXBeans does not introduce memory leaks. * @author Eamonn McManus - * @modules java.desktop - * java.management + * @modules java.management * @run build LeakTest RandomMXBeanTest MerlinMXBean TigerMXBean * @run main LeakTest */ diff -r 8db7e6cffaf4 -r d2a313368ccb jdk/test/javax/management/mxbean/MXBeanTest.java --- a/jdk/test/javax/management/mxbean/MXBeanTest.java Thu Oct 08 09:40:31 2015 +0200 +++ b/jdk/test/javax/management/mxbean/MXBeanTest.java Wed Sep 23 14:25:02 2015 +0200 @@ -27,8 +27,7 @@ * @summary General MXBean test. * @author Eamonn McManus * @author Jaroslav Bachorik - * @modules java.desktop - * java.management + * @modules java.management * @run clean MXBeanTest MerlinMXBean TigerMXBean * @run build MXBeanTest MerlinMXBean TigerMXBean * @run main MXBeanTest diff -r 8db7e6cffaf4 -r d2a313368ccb jdk/test/javax/management/mxbean/PropertyNamesTest.java --- a/jdk/test/javax/management/mxbean/PropertyNamesTest.java Thu Oct 08 09:40:31 2015 +0200 +++ b/jdk/test/javax/management/mxbean/PropertyNamesTest.java Wed Sep 23 14:25:02 2015 +0200 @@ -26,14 +26,13 @@ * @bug 6175517 * @summary Test the PropertyNames annotation with MXBeans * @author Eamonn McManus - * @modules java.desktop - * java.management + * @modules java.management * @run clean PropertyNamesTest * @run build PropertyNamesTest * @run main PropertyNamesTest */ -import java.beans.ConstructorProperties; +import javax.management.ConstructorProperties; import java.util.Collections; import java.util.List; import javax.management.JMX; diff -r 8db7e6cffaf4 -r d2a313368ccb jdk/test/javax/management/mxbean/TigerMXBean.java --- a/jdk/test/javax/management/mxbean/TigerMXBean.java Thu Oct 08 09:40:31 2015 +0200 +++ b/jdk/test/javax/management/mxbean/TigerMXBean.java Wed Sep 23 14:25:02 2015 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. 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 @@ -21,7 +21,7 @@ * questions. */ -import java.beans.ConstructorProperties; +import javax.management.ConstructorProperties; import java.util.Arrays; import java.util.Collections; import java.util.HashSet;