8080663: Use sun.misc.SharedSecrets to allow access from java.management to @ConstructorProperties
authorjbachorik
Tue, 26 May 2015 11:57:51 +0200
changeset 30906 1b67cbb0adce
parent 30806 6e9d62b1dbc3
child 30907 c064fa28311d
child 31064 49d006561bec
8080663: Use sun.misc.SharedSecrets to allow access from java.management to @ConstructorProperties Reviewed-by: alanb, mchung, dfuchs
jdk/src/java.base/share/classes/sun/misc/JavaBeansAccess.java
jdk/src/java.base/share/classes/sun/misc/JavaBeansIntrospectorAccess.java
jdk/src/java.base/share/classes/sun/misc/SharedSecrets.java
jdk/src/java.desktop/share/classes/java/beans/Introspector.java
jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java
jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/Introspector.java
jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/JavaBeansAccessor.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/misc/JavaBeansAccess.java	Tue May 26 11:57:51 2015 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, 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 sun.misc;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+public interface JavaBeansAccess {
+    /**
+     * Returns the getter method for a property of the given name
+     * @param clazz The JavaBeans class
+     * @param property The property name
+     * @return The resolved property getter method
+     * @throws Exception
+     */
+    Method getReadMethod(Class<?> clazz, String property) throws Exception;
+
+    /**
+     * Return the <b>value</b> attribute of the associated
+     * <code>@ConstructorProperties</code> annotation if that is present.
+     * @param ctr The constructor to extract the annotation value from
+     * @return The {@code value} attribute of the <code>@ConstructorProperties</code>
+     *         annotation or {@code null} if the constructor is not annotated by
+     *         this annotation or the annotation is not accessible.
+     */
+    String[] getConstructorPropertiesValue(Constructor<?> ctr);
+}
--- a/jdk/src/java.base/share/classes/sun/misc/JavaBeansIntrospectorAccess.java	Thu May 21 17:11:55 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2014, 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 sun.misc;
-
-import java.lang.reflect.Method;
-
-public interface JavaBeansIntrospectorAccess {
-    Method getReadMethod(Class<?> clazz, String property) throws Exception;
-}
--- a/jdk/src/java.base/share/classes/sun/misc/SharedSecrets.java	Thu May 21 17:11:55 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/misc/SharedSecrets.java	Tue May 26 11:57:51 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -56,7 +56,7 @@
     private static JavaUtilZipFileAccess javaUtilZipFileAccess;
     private static JavaAWTAccess javaAWTAccess;
     private static JavaAWTFontAccess javaAWTFontAccess;
-    private static JavaBeansIntrospectorAccess javaBeansIntrospectorAccess;
+    private static JavaBeansAccess javaBeansAccess;
 
     public static JavaUtilJarAccess javaUtilJarAccess() {
         if (javaUtilJarAccess == null) {
@@ -194,11 +194,11 @@
         return javaAWTFontAccess;
     }
 
-    public static JavaBeansIntrospectorAccess getJavaBeansIntrospectorAccess() {
-        return javaBeansIntrospectorAccess;
+    public static JavaBeansAccess getJavaBeansAccess() {
+        return javaBeansAccess;
     }
 
-    public static void setJavaBeansIntrospectorAccess(JavaBeansIntrospectorAccess access) {
-        javaBeansIntrospectorAccess = access;
+    public static void setJavaBeansAccess(JavaBeansAccess access) {
+        javaBeansAccess = access;
     }
 }
--- a/jdk/src/java.desktop/share/classes/java/beans/Introspector.java	Thu May 21 17:11:55 2015 -0700
+++ b/jdk/src/java.desktop/share/classes/java/beans/Introspector.java	Tue May 26 11:57:51 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -35,16 +35,19 @@
 
 import java.lang.ref.Reference;
 import java.lang.ref.SoftReference;
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
 
 import java.util.Map;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.EventObject;
 import java.util.List;
 import java.util.TreeMap;
+import sun.misc.JavaBeansAccess;
 
 import sun.misc.SharedSecrets;
 import sun.reflect.misc.ReflectUtil;
@@ -146,15 +149,25 @@
 
     // register with SharedSecrets for JMX usage
     static {
-        SharedSecrets.setJavaBeansIntrospectorAccess((clazz, property) -> {
-            BeanInfo bi = Introspector.getBeanInfo(clazz);
-            PropertyDescriptor[] pds = bi.getPropertyDescriptors();
-            for (PropertyDescriptor pd: pds) {
-                if (pd.getName().equals(property)) {
-                    return pd.getReadMethod();
+        SharedSecrets.setJavaBeansAccess(new JavaBeansAccess() {
+            @Override
+            public Method getReadMethod(Class<?> clazz, String property) throws Exception {
+                BeanInfo bi = Introspector.getBeanInfo(clazz);
+                PropertyDescriptor[] pds = bi.getPropertyDescriptors();
+                for (PropertyDescriptor pd: pds) {
+                    if (pd.getName().equals(property)) {
+                        return pd.getReadMethod();
+                    }
                 }
+                return null;
             }
-            return null;
+
+            @Override
+            public String[] getConstructorPropertiesValue(Constructor<?> ctr) {
+                ConstructorProperties cp = ctr.getAnnotation(ConstructorProperties.class);
+                String [] ret = cp != null ? cp.value() : null;
+                return ret;
+            }
         });
     }
 
--- a/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java	Thu May 21 17:11:55 2015 -0700
+++ b/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java	Tue May 26 11:57:51 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, 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
@@ -33,14 +33,12 @@
 import com.sun.jmx.remote.util.EnvHelp;
 
 import java.io.InvalidObjectException;
-import java.lang.annotation.Annotation;
 import java.lang.annotation.ElementType;
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Array;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.GenericArrayType;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.ParameterizedType;
@@ -1138,55 +1136,13 @@
         to getters.  */
     private static final class CompositeBuilderViaConstructor
             extends CompositeBuilder {
-        static class AnnotationHelper {
-            private static Class<? extends Annotation> constructorPropertiesClass;
-            private static Method valueMethod;
-            static {
-                findConstructorPropertiesClass();
-            }
-
-            @SuppressWarnings("unchecked")
-            private static void findConstructorPropertiesClass() {
-                try {
-                    constructorPropertiesClass = (Class<? extends Annotation>)
-                        Class.forName("java.beans.ConstructorProperties", false,
-                                      DefaultMXBeanMappingFactory.class.getClassLoader());
-                    valueMethod = constructorPropertiesClass.getMethod("value");
-                } catch (ClassNotFoundException cnf) {
-                    // java.beans not present
-                } catch (NoSuchMethodException e) {
-                    // should not reach here
-                    throw new InternalError(e);
-                }
-            }
-
-            static boolean isAvailable() {
-                return constructorPropertiesClass != null;
-            }
-
-            static String[] getPropertyNames(Constructor<?> constr) {
-                if (!isAvailable())
-                    return null;
-
-                Annotation a = constr.getAnnotation(constructorPropertiesClass);
-                if (a == null) return null;
-
-                try {
-                    return (String[]) valueMethod.invoke(a);
-                } catch (InvocationTargetException e) {
-                    throw new InternalError(e);
-                } catch (IllegalAccessException e) {
-                    throw new InternalError(e);
-                }
-            }
-        }
 
         CompositeBuilderViaConstructor(Class<?> targetClass, String[] itemNames) {
             super(targetClass, itemNames);
         }
 
         String applicable(Method[] getters) throws InvalidObjectException {
-            if (!AnnotationHelper.isAvailable())
+            if (!JavaBeansAccessor.isAvailable())
                 return "@ConstructorProperties annotation not available";
 
             Class<?> targetClass = getTargetClass();
@@ -1196,7 +1152,7 @@
             List<Constructor<?>> annotatedConstrList = newList();
             for (Constructor<?> constr : constrs) {
                 if (Modifier.isPublic(constr.getModifiers())
-                        && AnnotationHelper.getPropertyNames(constr) != null)
+                        && JavaBeansAccessor.getConstructorPropertiesValue(constr) != null)
                     annotatedConstrList.add(constr);
             }
 
@@ -1225,7 +1181,7 @@
             // so we can test unambiguity.
             Set<BitSet> getterIndexSets = newSet();
             for (Constructor<?> constr : annotatedConstrList) {
-                String[] propertyNames = AnnotationHelper.getPropertyNames(constr);
+                String[] propertyNames = JavaBeansAccessor.getConstructorPropertiesValue(constr);
 
                 Type[] paramTypes = constr.getGenericParameterTypes();
                 if (paramTypes.length != propertyNames.length) {
--- a/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/Introspector.java	Thu May 21 17:11:55 2015 -0700
+++ b/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/Introspector.java	Tue May 26 11:57:51 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -56,7 +56,7 @@
 import javax.management.AttributeNotFoundException;
 import javax.management.openmbean.CompositeData;
 
-import sun.misc.JavaBeansIntrospectorAccess;
+import sun.misc.JavaBeansAccess;
 import sun.misc.SharedSecrets;
 import sun.reflect.misc.MethodUtil;
 import sun.reflect.misc.ReflectUtil;
@@ -552,10 +552,8 @@
                 // Java Beans introspection
                 //
                 Class<?> clazz = complex.getClass();
-                Method readMethod;
-                if (BeansIntrospector.isAvailable()) {
-                    readMethod = BeansIntrospector.getReadMethod(clazz, element);
-                } else {
+                Method readMethod = JavaBeansAccessor.getReadMethod(clazz, element);
+                if (readMethod == null) {
                     // Java Beans not available so use simple introspection
                     // to locate method
                     readMethod = SimpleIntrospector.getReadMethod(clazz, element);
@@ -580,30 +578,6 @@
     }
 
     /**
-     * Provides access to java.beans.Introspector if available.
-     */
-    private static class BeansIntrospector {
-        private static final JavaBeansIntrospectorAccess JBIA;
-        static {
-            // ensure that java.beans.Introspector is initialized (if present)
-            try {
-                Class.forName("java.beans.Introspector", true,
-                              BeansIntrospector.class.getClassLoader());
-            } catch (ClassNotFoundException ignore) { }
-
-            JBIA = SharedSecrets.getJavaBeansIntrospectorAccess();
-        }
-
-        static boolean isAvailable() {
-            return JBIA != null;
-        }
-
-        static Method getReadMethod(Class<?> clazz, String property) throws Exception {
-            return JBIA.getReadMethod(clazz, property);
-        }
-    }
-
-    /**
      * A simple introspector that uses reflection to analyze a class and
      * identify its "getter" methods. This class is intended for use only when
      * Java Beans is not present (which implies that there isn't explicit
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/JavaBeansAccessor.java	Tue May 26 11:57:51 2015 +0200
@@ -0,0 +1,78 @@
+/*
+ * 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.  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 com.sun.jmx.mbeanserver;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import sun.misc.JavaBeansAccess;
+import sun.misc.SharedSecrets;
+
+/**
+ * A centralized place for gaining access to java.beans related functionality -
+ * if available.
+ */
+class JavaBeansAccessor {
+    static {
+        // ensure that java.beans.Introspector is initialized (if present)
+        // it will fill in the SharedSecrets
+        try {
+            Class.forName("java.beans.Introspector", true,
+                          JavaBeansAccessor.class.getClassLoader());
+        } catch (ClassNotFoundException ignore) { }
+    }
+
+    private static JavaBeansAccess getJavaBeansAccess() {
+        return SharedSecrets.getJavaBeansAccess();
+    }
+
+    static boolean isAvailable() {
+        return getJavaBeansAccess() != null;
+    }
+
+    /**
+     * Returns the getter method for a property of the given name
+     * @param clazz The JavaBeans class
+     * @param property The property name
+     * @return The resolved property getter name or null
+     * @throws Exception
+     */
+    static Method getReadMethod(Class<?> clazz, String property) throws Exception {
+        JavaBeansAccess jba = getJavaBeansAccess();
+        return jba != null ? jba.getReadMethod(clazz, property) : null;
+    }
+
+    /**
+     * Return the <b>value</b> attribute of the associated
+     * <code>@ConstructorProperties</code> annotation if that is present.
+     * @param ctr The constructor to extract the annotation value from
+     * @return The {@code value} attribute of the <code>@ConstructorProperties</code>
+     *         annotation or {@code null} if the constructor is not annotated by
+     *         this annotation or the annotation is not accessible.
+     */
+    static String[] getConstructorPropertiesValue(Constructor<?> ctr) {
+        JavaBeansAccess jba = getJavaBeansAccess();
+        return jba != null ? jba.getConstructorPropertiesValue(ctr) : null;
+    }
+}