1 /* |
1 /* |
2 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
31 import static javax.management.openmbean.SimpleType.*; |
31 import static javax.management.openmbean.SimpleType.*; |
32 |
32 |
33 import com.sun.jmx.remote.util.EnvHelp; |
33 import com.sun.jmx.remote.util.EnvHelp; |
34 |
34 |
35 import java.io.InvalidObjectException; |
35 import java.io.InvalidObjectException; |
36 import java.lang.annotation.Annotation; |
|
37 import java.lang.annotation.ElementType; |
36 import java.lang.annotation.ElementType; |
38 import java.lang.ref.WeakReference; |
37 import java.lang.ref.WeakReference; |
39 import java.lang.reflect.Array; |
38 import java.lang.reflect.Array; |
40 import java.lang.reflect.Constructor; |
39 import java.lang.reflect.Constructor; |
41 import java.lang.reflect.Field; |
40 import java.lang.reflect.Field; |
42 import java.lang.reflect.GenericArrayType; |
41 import java.lang.reflect.GenericArrayType; |
43 import java.lang.reflect.InvocationTargetException; |
|
44 import java.lang.reflect.Method; |
42 import java.lang.reflect.Method; |
45 import java.lang.reflect.Modifier; |
43 import java.lang.reflect.Modifier; |
46 import java.lang.reflect.ParameterizedType; |
44 import java.lang.reflect.ParameterizedType; |
47 import java.lang.reflect.Proxy; |
45 import java.lang.reflect.Proxy; |
48 import java.lang.reflect.Type; |
46 import java.lang.reflect.Type; |
1136 /** Builder for when the target class has a constructor that is |
1134 /** Builder for when the target class has a constructor that is |
1137 annotated with @ConstructorProperties so we can see the correspondence |
1135 annotated with @ConstructorProperties so we can see the correspondence |
1138 to getters. */ |
1136 to getters. */ |
1139 private static final class CompositeBuilderViaConstructor |
1137 private static final class CompositeBuilderViaConstructor |
1140 extends CompositeBuilder { |
1138 extends CompositeBuilder { |
1141 static class AnnotationHelper { |
|
1142 private static Class<? extends Annotation> constructorPropertiesClass; |
|
1143 private static Method valueMethod; |
|
1144 static { |
|
1145 findConstructorPropertiesClass(); |
|
1146 } |
|
1147 |
|
1148 @SuppressWarnings("unchecked") |
|
1149 private static void findConstructorPropertiesClass() { |
|
1150 try { |
|
1151 constructorPropertiesClass = (Class<? extends Annotation>) |
|
1152 Class.forName("java.beans.ConstructorProperties", false, |
|
1153 DefaultMXBeanMappingFactory.class.getClassLoader()); |
|
1154 valueMethod = constructorPropertiesClass.getMethod("value"); |
|
1155 } catch (ClassNotFoundException cnf) { |
|
1156 // java.beans not present |
|
1157 } catch (NoSuchMethodException e) { |
|
1158 // should not reach here |
|
1159 throw new InternalError(e); |
|
1160 } |
|
1161 } |
|
1162 |
|
1163 static boolean isAvailable() { |
|
1164 return constructorPropertiesClass != null; |
|
1165 } |
|
1166 |
|
1167 static String[] getPropertyNames(Constructor<?> constr) { |
|
1168 if (!isAvailable()) |
|
1169 return null; |
|
1170 |
|
1171 Annotation a = constr.getAnnotation(constructorPropertiesClass); |
|
1172 if (a == null) return null; |
|
1173 |
|
1174 try { |
|
1175 return (String[]) valueMethod.invoke(a); |
|
1176 } catch (InvocationTargetException e) { |
|
1177 throw new InternalError(e); |
|
1178 } catch (IllegalAccessException e) { |
|
1179 throw new InternalError(e); |
|
1180 } |
|
1181 } |
|
1182 } |
|
1183 |
1139 |
1184 CompositeBuilderViaConstructor(Class<?> targetClass, String[] itemNames) { |
1140 CompositeBuilderViaConstructor(Class<?> targetClass, String[] itemNames) { |
1185 super(targetClass, itemNames); |
1141 super(targetClass, itemNames); |
1186 } |
1142 } |
1187 |
1143 |
1188 String applicable(Method[] getters) throws InvalidObjectException { |
1144 String applicable(Method[] getters) throws InvalidObjectException { |
1189 if (!AnnotationHelper.isAvailable()) |
1145 if (!JavaBeansAccessor.isAvailable()) |
1190 return "@ConstructorProperties annotation not available"; |
1146 return "@ConstructorProperties annotation not available"; |
1191 |
1147 |
1192 Class<?> targetClass = getTargetClass(); |
1148 Class<?> targetClass = getTargetClass(); |
1193 Constructor<?>[] constrs = targetClass.getConstructors(); |
1149 Constructor<?>[] constrs = targetClass.getConstructors(); |
1194 |
1150 |
1195 // Applicable if and only if there are any annotated constructors |
1151 // Applicable if and only if there are any annotated constructors |
1196 List<Constructor<?>> annotatedConstrList = newList(); |
1152 List<Constructor<?>> annotatedConstrList = newList(); |
1197 for (Constructor<?> constr : constrs) { |
1153 for (Constructor<?> constr : constrs) { |
1198 if (Modifier.isPublic(constr.getModifiers()) |
1154 if (Modifier.isPublic(constr.getModifiers()) |
1199 && AnnotationHelper.getPropertyNames(constr) != null) |
1155 && JavaBeansAccessor.getConstructorPropertiesValue(constr) != null) |
1200 annotatedConstrList.add(constr); |
1156 annotatedConstrList.add(constr); |
1201 } |
1157 } |
1202 |
1158 |
1203 if (annotatedConstrList.isEmpty()) |
1159 if (annotatedConstrList.isEmpty()) |
1204 return "no constructor has @ConstructorProperties annotation"; |
1160 return "no constructor has @ConstructorProperties annotation"; |
1223 // element is -1, that item isn't given to the constructor. |
1179 // element is -1, that item isn't given to the constructor. |
1224 // Also remember the set of properties in that constructor |
1180 // Also remember the set of properties in that constructor |
1225 // so we can test unambiguity. |
1181 // so we can test unambiguity. |
1226 Set<BitSet> getterIndexSets = newSet(); |
1182 Set<BitSet> getterIndexSets = newSet(); |
1227 for (Constructor<?> constr : annotatedConstrList) { |
1183 for (Constructor<?> constr : annotatedConstrList) { |
1228 String[] propertyNames = AnnotationHelper.getPropertyNames(constr); |
1184 String[] propertyNames = JavaBeansAccessor.getConstructorPropertiesValue(constr); |
1229 |
1185 |
1230 Type[] paramTypes = constr.getGenericParameterTypes(); |
1186 Type[] paramTypes = constr.getGenericParameterTypes(); |
1231 if (paramTypes.length != propertyNames.length) { |
1187 if (paramTypes.length != propertyNames.length) { |
1232 final String msg = |
1188 final String msg = |
1233 "Number of constructor params does not match " + |
1189 "Number of constructor params does not match " + |