4058433: RFE: tool for creating BeanInfo template
Reviewed-by: alexsch, serb
This commit is contained in:
parent
52f8e9c096
commit
d5b9d36ad9
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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 com.sun.beans.introspect;
|
||||
|
||||
import com.sun.beans.util.Cache;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static sun.reflect.misc.ReflectUtil.checkPackageAccess;
|
||||
|
||||
public final class ClassInfo {
|
||||
private static final ClassInfo DEFAULT = new ClassInfo(null);
|
||||
private static final Cache<Class<?>,ClassInfo> CACHE
|
||||
= new Cache<Class<?>,ClassInfo>(Cache.Kind.SOFT, Cache.Kind.SOFT) {
|
||||
@Override
|
||||
public ClassInfo create(Class<?> type) {
|
||||
return new ClassInfo(type);
|
||||
}
|
||||
};
|
||||
|
||||
public static ClassInfo get(Class<?> type) {
|
||||
if (type == null) {
|
||||
return DEFAULT;
|
||||
}
|
||||
try {
|
||||
checkPackageAccess(type);
|
||||
return CACHE.get(type);
|
||||
} catch (SecurityException exception) {
|
||||
return DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
private final Object mutex = new Object();
|
||||
private final Class<?> type;
|
||||
private List<Method> methods;
|
||||
private Map<String,PropertyInfo> properties;
|
||||
private Map<String,EventSetInfo> eventSets;
|
||||
|
||||
private ClassInfo(Class<?> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public List<Method> getMethods() {
|
||||
if (this.methods == null) {
|
||||
synchronized (this.mutex) {
|
||||
if (this.methods == null) {
|
||||
this.methods = MethodInfo.get(this.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.methods;
|
||||
}
|
||||
|
||||
public Map<String,PropertyInfo> getProperties() {
|
||||
if (this.properties == null) {
|
||||
synchronized (this.mutex) {
|
||||
if (this.properties == null) {
|
||||
this.properties = PropertyInfo.get(this.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
public Map<String,EventSetInfo> getEventSets() {
|
||||
if (this.eventSets == null) {
|
||||
synchronized (this.mutex) {
|
||||
if (this.eventSets == null) {
|
||||
this.eventSets = EventSetInfo.get(this.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.eventSets;
|
||||
}
|
||||
}
|
145
jdk/src/share/classes/com/sun/beans/introspect/EventSetInfo.java
Normal file
145
jdk/src/share/classes/com/sun/beans/introspect/EventSetInfo.java
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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 com.sun.beans.introspect;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collections;
|
||||
import java.util.EventListener;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TooManyListenersException;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public final class EventSetInfo {
|
||||
private MethodInfo add;
|
||||
private MethodInfo remove;
|
||||
private MethodInfo get;
|
||||
|
||||
private EventSetInfo() {
|
||||
}
|
||||
|
||||
private boolean initialize() {
|
||||
if ((this.add == null) || (this.remove == null) || (this.remove.type != this.add.type)) {
|
||||
return false;
|
||||
}
|
||||
if ((this.get != null) && (this.get.type != this.add.type)) {
|
||||
this.get = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Class<?> getListenerType() {
|
||||
return this.add.type;
|
||||
}
|
||||
|
||||
public Method getAddMethod() {
|
||||
return this.add.method;
|
||||
}
|
||||
|
||||
public Method getRemoveMethod() {
|
||||
return this.remove.method;
|
||||
}
|
||||
|
||||
public Method getGetMethod() {
|
||||
return (this.get == null) ? null : this.get.method;
|
||||
}
|
||||
|
||||
public boolean isUnicast() {
|
||||
// if the adder method throws the TooManyListenersException
|
||||
// then it is an Unicast event source
|
||||
return this.add.isThrow(TooManyListenersException.class);
|
||||
}
|
||||
|
||||
private static MethodInfo getInfo(MethodInfo info, Method method, int prefix, int postfix) {
|
||||
Class<?> type = (postfix > 0)
|
||||
? MethodInfo.resolve(method, method.getGenericReturnType()).getComponentType()
|
||||
: MethodInfo.resolve(method, method.getGenericParameterTypes()[0]);
|
||||
|
||||
if ((type != null) && EventListener.class.isAssignableFrom(type)) {
|
||||
String name = method.getName();
|
||||
if (prefix + postfix < name.length()) {
|
||||
if (type.getName().endsWith(name.substring(prefix, name.length() - postfix))) {
|
||||
if ((info == null) || info.type.isAssignableFrom(type)) {
|
||||
return new MethodInfo(method, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
private static EventSetInfo getInfo(Map<String,EventSetInfo> map, String key) {
|
||||
EventSetInfo info = map.get(key);
|
||||
if (info == null) {
|
||||
info = new EventSetInfo();
|
||||
map.put(key, info);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
public static Map<String,EventSetInfo> get(Class<?> type) {
|
||||
List<Method> methods = ClassInfo.get(type).getMethods();
|
||||
if (methods.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String,EventSetInfo> map = new TreeMap<>();
|
||||
for (Method method : ClassInfo.get(type).getMethods()) {
|
||||
if (!Modifier.isStatic(method.getModifiers())) {
|
||||
Class<?> returnType = method.getReturnType();
|
||||
String name = method.getName();
|
||||
switch (method.getParameterCount()) {
|
||||
case 1:
|
||||
if ((returnType == void.class) && name.endsWith("Listener")) {
|
||||
if (name.startsWith("add")) {
|
||||
EventSetInfo info = getInfo(map, name.substring(3, name.length() - 8));
|
||||
info.add = getInfo(info.add, method, 3, 0);
|
||||
} else if (name.startsWith("remove")) {
|
||||
EventSetInfo info = getInfo(map, name.substring(6, name.length() - 8));
|
||||
info.remove = getInfo(info.remove, method, 6, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
if (returnType.isArray() && name.startsWith("get") && name.endsWith("Listeners")) {
|
||||
EventSetInfo info = getInfo(map, name.substring(3, name.length() - 9));
|
||||
info.get = getInfo(info.get, method, 3, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Iterator<EventSetInfo> iterator = map.values().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
if (!iterator.next().initialize()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
return !map.isEmpty()
|
||||
? Collections.unmodifiableMap(map)
|
||||
: Collections.emptyMap();
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 com.sun.beans.introspect;
|
||||
|
||||
import com.sun.beans.TypeResolver;
|
||||
import com.sun.beans.finder.MethodFinder;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
final class MethodInfo {
|
||||
final Method method;
|
||||
final Class<?> type;
|
||||
|
||||
MethodInfo(Method method, Class<?> type) {
|
||||
this.method = method;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
MethodInfo(Method method, Type type) {
|
||||
this.method = method;
|
||||
this.type = resolve(method, type);
|
||||
}
|
||||
|
||||
boolean isThrow(Class<?> exception) {
|
||||
for (Class<?> type : this.method.getExceptionTypes()) {
|
||||
if (type == exception) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static Class<?> resolve(Method method, Type type) {
|
||||
return TypeResolver.erase(TypeResolver.resolveInClass(method.getDeclaringClass(), type));
|
||||
}
|
||||
|
||||
static List<Method> get(Class<?> type) {
|
||||
List<Method> list = null;
|
||||
if (type != null) {
|
||||
boolean inaccessible = !Modifier.isPublic(type.getModifiers());
|
||||
for (Method method : type.getMethods()) {
|
||||
if (method.getDeclaringClass().equals(type)) {
|
||||
if (inaccessible) {
|
||||
try {
|
||||
method = MethodFinder.findAccessibleMethod(method);
|
||||
if (!method.getDeclaringClass().isInterface()) {
|
||||
method = null; // ignore methods from superclasses
|
||||
}
|
||||
} catch (NoSuchMethodException exception) {
|
||||
// commented out because of 6976577
|
||||
// method = null; // ignore inaccessible methods
|
||||
}
|
||||
}
|
||||
if (method != null) {
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
list.add(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (list != null)
|
||||
? Collections.unmodifiableList(list)
|
||||
: Collections.emptyList();
|
||||
}
|
||||
}
|
301
jdk/src/share/classes/com/sun/beans/introspect/PropertyInfo.java
Normal file
301
jdk/src/share/classes/com/sun/beans/introspect/PropertyInfo.java
Normal file
@ -0,0 +1,301 @@
|
||||
/*
|
||||
* 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 com.sun.beans.introspect;
|
||||
|
||||
import java.beans.BeanProperty;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import static com.sun.beans.finder.ClassFinder.findClass;
|
||||
|
||||
public final class PropertyInfo {
|
||||
public enum Name {bound, expert, hidden, preferred, visualUpdate, description, enumerationValues}
|
||||
|
||||
private static final String VETO_EXCEPTION_NAME = "java.beans.PropertyVetoException";
|
||||
private static final Class<?> VETO_EXCEPTION;
|
||||
|
||||
static {
|
||||
Class<?> type;
|
||||
try {
|
||||
type = Class.forName(VETO_EXCEPTION_NAME);
|
||||
} catch (Exception exception) {
|
||||
type = null;
|
||||
}
|
||||
VETO_EXCEPTION = type;
|
||||
}
|
||||
|
||||
private Class<?> type;
|
||||
private MethodInfo read;
|
||||
private MethodInfo write;
|
||||
private PropertyInfo indexed;
|
||||
private List<MethodInfo> readList;
|
||||
private List<MethodInfo> writeList;
|
||||
private Map<Name,Object> map;
|
||||
|
||||
private PropertyInfo() {
|
||||
}
|
||||
|
||||
private boolean initialize() {
|
||||
if (this.read != null) {
|
||||
this.type = this.read.type;
|
||||
}
|
||||
if (this.readList != null) {
|
||||
for (MethodInfo info : this.readList) {
|
||||
if ((this.read == null) || this.read.type.isAssignableFrom(info.type)) {
|
||||
this.read = info;
|
||||
this.type = info.type;
|
||||
}
|
||||
}
|
||||
this.readList = null;
|
||||
}
|
||||
if (this.writeList != null) {
|
||||
for (MethodInfo info : this.writeList) {
|
||||
if (this.type == null) {
|
||||
this.write = info;
|
||||
this.type = info.type;
|
||||
} else if (this.type.isAssignableFrom(info.type)) {
|
||||
if ((this.write == null) || this.write.type.isAssignableFrom(info.type)) {
|
||||
this.write = info;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.writeList = null;
|
||||
}
|
||||
if (this.indexed != null) {
|
||||
if ((this.type != null) && !this.type.isArray()) {
|
||||
this.indexed = null; // property type is not an array
|
||||
} else if (!this.indexed.initialize()) {
|
||||
this.indexed = null; // cannot initialize indexed methods
|
||||
} else if ((this.type != null) && (this.indexed.type != this.type.getComponentType())) {
|
||||
this.indexed = null; // different property types
|
||||
} else {
|
||||
this.map = this.indexed.map;
|
||||
this.indexed.map = null;
|
||||
}
|
||||
}
|
||||
if ((this.type == null) && (this.indexed == null)) {
|
||||
return false;
|
||||
}
|
||||
initialize(this.write);
|
||||
initialize(this.read);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void initialize(MethodInfo info) {
|
||||
if (info != null) {
|
||||
BeanProperty annotation = info.method.getAnnotation(BeanProperty.class);
|
||||
if (annotation != null) {
|
||||
if (!annotation.bound()) {
|
||||
put(Name.bound, Boolean.FALSE);
|
||||
}
|
||||
put(Name.expert, annotation.expert());
|
||||
put(Name.hidden, annotation.hidden());
|
||||
put(Name.preferred, annotation.preferred());
|
||||
put(Name.visualUpdate, annotation.visualUpdate());
|
||||
put(Name.description, annotation.description());
|
||||
String[] values = annotation.enumerationValues();
|
||||
if (0 < values.length) {
|
||||
try {
|
||||
Object[] array = new Object[3 * values.length];
|
||||
int index = 0;
|
||||
for (String value : values) {
|
||||
Class<?> type = info.method.getDeclaringClass();
|
||||
String name = value;
|
||||
int pos = value.lastIndexOf('.');
|
||||
if (pos > 0) {
|
||||
name = value.substring(0, pos);
|
||||
if (name.indexOf('.') < 0) {
|
||||
String pkg = type.getName();
|
||||
name = pkg.substring(0, 1 + Math.max(
|
||||
pkg.lastIndexOf('.'),
|
||||
pkg.lastIndexOf('$'))) + name;
|
||||
}
|
||||
type = findClass(name);
|
||||
name = value.substring(pos + 1);
|
||||
}
|
||||
Field field = type.getField(name);
|
||||
if (Modifier.isStatic(field.getModifiers()) && info.type.isAssignableFrom(field.getType())) {
|
||||
array[index++] = name;
|
||||
array[index++] = field.get(null);
|
||||
array[index++] = value;
|
||||
}
|
||||
}
|
||||
if (index == array.length) {
|
||||
put(Name.enumerationValues, array);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
ignored.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Class<?> getPropertyType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public Method getReadMethod() {
|
||||
return (this.read == null) ? null : this.read.method;
|
||||
}
|
||||
|
||||
public Method getWriteMethod() {
|
||||
return (this.write == null) ? null : this.write.method;
|
||||
}
|
||||
|
||||
public PropertyInfo getIndexed() {
|
||||
return this.indexed;
|
||||
}
|
||||
|
||||
public boolean isConstrained() {
|
||||
if (this.write != null) {
|
||||
if (VETO_EXCEPTION == null) {
|
||||
for (Class<?> type : this.write.method.getExceptionTypes()) {
|
||||
if (type.getName().equals(VETO_EXCEPTION_NAME)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (this.write.isThrow(VETO_EXCEPTION)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return (this.indexed != null) && this.indexed.isConstrained();
|
||||
}
|
||||
|
||||
public boolean is(Name name) {
|
||||
Object value = get(name);
|
||||
return (value instanceof Boolean)
|
||||
? (Boolean) value
|
||||
: Name.bound.equals(name);
|
||||
}
|
||||
|
||||
public Object get(Name name) {
|
||||
return this.map == null ? null : this.map.get(name);
|
||||
}
|
||||
|
||||
private void put(Name name, boolean value) {
|
||||
if (value) {
|
||||
put(name, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
private void put(Name name, String value) {
|
||||
if (0 < value.length()) {
|
||||
put(name, (Object) value);
|
||||
}
|
||||
}
|
||||
|
||||
private void put(Name name, Object value) {
|
||||
if (this.map == null) {
|
||||
this.map = new EnumMap<>(Name.class);
|
||||
}
|
||||
this.map.put(name, value);
|
||||
}
|
||||
|
||||
private static List<MethodInfo> add(List<MethodInfo> list, Method method, Type type) {
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
list.add(new MethodInfo(method, type));
|
||||
return list;
|
||||
}
|
||||
|
||||
private static boolean isPrefix(String name, String prefix) {
|
||||
return name.length() > prefix.length() && name.startsWith(prefix);
|
||||
}
|
||||
|
||||
private static PropertyInfo getInfo(Map<String,PropertyInfo> map, String key, boolean indexed) {
|
||||
PropertyInfo info = map.get(key);
|
||||
if (info == null) {
|
||||
info = new PropertyInfo();
|
||||
map.put(key, info);
|
||||
}
|
||||
if (!indexed) {
|
||||
return info;
|
||||
}
|
||||
if (info.indexed == null) {
|
||||
info.indexed = new PropertyInfo();
|
||||
}
|
||||
return info.indexed;
|
||||
}
|
||||
|
||||
public static Map<String,PropertyInfo> get(Class<?> type) {
|
||||
List<Method> methods = ClassInfo.get(type).getMethods();
|
||||
if (methods.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String,PropertyInfo> map = new TreeMap<>();
|
||||
for (Method method : methods) {
|
||||
if (!Modifier.isStatic(method.getModifiers())) {
|
||||
Class<?> returnType = method.getReturnType();
|
||||
String name = method.getName();
|
||||
switch (method.getParameterCount()) {
|
||||
case 0:
|
||||
if (returnType.equals(boolean.class) && isPrefix(name, "is")) {
|
||||
PropertyInfo info = getInfo(map, name.substring(2), false);
|
||||
info.read = new MethodInfo(method, boolean.class);
|
||||
} else if (!returnType.equals(void.class) && isPrefix(name, "get")) {
|
||||
PropertyInfo info = getInfo(map, name.substring(3), false);
|
||||
info.readList = add(info.readList, method, method.getGenericReturnType());
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (returnType.equals(void.class) && isPrefix(name, "set")) {
|
||||
PropertyInfo info = getInfo(map, name.substring(3), false);
|
||||
info.writeList = add(info.writeList, method, method.getGenericParameterTypes()[0]);
|
||||
} else if (!returnType.equals(void.class) && method.getParameterTypes()[0].equals(int.class) && isPrefix(name, "get")) {
|
||||
PropertyInfo info = getInfo(map, name.substring(3), true);
|
||||
info.readList = add(info.readList, method, method.getGenericReturnType());
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (returnType.equals(void.class) && method.getParameterTypes()[0].equals(int.class) && isPrefix(name, "set")) {
|
||||
PropertyInfo info = getInfo(map, name.substring(3), true);
|
||||
info.writeList = add(info.writeList, method, method.getGenericParameterTypes()[1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Iterator<PropertyInfo> iterator = map.values().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
if (!iterator.next().initialize()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
return !map.isEmpty()
|
||||
? Collections.unmodifiableMap(map)
|
||||
: Collections.emptyMap();
|
||||
}
|
||||
}
|
@ -22,10 +22,10 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.beans;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import javax.swing.SwingContainer;
|
||||
|
||||
/**
|
||||
* A BeanDescriptor provides global information about a "bean",
|
||||
@ -69,6 +69,23 @@ public class BeanDescriptor extends FeatureDescriptor {
|
||||
name = name.substring(name.indexOf('.')+1);
|
||||
}
|
||||
setName(name);
|
||||
|
||||
JavaBean annotation = beanClass.getAnnotation(JavaBean.class);
|
||||
if (annotation != null) {
|
||||
setPreferred(true);
|
||||
String description = annotation.description();
|
||||
if (!description.isEmpty()) {
|
||||
setShortDescription(description);
|
||||
}
|
||||
}
|
||||
SwingContainer container = beanClass.getAnnotation(SwingContainer.class);
|
||||
if (container != null) {
|
||||
setValue("isContainer", container.value());
|
||||
String delegate = container.delegate();
|
||||
if (!delegate.isEmpty()) {
|
||||
setValue("containerDelegate", delegate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
129
jdk/src/share/classes/java/beans/BeanProperty.java
Normal file
129
jdk/src/share/classes/java/beans/BeanProperty.java
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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 java.beans;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* An annotation used to specify some property-related information
|
||||
* for the automatically generated {@link BeanInfo} classes.
|
||||
* This annotation is not used if the annotated class
|
||||
* has a corresponding user-defined {@code BeanInfo} class,
|
||||
* which does not imply the automatic analysis.
|
||||
*
|
||||
* @see BeanInfo#getPropertyDescriptors
|
||||
* @since 1.9
|
||||
*
|
||||
* @author Sergey A. Malenkov
|
||||
*/
|
||||
@Documented
|
||||
@Target({METHOD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface BeanProperty {
|
||||
/**
|
||||
* The value that indicates whether the annotated property can be
|
||||
* a {@link PropertyDescriptor#isBound bound} property or not.
|
||||
* This value applies only to the beans that have the
|
||||
* {@link PropertyChangeListener propertyChange} event set.
|
||||
*
|
||||
* @return {@code true} if the annotated property can be a bound property;
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
boolean bound() default true;
|
||||
|
||||
/**
|
||||
* The value that indicates whether the annotated property is
|
||||
* an {@link PropertyDescriptor#isExpert expert} property or not.
|
||||
*
|
||||
* @return {@code true} if the annotated property is an expert property;
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
boolean expert() default false;
|
||||
|
||||
/**
|
||||
* The value that indicates whether the annotated property is
|
||||
* a {@link PropertyDescriptor#isHidden hidden} property or not.
|
||||
*
|
||||
* @return {@code true} if the annotated property is a hidden property;
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
boolean hidden() default false;
|
||||
|
||||
/**
|
||||
* The value that indicates whether the annotated property is
|
||||
* a {@link PropertyDescriptor#isPreferred preferred} property or not.
|
||||
*
|
||||
* @return {@code true} if the annotated property is a preferred property;
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
boolean preferred() default false;
|
||||
|
||||
/**
|
||||
* The value that indicates whether the annotated property is
|
||||
* a required property or not.
|
||||
*
|
||||
* @return {@code true} if the annotated property is a required property;
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
boolean required() default false;
|
||||
|
||||
/**
|
||||
* The value that indicates whether the corresponding component
|
||||
* is repainted after the annotated property got changed or not.
|
||||
*
|
||||
* @return {@code true} if the corresponding component is repainted;
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
boolean visualUpdate() default false;
|
||||
|
||||
/**
|
||||
* The {@link PropertyDescriptor#getShortDescription short description}
|
||||
* for the {@link BeanInfo#getPropertyDescriptors descriptor}
|
||||
* of the annotated property.
|
||||
*
|
||||
* @return the property description,
|
||||
* or an empty string if the description is not set.
|
||||
*/
|
||||
String description() default "";
|
||||
|
||||
/**
|
||||
* The array of names for the public static fields
|
||||
* that contains the valid values of the annotated property.
|
||||
* These names are used to generate the {@code enumerationValues}
|
||||
* {@link java.beans.BeanDescriptor#getValue feature attribute}
|
||||
* that must contain the following items per each property value:
|
||||
* a displayable name for the property value, the actual property value,
|
||||
* and a Java code piece used for the code generator.
|
||||
*
|
||||
* @return the names of the valid values of the annotated property,
|
||||
* or an empty array if the names are not provided.
|
||||
*/
|
||||
String[] enumerationValues() default {};
|
||||
}
|
@ -22,13 +22,14 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.beans;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import com.sun.beans.introspect.EventSetInfo;
|
||||
|
||||
/**
|
||||
* An EventSetDescriptor describes a group of events that a given Java
|
||||
* bean fires.
|
||||
@ -255,6 +256,16 @@ public class EventSetDescriptor extends FeatureDescriptor {
|
||||
setListenerType(listenerType);
|
||||
}
|
||||
|
||||
EventSetDescriptor(String base, EventSetInfo info, Method... methods) {
|
||||
setName(Introspector.decapitalize(base));
|
||||
setListenerMethods(methods);
|
||||
setAddListenerMethod(info.getAddMethod());
|
||||
setRemoveListenerMethod(info.getRemoveMethod());
|
||||
setGetListenerMethod(info.getGetMethod());
|
||||
setListenerType(info.getListenerType());
|
||||
setUnicast(info.isUnicast());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an <TT>EventSetDescriptor</TT> from scratch using
|
||||
* <TT>java.lang.reflect.MethodDescriptor</TT> and <TT>java.lang.Class</TT>
|
||||
|
@ -22,11 +22,13 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.beans;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.sun.beans.introspect.PropertyInfo;
|
||||
|
||||
/**
|
||||
* An IndexedPropertyDescriptor describes a property that acts like an
|
||||
@ -143,27 +145,21 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates <code>PropertyDescriptor</code> for the specified bean
|
||||
* with the specified name and methods to read/write the property value.
|
||||
* Creates {@code IndexedPropertyDescriptor} from the specified property info.
|
||||
*
|
||||
* @param bean the type of the target bean
|
||||
* @param base the base name of the property (the rest of the method name)
|
||||
* @param read the method used for reading the property value
|
||||
* @param write the method used for writing the property value
|
||||
* @param readIndexed the method used for reading an indexed property value
|
||||
* @param writeIndexed the method used for writing an indexed property value
|
||||
* @exception IntrospectionException if an exception occurs during introspection
|
||||
* @param entry the key-value pair,
|
||||
* where the {@code key} is the base name of the property (the rest of the method name)
|
||||
* and the {@code value} is the automatically generated property info
|
||||
* @param bound the flag indicating whether it is possible to treat this property as a bound property
|
||||
*
|
||||
* @since 1.7
|
||||
* @since 1.9
|
||||
*/
|
||||
IndexedPropertyDescriptor(Class<?> bean, String base, Method read, Method write, Method readIndexed, Method writeIndexed) throws IntrospectionException {
|
||||
super(bean, base, read, write);
|
||||
|
||||
setIndexedReadMethod0(readIndexed);
|
||||
setIndexedWriteMethod0(writeIndexed);
|
||||
|
||||
// Type checking
|
||||
setIndexedPropertyType(findIndexedPropertyType(readIndexed, writeIndexed));
|
||||
IndexedPropertyDescriptor(Entry<String,PropertyInfo> entry, boolean bound) {
|
||||
super(entry, bound);
|
||||
PropertyInfo info = entry.getValue().getIndexed();
|
||||
setIndexedReadMethod0(info.getReadMethod());
|
||||
setIndexedWriteMethod0(info.getWriteMethod());
|
||||
setIndexedPropertyType(info.getPropertyType());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,32 +22,30 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.beans;
|
||||
|
||||
import com.sun.beans.TypeResolver;
|
||||
import com.sun.beans.WeakCache;
|
||||
import com.sun.beans.finder.ClassFinder;
|
||||
import com.sun.beans.finder.MethodFinder;
|
||||
import com.sun.beans.introspect.ClassInfo;
|
||||
import com.sun.beans.introspect.EventSetInfo;
|
||||
import com.sun.beans.introspect.PropertyInfo;
|
||||
|
||||
import java.awt.Component;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.EventListener;
|
||||
import java.util.EventObject;
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import sun.misc.JavaBeansIntrospectorAccess;
|
||||
import sun.misc.SharedSecrets;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
@ -122,7 +120,6 @@ public class Introspector {
|
||||
private BeanInfo additionalBeanInfo[];
|
||||
|
||||
private boolean propertyChangeSource = false;
|
||||
private static Class<EventListener> eventListenerType = EventListener.class;
|
||||
|
||||
// These should be removed.
|
||||
private String defaultEventName;
|
||||
@ -501,78 +498,15 @@ public class Introspector {
|
||||
addPropertyDescriptors(explicitProperties);
|
||||
|
||||
} else {
|
||||
|
||||
// Apply some reflection to the current class.
|
||||
|
||||
// First get an array of all the public methods at this level
|
||||
Method methodList[] = getPublicDeclaredMethods(beanClass);
|
||||
|
||||
// Now analyze each method.
|
||||
for (int i = 0; i < methodList.length; i++) {
|
||||
Method method = methodList[i];
|
||||
if (method == null) {
|
||||
continue;
|
||||
}
|
||||
// skip static methods.
|
||||
int mods = method.getModifiers();
|
||||
if (Modifier.isStatic(mods)) {
|
||||
continue;
|
||||
}
|
||||
String name = method.getName();
|
||||
Class<?>[] argTypes = method.getParameterTypes();
|
||||
Class<?> resultType = method.getReturnType();
|
||||
int argCount = argTypes.length;
|
||||
PropertyDescriptor pd = null;
|
||||
|
||||
if (name.length() <= 3 && !name.startsWith(IS_PREFIX)) {
|
||||
// Optimization. Don't bother with invalid propertyNames.
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if (argCount == 0) {
|
||||
if (name.startsWith(GET_PREFIX)) {
|
||||
// Simple getter
|
||||
pd = new PropertyDescriptor(this.beanClass, name.substring(3), method, null);
|
||||
} else if (resultType == boolean.class && name.startsWith(IS_PREFIX)) {
|
||||
// Boolean getter
|
||||
pd = new PropertyDescriptor(this.beanClass, name.substring(2), method, null);
|
||||
}
|
||||
} else if (argCount == 1) {
|
||||
if (int.class.equals(argTypes[0]) && name.startsWith(GET_PREFIX)) {
|
||||
pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, method, null);
|
||||
} else if (void.class.equals(resultType) && name.startsWith(SET_PREFIX)) {
|
||||
// Simple setter
|
||||
pd = new PropertyDescriptor(this.beanClass, name.substring(3), null, method);
|
||||
if (throwsException(method, PropertyVetoException.class)) {
|
||||
pd.setConstrained(true);
|
||||
}
|
||||
}
|
||||
} else if (argCount == 2) {
|
||||
if (void.class.equals(resultType) && int.class.equals(argTypes[0]) && name.startsWith(SET_PREFIX)) {
|
||||
pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, null, method);
|
||||
if (throwsException(method, PropertyVetoException.class)) {
|
||||
pd.setConstrained(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IntrospectionException ex) {
|
||||
// This happens if a PropertyDescriptor or IndexedPropertyDescriptor
|
||||
// constructor fins that the method violates details of the deisgn
|
||||
// pattern, e.g. by having an empty name, or a getter returning
|
||||
// void , or whatever.
|
||||
pd = null;
|
||||
}
|
||||
|
||||
if (pd != null) {
|
||||
// If this class or one of its base classes is a PropertyChange
|
||||
// source, then we assume that any properties we discover are "bound".
|
||||
if (propertyChangeSource) {
|
||||
pd.setBound(true);
|
||||
}
|
||||
addPropertyDescriptor(pd);
|
||||
}
|
||||
for (Map.Entry<String,PropertyInfo> entry : ClassInfo.get(this.beanClass).getProperties().entrySet()) {
|
||||
addPropertyDescriptor(null != entry.getValue().getIndexed()
|
||||
? new IndexedPropertyDescriptor(entry, this.propertyChangeSource)
|
||||
: new PropertyDescriptor(entry, this.propertyChangeSource));
|
||||
}
|
||||
JavaBean annotation = this.beanClass.getAnnotation(JavaBean.class);
|
||||
if ((annotation != null) && !annotation.defaultProperty().isEmpty()) {
|
||||
this.defaultPropertyName = annotation.defaultProperty();
|
||||
}
|
||||
}
|
||||
processPropertyDescriptors();
|
||||
@ -589,7 +523,6 @@ public class Introspector {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1003,143 +936,24 @@ public class Introspector {
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Apply some reflection to the current class.
|
||||
|
||||
// Get an array of all the public beans methods at this level
|
||||
Method methodList[] = getPublicDeclaredMethods(beanClass);
|
||||
|
||||
// Find all suitable "add", "remove" and "get" Listener methods
|
||||
// The name of the listener type is the key for these hashtables
|
||||
// i.e, ActionListener
|
||||
Map<String, Method> adds = null;
|
||||
Map<String, Method> removes = null;
|
||||
Map<String, Method> gets = null;
|
||||
|
||||
for (int i = 0; i < methodList.length; i++) {
|
||||
Method method = methodList[i];
|
||||
if (method == null) {
|
||||
continue;
|
||||
}
|
||||
// skip static methods.
|
||||
int mods = method.getModifiers();
|
||||
if (Modifier.isStatic(mods)) {
|
||||
continue;
|
||||
}
|
||||
String name = method.getName();
|
||||
// Optimization avoid getParameterTypes
|
||||
if (!name.startsWith(ADD_PREFIX) && !name.startsWith(REMOVE_PREFIX)
|
||||
&& !name.startsWith(GET_PREFIX)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (name.startsWith(ADD_PREFIX)) {
|
||||
Class<?> returnType = method.getReturnType();
|
||||
if (returnType == void.class) {
|
||||
Type[] parameterTypes = method.getGenericParameterTypes();
|
||||
if (parameterTypes.length == 1) {
|
||||
Class<?> type = TypeResolver.erase(TypeResolver.resolveInClass(beanClass, parameterTypes[0]));
|
||||
if (Introspector.isSubclass(type, eventListenerType)) {
|
||||
String listenerName = name.substring(3);
|
||||
if (listenerName.length() > 0 &&
|
||||
type.getName().endsWith(listenerName)) {
|
||||
if (adds == null) {
|
||||
adds = new HashMap<>();
|
||||
}
|
||||
adds.put(listenerName, method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (name.startsWith(REMOVE_PREFIX)) {
|
||||
Class<?> returnType = method.getReturnType();
|
||||
if (returnType == void.class) {
|
||||
Type[] parameterTypes = method.getGenericParameterTypes();
|
||||
if (parameterTypes.length == 1) {
|
||||
Class<?> type = TypeResolver.erase(TypeResolver.resolveInClass(beanClass, parameterTypes[0]));
|
||||
if (Introspector.isSubclass(type, eventListenerType)) {
|
||||
String listenerName = name.substring(6);
|
||||
if (listenerName.length() > 0 &&
|
||||
type.getName().endsWith(listenerName)) {
|
||||
if (removes == null) {
|
||||
removes = new HashMap<>();
|
||||
}
|
||||
removes.put(listenerName, method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (name.startsWith(GET_PREFIX)) {
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
if (parameterTypes.length == 0) {
|
||||
Class<?> returnType = FeatureDescriptor.getReturnType(beanClass, method);
|
||||
if (returnType.isArray()) {
|
||||
Class<?> type = returnType.getComponentType();
|
||||
if (Introspector.isSubclass(type, eventListenerType)) {
|
||||
String listenerName = name.substring(3, name.length() - 1);
|
||||
if (listenerName.length() > 0 &&
|
||||
type.getName().endsWith(listenerName)) {
|
||||
if (gets == null) {
|
||||
gets = new HashMap<>();
|
||||
}
|
||||
gets.put(listenerName, method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (adds != null && removes != null) {
|
||||
// Now look for matching addFooListener+removeFooListener pairs.
|
||||
// Bonus if there is a matching getFooListeners method as well.
|
||||
Iterator<String> keys = adds.keySet().iterator();
|
||||
while (keys.hasNext()) {
|
||||
String listenerName = keys.next();
|
||||
// Skip any "add" which doesn't have a matching "remove" or
|
||||
// a listener name that doesn't end with Listener
|
||||
if (removes.get(listenerName) == null || !listenerName.endsWith("Listener")) {
|
||||
continue;
|
||||
}
|
||||
String eventName = decapitalize(listenerName.substring(0, listenerName.length()-8));
|
||||
Method addMethod = adds.get(listenerName);
|
||||
Method removeMethod = removes.get(listenerName);
|
||||
Method getMethod = null;
|
||||
if (gets != null) {
|
||||
getMethod = gets.get(listenerName);
|
||||
}
|
||||
Class<?> argType = FeatureDescriptor.getParameterTypes(beanClass, addMethod)[0];
|
||||
|
||||
for (Map.Entry<String,EventSetInfo> entry : ClassInfo.get(this.beanClass).getEventSets().entrySet()) {
|
||||
// generate a list of Method objects for each of the target methods:
|
||||
Method allMethods[] = getPublicDeclaredMethods(argType);
|
||||
List<Method> validMethods = new ArrayList<>(allMethods.length);
|
||||
for (int i = 0; i < allMethods.length; i++) {
|
||||
if (allMethods[i] == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isEventHandler(allMethods[i])) {
|
||||
validMethods.add(allMethods[i]);
|
||||
}
|
||||
List<Method> methods = new ArrayList<>();
|
||||
for (Method method : ClassInfo.get(entry.getValue().getListenerType()).getMethods()) {
|
||||
if (isEventHandler(method)) {
|
||||
methods.add(method);
|
||||
}
|
||||
Method[] methods = validMethods.toArray(new Method[validMethods.size()]);
|
||||
|
||||
EventSetDescriptor esd = new EventSetDescriptor(eventName, argType,
|
||||
methods, addMethod,
|
||||
removeMethod,
|
||||
getMethod);
|
||||
|
||||
// If the adder method throws the TooManyListenersException then it
|
||||
// is a Unicast event source.
|
||||
if (throwsException(addMethod,
|
||||
java.util.TooManyListenersException.class)) {
|
||||
esd.setUnicast(true);
|
||||
}
|
||||
addEvent(esd);
|
||||
}
|
||||
} // if (adds != null ...
|
||||
addEvent(new EventSetDescriptor(
|
||||
entry.getKey(),
|
||||
entry.getValue(),
|
||||
methods.toArray(new Method[methods.size()])));
|
||||
}
|
||||
JavaBean annotation = this.beanClass.getAnnotation(JavaBean.class);
|
||||
if ((annotation != null) && !annotation.defaultEventSet().isEmpty()) {
|
||||
this.defaultEventName = annotation.defaultEventSet();
|
||||
}
|
||||
}
|
||||
EventSetDescriptor[] result;
|
||||
if (events.size() == 0) {
|
||||
@ -1148,7 +962,6 @@ public class Introspector {
|
||||
// Allocate and populate the result array.
|
||||
result = new EventSetDescriptor[events.size()];
|
||||
result = events.values().toArray(result);
|
||||
|
||||
// Set the default index.
|
||||
if (defaultEventName != null) {
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
@ -1215,20 +1028,9 @@ public class Introspector {
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Apply some reflection to the current class.
|
||||
|
||||
// First get an array of all the beans methods at this level
|
||||
Method methodList[] = getPublicDeclaredMethods(beanClass);
|
||||
|
||||
// Now analyze each method.
|
||||
for (int i = 0; i < methodList.length; i++) {
|
||||
Method method = methodList[i];
|
||||
if (method == null) {
|
||||
continue;
|
||||
}
|
||||
MethodDescriptor md = new MethodDescriptor(method);
|
||||
addMethod(md);
|
||||
for (Method method : ClassInfo.get(this.beanClass).getMethods()) {
|
||||
addMethod(new MethodDescriptor(method));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1346,44 +1148,6 @@ public class Introspector {
|
||||
return isSubclass(TypeResolver.erase(TypeResolver.resolveInClass(beanClass, argTypes[0])), EventObject.class);
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal method to return *public* methods within a class.
|
||||
*/
|
||||
private static Method[] getPublicDeclaredMethods(Class<?> clz) {
|
||||
// Looking up Class.getDeclaredMethods is relatively expensive,
|
||||
// so we cache the results.
|
||||
if (!ReflectUtil.isPackageAccessible(clz)) {
|
||||
return new Method[0];
|
||||
}
|
||||
synchronized (declaredMethodCache) {
|
||||
Method[] result = declaredMethodCache.get(clz);
|
||||
if (result == null) {
|
||||
result = clz.getMethods();
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
Method method = result[i];
|
||||
if (!method.getDeclaringClass().equals(clz)) {
|
||||
result[i] = null; // ignore methods declared elsewhere
|
||||
}
|
||||
else {
|
||||
try {
|
||||
method = MethodFinder.findAccessibleMethod(method);
|
||||
Class<?> type = method.getDeclaringClass();
|
||||
result[i] = type.equals(clz) || type.isInterface()
|
||||
? method
|
||||
: null; // ignore methods from superclasses
|
||||
}
|
||||
catch (NoSuchMethodException exception) {
|
||||
// commented out because of 6976577
|
||||
// result[i] = null; // ignore inaccessible methods
|
||||
}
|
||||
}
|
||||
}
|
||||
declaredMethodCache.put(clz, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// Package private support methods.
|
||||
//======================================================================
|
||||
@ -1396,17 +1160,8 @@ public class Introspector {
|
||||
int argCount, Class<?> args[]) {
|
||||
// For overriden methods we need to find the most derived version.
|
||||
// So we start with the given class and walk up the superclass chain.
|
||||
|
||||
Method method = null;
|
||||
|
||||
for (Class<?> cl = start; cl != null; cl = cl.getSuperclass()) {
|
||||
Method methods[] = getPublicDeclaredMethods(cl);
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
method = methods[i];
|
||||
if (method == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Method method : ClassInfo.get(cl).getMethods()) {
|
||||
// make sure method signature matches.
|
||||
if (method.getName().equals(methodName)) {
|
||||
Type[] params = method.getGenericParameterTypes();
|
||||
@ -1430,8 +1185,6 @@ public class Introspector {
|
||||
}
|
||||
}
|
||||
}
|
||||
method = null;
|
||||
|
||||
// Now check any inherited interfaces. This is necessary both when
|
||||
// the argument class is itself an interface, and when the argument
|
||||
// class is an abstract class.
|
||||
@ -1440,12 +1193,12 @@ public class Introspector {
|
||||
// Note: The original implementation had both methods calling
|
||||
// the 3 arg method. This is preserved but perhaps it should
|
||||
// pass the args array instead of null.
|
||||
method = internalFindMethod(ifcs[i], methodName, argCount, null);
|
||||
Method method = internalFindMethod(ifcs[i], methodName, argCount, null);
|
||||
if (method != null) {
|
||||
break;
|
||||
return method;
|
||||
}
|
||||
}
|
||||
return method;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1507,19 +1260,6 @@ public class Introspector {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true iff the given method throws the given exception.
|
||||
*/
|
||||
private boolean throwsException(Method method, Class<?> exception) {
|
||||
Class<?>[] exs = method.getExceptionTypes();
|
||||
for (int i = 0; i < exs.length; i++) {
|
||||
if (exs[i] == exception) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to create an instance of a named class.
|
||||
* First try the classloader of "sibling", then try the system
|
||||
|
89
jdk/src/share/classes/java/beans/JavaBean.java
Normal file
89
jdk/src/share/classes/java/beans/JavaBean.java
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 java.beans;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* An annotation used to specify some class-related information
|
||||
* for the automatically generated {@link BeanInfo} classes.
|
||||
* This annotation is not used if the annotated class
|
||||
* has a corresponding user-defined {@code BeanInfo} class,
|
||||
* which does not imply the automatic analysis.
|
||||
*
|
||||
* @see BeanInfo#getBeanDescriptor
|
||||
* @since 1.9
|
||||
*
|
||||
* @author Sergey A. Malenkov
|
||||
*/
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface JavaBean {
|
||||
/**
|
||||
* The {@link BeanDescriptor#getShortDescription short description}
|
||||
* for the {@link BeanInfo#getBeanDescriptor bean descriptor}
|
||||
* of the annotated class.
|
||||
*
|
||||
* @return the bean description,
|
||||
* or an empty string if the description is not set.
|
||||
*/
|
||||
String description() default "";
|
||||
|
||||
/**
|
||||
* The name of the default property is used to calculate its
|
||||
* {@link BeanInfo#getDefaultPropertyIndex index} in the
|
||||
* {@link BeanInfo#getPropertyDescriptors array} of properties
|
||||
* defined in the annotated class. If the name is not set or
|
||||
* the annotated class does not define a property
|
||||
* with the specified name, the default property index
|
||||
* will be calculated automatically by the
|
||||
* {@link Introspector} depending on its state.
|
||||
*
|
||||
* @return the name of the default property,
|
||||
* or an empty string if the name is not set.
|
||||
*/
|
||||
String defaultProperty() default "";
|
||||
|
||||
/**
|
||||
* The name of the default event set is used to calculate its
|
||||
* {@link BeanInfo#getDefaultEventIndex index} in the
|
||||
* {@link BeanInfo#getEventSetDescriptors array} of event sets
|
||||
* defined in the annotated class. If the name is not set or
|
||||
* the annotated class does not define an event set
|
||||
* with the specified name, the default event set index
|
||||
* will be calculated automatically by the
|
||||
* {@link Introspector} depending on its state.
|
||||
*
|
||||
* @return the name of the default event set,
|
||||
* or an empty string if the name is not set.
|
||||
*/
|
||||
String defaultEventSet() default "";
|
||||
}
|
@ -22,12 +22,14 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.beans;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.sun.beans.introspect.PropertyInfo;
|
||||
|
||||
/**
|
||||
* A PropertyDescriptor describes one property that a Java Bean
|
||||
@ -140,25 +142,47 @@ public class PropertyDescriptor extends FeatureDescriptor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates <code>PropertyDescriptor</code> for the specified bean
|
||||
* with the specified name and methods to read/write the property value.
|
||||
* Creates {@code PropertyDescriptor} from the specified property info.
|
||||
*
|
||||
* @param bean the type of the target bean
|
||||
* @param base the base name of the property (the rest of the method name)
|
||||
* @param read the method used for reading the property value
|
||||
* @param write the method used for writing the property value
|
||||
* @exception IntrospectionException if an exception occurs during introspection
|
||||
* @param entry the pair of values,
|
||||
* where the {@code key} is the base name of the property (the rest of the method name)
|
||||
* and the {@code value} is the automatically generated property info
|
||||
* @param bound the flag indicating whether it is possible to treat this property as a bound property
|
||||
*
|
||||
* @since 1.7
|
||||
* @since 1.9
|
||||
*/
|
||||
PropertyDescriptor(Class<?> bean, String base, Method read, Method write) throws IntrospectionException {
|
||||
if (bean == null) {
|
||||
throw new IntrospectionException("Target Bean class is null");
|
||||
}
|
||||
setClass0(bean);
|
||||
PropertyDescriptor(Entry<String,PropertyInfo> entry, boolean bound) {
|
||||
String base = entry.getKey();
|
||||
PropertyInfo info = entry.getValue();
|
||||
setName(Introspector.decapitalize(base));
|
||||
setReadMethod(read);
|
||||
setWriteMethod(write);
|
||||
setReadMethod0(info.getReadMethod());
|
||||
setWriteMethod0(info.getWriteMethod());
|
||||
setPropertyType(info.getPropertyType());
|
||||
setConstrained(info.isConstrained());
|
||||
setBound(bound && info.is(PropertyInfo.Name.bound));
|
||||
if (info.is(PropertyInfo.Name.expert)) {
|
||||
setValue(PropertyInfo.Name.expert.name(), Boolean.TRUE); // compatibility
|
||||
setExpert(true);
|
||||
}
|
||||
if (info.is(PropertyInfo.Name.hidden)) {
|
||||
setValue(PropertyInfo.Name.hidden.name(), Boolean.TRUE); // compatibility
|
||||
setHidden(true);
|
||||
}
|
||||
if (info.is(PropertyInfo.Name.preferred)) {
|
||||
setPreferred(true);
|
||||
}
|
||||
Object visual = info.get(PropertyInfo.Name.visualUpdate);
|
||||
if (visual != null) {
|
||||
setValue(PropertyInfo.Name.visualUpdate.name(), visual);
|
||||
}
|
||||
Object description = info.get(PropertyInfo.Name.description);
|
||||
if (description != null) {
|
||||
setShortDescription(description.toString());
|
||||
}
|
||||
Object values = info.get(PropertyInfo.Name.enumerationValues);
|
||||
if (values != null) {
|
||||
setValue(PropertyInfo.Name.enumerationValues.name(), values);
|
||||
}
|
||||
this.baseName = base;
|
||||
}
|
||||
|
||||
@ -249,13 +273,17 @@ public class PropertyDescriptor extends FeatureDescriptor {
|
||||
*/
|
||||
public synchronized void setReadMethod(Method readMethod)
|
||||
throws IntrospectionException {
|
||||
// The property type is determined by the read method.
|
||||
setPropertyType(findPropertyType(readMethod, this.writeMethodRef.get()));
|
||||
setReadMethod0(readMethod);
|
||||
}
|
||||
|
||||
private void setReadMethod0(Method readMethod) {
|
||||
this.readMethodRef.set(readMethod);
|
||||
if (readMethod == null) {
|
||||
readMethodName = null;
|
||||
return;
|
||||
}
|
||||
// The property type is determined by the read method.
|
||||
setPropertyType(findPropertyType(readMethod, this.writeMethodRef.get()));
|
||||
setClass0(readMethod.getDeclaringClass());
|
||||
|
||||
readMethodName = readMethod.getName();
|
||||
@ -320,13 +348,17 @@ public class PropertyDescriptor extends FeatureDescriptor {
|
||||
*/
|
||||
public synchronized void setWriteMethod(Method writeMethod)
|
||||
throws IntrospectionException {
|
||||
// Set the property type - which validates the method
|
||||
setPropertyType(findPropertyType(getReadMethod(), writeMethod));
|
||||
setWriteMethod0(writeMethod);
|
||||
}
|
||||
|
||||
private void setWriteMethod0(Method writeMethod) {
|
||||
this.writeMethodRef.set(writeMethod);
|
||||
if (writeMethod == null) {
|
||||
writeMethodName = null;
|
||||
return;
|
||||
}
|
||||
// Set the property type - which validates the method
|
||||
setPropertyType(findPropertyType(getReadMethod(), writeMethod));
|
||||
setClass0(writeMethod.getDeclaringClass());
|
||||
|
||||
writeMethodName = writeMethod.getName();
|
||||
|
75
jdk/src/share/classes/javax/swing/SwingContainer.java
Normal file
75
jdk/src/share/classes/javax/swing/SwingContainer.java
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 javax.swing;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* An annotation used to specify some swing-related information
|
||||
* for the automatically generated {@code BeanInfo} classes.
|
||||
* This annotation is not used if the annotated class
|
||||
* has a corresponding user-defined {@code BeanInfo} class,
|
||||
* which does not imply the automatic analysis.
|
||||
* <p>
|
||||
* The {@code isContainer} {@link java.beans.BeanDescriptor#getValue
|
||||
* feature attribute} was introduced primarily for the Swing library.
|
||||
* All Swing components extend the {@link java.awt.Container Container}
|
||||
* class by design, so the builder tool assumes that all Swing components
|
||||
* are containers. The {@link java.beans.BeanInfo BeanInfo} classes
|
||||
* with the {@code isContainer} attribute allow to directly specify
|
||||
* whether a Swing component is a container or not.
|
||||
*
|
||||
* @since 1.9
|
||||
*
|
||||
* @author Sergey A. Malenkov
|
||||
*/
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface SwingContainer {
|
||||
/**
|
||||
* The value that indicates whether the annotated class can be used
|
||||
* as a container for other Swing components or not.
|
||||
*
|
||||
* @return {@code true} if the annotated class is a Swing container;
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
boolean value() default true;
|
||||
|
||||
/**
|
||||
* The name of the getter method in the annotated class,
|
||||
* which returns the corresponding Swing container,
|
||||
* if it is not recommended to add subcomponents
|
||||
* to the annotated class directly.
|
||||
*
|
||||
* @return the name of the getter method in the annotated class,
|
||||
* which returns the corresponding Swing container,
|
||||
* or an empty string if the method name is not set.
|
||||
*/
|
||||
String delegate() default "";
|
||||
}
|
272
jdk/test/java/beans/Introspector/4058433/TestBeanProperty.java
Normal file
272
jdk/test/java/beans/Introspector/4058433/TestBeanProperty.java
Normal file
@ -0,0 +1,272 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.BeanProperty;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.util.Arrays;
|
||||
/*
|
||||
* @test
|
||||
* @bug 4058433
|
||||
* @summary Tests the BeanProperty annotation
|
||||
* @author Sergey Malenkov
|
||||
* @library ..
|
||||
*/
|
||||
public class TestBeanProperty {
|
||||
public static void main(String[] args) throws Exception {
|
||||
Class<?>[] types = {B.class, BL.class, BLF.class, E.class, H.class, P.class, VU.class, D.class, EV.class, EVL.class, EVX.class};
|
||||
for (Class<?> type : types) {
|
||||
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(type, "value");
|
||||
if (((B.class == type) || (BLF.class == type)) && pd.isBound()) {
|
||||
BeanUtils.reportPropertyDescriptor(pd);
|
||||
throw new Error("not bound");
|
||||
}
|
||||
if ((BL.class == type) == !pd.isBound()) {
|
||||
BeanUtils.reportPropertyDescriptor(pd);
|
||||
throw new Error("bound");
|
||||
}
|
||||
if ((E.class == type) == !pd.isExpert()) {
|
||||
BeanUtils.reportPropertyDescriptor(pd);
|
||||
throw new Error("expert");
|
||||
}
|
||||
if ((H.class == type) == !pd.isHidden()) {
|
||||
BeanUtils.reportPropertyDescriptor(pd);
|
||||
throw new Error("hidden");
|
||||
}
|
||||
if ((P.class == type) == !pd.isPreferred()) {
|
||||
BeanUtils.reportPropertyDescriptor(pd);
|
||||
throw new Error("preferred");
|
||||
}
|
||||
if ((R.class == type) == !Boolean.TRUE.equals(pd.getValue("required"))) {
|
||||
BeanUtils.reportPropertyDescriptor(pd);
|
||||
throw new Error("required");
|
||||
}
|
||||
if ((VU.class == type) == !Boolean.TRUE.equals(pd.getValue("visualUpdate"))) {
|
||||
BeanUtils.reportPropertyDescriptor(pd);
|
||||
throw new Error("visualUpdate");
|
||||
}
|
||||
if ((EV.class == type) == !isEV(pd, "LEFT", 2, "javax.swing.SwingConstants.LEFT", "RIGHT", 4, "javax.swing.SwingConstants.RIGHT")) {
|
||||
BeanUtils.reportPropertyDescriptor(pd);
|
||||
throw new Error("enumerationValues from another package");
|
||||
}
|
||||
if ((EVL.class == type) == !isEV(pd, "ZERO", 0, "ZERO", "ONE", 1, "ONE")) {
|
||||
BeanUtils.reportPropertyDescriptor(pd);
|
||||
throw new Error("enumerationValues from another package");
|
||||
}
|
||||
if ((EVX.class == type) == !isEV(pd, "ZERO", 0, "X.ZERO", "ONE", 1, "X.ONE")) {
|
||||
BeanUtils.reportPropertyDescriptor(pd);
|
||||
throw new Error("enumerationValues from another package");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isEV(PropertyDescriptor pd, Object... expected) {
|
||||
Object value = pd.getValue("enumerationValues");
|
||||
return value instanceof Object[] && Arrays.equals((Object[]) value, expected);
|
||||
}
|
||||
|
||||
public static class B {
|
||||
private int value;
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class BL {
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
private int value;
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
this.pcs.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
this.pcs.removePropertyChangeListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public static class BLF {
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
private int value;
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@BeanProperty(bound = false)
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
this.pcs.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
this.pcs.removePropertyChangeListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public static class E {
|
||||
private int value;
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@BeanProperty(expert = true)
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class H {
|
||||
private int value;
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@BeanProperty(hidden = true)
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class P {
|
||||
private int value;
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@BeanProperty(preferred = true)
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class R {
|
||||
private int value;
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@BeanProperty(required = true)
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class VU {
|
||||
private int value;
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@BeanProperty(visualUpdate = true)
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class D {
|
||||
private int value;
|
||||
|
||||
@BeanProperty(description = "getter")
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@BeanProperty(description = "setter")
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class EV {
|
||||
private int value;
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@BeanProperty(enumerationValues = {
|
||||
"javax.swing.SwingConstants.LEFT",
|
||||
"javax.swing.SwingConstants.RIGHT"})
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class EVL {
|
||||
private int value;
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@BeanProperty(enumerationValues = {"ZERO", "ONE"})
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static int ZERO = 0;
|
||||
public static int ONE = 1;
|
||||
}
|
||||
|
||||
public static class EVX {
|
||||
private int value;
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@BeanProperty(enumerationValues = {
|
||||
"X.ZERO",
|
||||
"X.ONE"})
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static interface X {
|
||||
int ZERO = 0;
|
||||
int ONE = 1;
|
||||
}
|
||||
}
|
102
jdk/test/java/beans/Introspector/4058433/TestJavaBean.java
Normal file
102
jdk/test/java/beans/Introspector/4058433/TestJavaBean.java
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.awt.event.ActionListener;
|
||||
import java.beans.BeanDescriptor;
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.JavaBean;
|
||||
/*
|
||||
* @test
|
||||
* @bug 4058433
|
||||
* @summary Tests the JavaBean annotation
|
||||
* @author Sergey Malenkov
|
||||
*/
|
||||
public class TestJavaBean {
|
||||
public static void main(String[] args) throws Exception {
|
||||
test(X.class);
|
||||
test(D.class);
|
||||
test(DP.class);
|
||||
test(DES.class);
|
||||
}
|
||||
|
||||
private static void test(Class<?> type) throws Exception {
|
||||
System.out.println(type);
|
||||
BeanInfo info = Introspector.getBeanInfo(type);
|
||||
BeanDescriptor bd = info.getBeanDescriptor();
|
||||
|
||||
String description = bd.getShortDescription();
|
||||
System.out.println("description = " + description);
|
||||
|
||||
int dp = info.getDefaultPropertyIndex();
|
||||
System.out.println("property index = " + dp);
|
||||
if (0 <= dp) {
|
||||
String name = info.getPropertyDescriptors()[dp].getName();
|
||||
System.out.println("property name = " + name);
|
||||
}
|
||||
int des = info.getDefaultEventIndex();
|
||||
System.out.println("event set index = " + des);
|
||||
if (0 <= des) {
|
||||
String name = info.getPropertyDescriptors()[des].getName();
|
||||
System.out.println("event set name = " + name);
|
||||
}
|
||||
|
||||
if ((D.class == type) == bd.getName().equals(description)) {
|
||||
throw new Error("unexpected description of the bean");
|
||||
}
|
||||
if ((DP.class == type) == (dp < 0)) {
|
||||
throw new Error("unexpected index of the default property");
|
||||
}
|
||||
if ((DES.class == type) == (des < 0)) {
|
||||
throw new Error("unexpected index of the default event set");
|
||||
}
|
||||
}
|
||||
|
||||
public static class X {
|
||||
}
|
||||
|
||||
@JavaBean(description = "description")
|
||||
public static class D {
|
||||
}
|
||||
|
||||
@JavaBean(defaultProperty = "value")
|
||||
public static class DP {
|
||||
private int value;
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
@JavaBean(defaultEventSet = "action")
|
||||
public static class DES {
|
||||
public void addActionListener(ActionListener listener) {
|
||||
}
|
||||
|
||||
public void removeActionListener(ActionListener listener) {
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.BeanDescriptor;
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.Introspector;
|
||||
import java.util.Objects;
|
||||
import javax.swing.SwingContainer;
|
||||
/*
|
||||
* @test
|
||||
* @bug 4058433
|
||||
* @summary Tests the SwingContainer annotation
|
||||
* @author Sergey Malenkov
|
||||
*/
|
||||
public class TestSwingContainer {
|
||||
public static void main(String[] args) throws Exception {
|
||||
test(X.class, null, null);
|
||||
test(T.class, true, null);
|
||||
test(D.class, true, "method");
|
||||
test(F.class, false, null);
|
||||
test(A.class, false, "method");
|
||||
}
|
||||
|
||||
private static void test(Class<?> type, Object iC, Object cD) throws Exception {
|
||||
System.out.println(type);
|
||||
BeanInfo info = Introspector.getBeanInfo(type);
|
||||
BeanDescriptor bd = info.getBeanDescriptor();
|
||||
test(bd, "isContainer", iC);
|
||||
test(bd, "containerDelegate", cD);
|
||||
}
|
||||
|
||||
private static void test(BeanDescriptor bd, String name, Object expected) {
|
||||
Object value = bd.getValue(name);
|
||||
System.out.println(name + " = " + value);
|
||||
if (!Objects.equals(value, expected)) {
|
||||
throw new Error(name + ": expected = " + expected + "; actual = " + value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class X {
|
||||
}
|
||||
|
||||
@SwingContainer()
|
||||
public static class T {
|
||||
}
|
||||
|
||||
@SwingContainer(delegate = "method")
|
||||
public static class D {
|
||||
}
|
||||
|
||||
@SwingContainer(false)
|
||||
public static class F {
|
||||
}
|
||||
|
||||
@SwingContainer(value = false, delegate = "method")
|
||||
public static class A {
|
||||
}
|
||||
}
|
@ -27,6 +27,7 @@ import java.lang.reflect.Method;
|
||||
* @bug 7084904
|
||||
* @summary Compares reflection and bean introspection
|
||||
* @author Sergey Malenkov
|
||||
* @library ..
|
||||
*/
|
||||
public class Test7084904 {
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
249
jdk/test/java/beans/Performance/Test4058433.java
Normal file
249
jdk/test/java/beans/Performance/Test4058433.java
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.awt.Image;
|
||||
import java.beans.BeanDescriptor;
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.EventSetDescriptor;
|
||||
import java.beans.FeatureDescriptor;
|
||||
import java.beans.IndexedPropertyDescriptor;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.MethodDescriptor;
|
||||
import java.beans.ParameterDescriptor;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4058433
|
||||
* @summary Generates BeanInfo for public classes in AWT, Accessibility, and Swing
|
||||
* @author Sergey Malenkov
|
||||
* @run main/manual Test4058433
|
||||
*/
|
||||
|
||||
public class Test4058433 implements Comparator<Object> {
|
||||
@Override
|
||||
public int compare(Object one, Object two) {
|
||||
if (one instanceof Method && two instanceof Method) {
|
||||
Method oneMethod = (Method) one;
|
||||
Method twoMethod = (Method) two;
|
||||
int result = oneMethod.getName().compareTo(twoMethod.getName());
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (one instanceof FeatureDescriptor && two instanceof FeatureDescriptor) {
|
||||
FeatureDescriptor oneFD = (FeatureDescriptor) one;
|
||||
FeatureDescriptor twoFD = (FeatureDescriptor) two;
|
||||
int result = oneFD.getName().compareTo(twoFD.getName());
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return one.toString().compareTo(two.toString());
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String resource = ClassLoader.getSystemResource("java/lang/Object.class").toString();
|
||||
|
||||
Pattern pattern = Pattern.compile("jar:file:(.*)!.*");
|
||||
Matcher matcher = pattern.matcher(resource);
|
||||
matcher.matches();
|
||||
resource = matcher.group(1);
|
||||
|
||||
TreeSet<Class<?>> types = new TreeSet<>(new Test4058433());
|
||||
try (JarFile jarFile = new JarFile(resource.replaceAll("%20", " "))) {
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
String name = entries.nextElement().getName();
|
||||
if (name.startsWith("java/awt/") || name.startsWith("javax/accessibility/") || name.startsWith("javax/swing/")) {
|
||||
if (name.endsWith(".class")) {
|
||||
name = name.substring(0, name.indexOf(".")).replace('/', '.');
|
||||
Class<?> type = Class.forName(name);
|
||||
if (!type.isInterface() && !type.isEnum() && !type.isAnnotation() && !type.isAnonymousClass()) {
|
||||
if (null == type.getDeclaringClass()) {
|
||||
types.add(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("found " + types.size() + " classes");
|
||||
long time = -System.currentTimeMillis();
|
||||
for (Class<?> type : types) {
|
||||
System.out.println("========================================");
|
||||
BeanInfo info = Introspector.getBeanInfo(type);
|
||||
|
||||
BeanDescriptor bd = info.getBeanDescriptor();
|
||||
System.out.println(bd.getBeanClass());
|
||||
print("customizer", bd.getCustomizerClass());
|
||||
print(bd);
|
||||
print("mono 16x16", info.getIcon(BeanInfo.ICON_MONO_16x16));
|
||||
print("mono 32x32", info.getIcon(BeanInfo.ICON_MONO_32x32));
|
||||
print("color 16x16", info.getIcon(BeanInfo.ICON_COLOR_16x16));
|
||||
print("color 32x32", info.getIcon(BeanInfo.ICON_COLOR_32x32));
|
||||
|
||||
PropertyDescriptor[] pds = info.getPropertyDescriptors();
|
||||
PropertyDescriptor dpd = getDefault(pds, info.getDefaultPropertyIndex());
|
||||
System.out.println(pds.length + " property descriptors");
|
||||
Arrays.sort(pds, new Test4058433());
|
||||
for (PropertyDescriptor pd : pds) {
|
||||
print(pd);
|
||||
if (dpd == pd) {
|
||||
System.out.println("default property");
|
||||
}
|
||||
print("bound", pd.isBound());
|
||||
print("constrained", pd.isConstrained());
|
||||
print("property editor", pd.getPropertyEditorClass());
|
||||
print("property type", pd.getPropertyType());
|
||||
print("read method", pd.getReadMethod());
|
||||
print("write method", pd.getWriteMethod());
|
||||
if (pd instanceof IndexedPropertyDescriptor) {
|
||||
IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;
|
||||
print("indexed property type", ipd.getIndexedPropertyType());
|
||||
print("indexed read method", ipd.getIndexedReadMethod());
|
||||
print("indexed write method", ipd.getIndexedWriteMethod());
|
||||
}
|
||||
}
|
||||
EventSetDescriptor[] esds = info.getEventSetDescriptors();
|
||||
EventSetDescriptor desd = getDefault(esds, info.getDefaultEventIndex());
|
||||
System.out.println(esds.length + " event set descriptors");
|
||||
Arrays.sort(esds, new Test4058433());
|
||||
for (EventSetDescriptor esd : esds) {
|
||||
print(esd);
|
||||
if (desd == esd) {
|
||||
System.out.println("default event set");
|
||||
}
|
||||
print("in default", esd.isInDefaultEventSet());
|
||||
print("unicast", esd.isUnicast());
|
||||
print("listener type", esd.getListenerType());
|
||||
print("get listener method", esd.getGetListenerMethod());
|
||||
print("add listener method", esd.getAddListenerMethod());
|
||||
print("remove listener method", esd.getRemoveListenerMethod());
|
||||
Method[] methods = esd.getListenerMethods();
|
||||
Arrays.sort(methods, new Test4058433());
|
||||
for (Method method : methods) {
|
||||
print("listener method", method);
|
||||
}
|
||||
print(esd.getListenerMethodDescriptors());
|
||||
}
|
||||
print(info.getMethodDescriptors());
|
||||
}
|
||||
time += System.currentTimeMillis();
|
||||
System.out.println("DONE IN " + time + " MS");
|
||||
}
|
||||
|
||||
private static <T> T getDefault(T[] array, int index) {
|
||||
return (index == -1) ? null : array[index];
|
||||
}
|
||||
|
||||
private static void print(MethodDescriptor[] mds) {
|
||||
System.out.println(mds.length + " method descriptors");
|
||||
Arrays.sort(mds, new Test4058433());
|
||||
for (MethodDescriptor md : mds) {
|
||||
print(md);
|
||||
print("method", md.getMethod());
|
||||
ParameterDescriptor[] pds = md.getParameterDescriptors();
|
||||
if (pds != null) {
|
||||
System.out.println(pds.length + " parameter descriptors");
|
||||
for (ParameterDescriptor pd : pds) {
|
||||
print(pd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void print(FeatureDescriptor descriptor) {
|
||||
String name = descriptor.getName();
|
||||
String display = descriptor.getDisplayName();
|
||||
String description = descriptor.getShortDescription();
|
||||
System.out.println("name: " + name);
|
||||
if (!Objects.equals(name, display)) {
|
||||
System.out.println("display name: " + display);
|
||||
}
|
||||
if (!Objects.equals(display, description)) {
|
||||
System.out.println("description: " + description.trim());
|
||||
}
|
||||
print("expert", descriptor.isExpert());
|
||||
print("hidden", descriptor.isHidden());
|
||||
print("preferred", descriptor.isPreferred());
|
||||
TreeMap<String,Object> map = new TreeMap<>();
|
||||
Enumeration<String> enumeration = descriptor.attributeNames();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
String id = enumeration.nextElement();
|
||||
Object value = descriptor.getValue(id);
|
||||
if (value.getClass().isArray()) {
|
||||
TreeSet<String> set = new TreeSet<>();
|
||||
int index = 0;
|
||||
int length = Array.getLength(value);
|
||||
while (index < length) {
|
||||
set.add(Array.get(value, index++) + ", " +
|
||||
Array.get(value, index++) + ", " +
|
||||
Array.get(value, index++));
|
||||
}
|
||||
value = set.toString();
|
||||
}
|
||||
map.put(id, value);
|
||||
}
|
||||
for (Entry<String,Object> entry : map.entrySet()) {
|
||||
System.out.println(entry.getKey() + ": " + entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private static void print(String id, boolean flag) {
|
||||
if (flag) {
|
||||
System.out.println(id + " is set");
|
||||
}
|
||||
}
|
||||
|
||||
private static void print(String id, Class<?> type) {
|
||||
if (type != null) {
|
||||
System.out.println(id + ": " + type.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private static void print(String id, Method method) {
|
||||
if (method != null) {
|
||||
System.out.println(id + ": " + method);
|
||||
}
|
||||
}
|
||||
|
||||
private static void print(String name, Image image) {
|
||||
if (image != null) {
|
||||
System.out.println(name + " icon is exist");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user