changeset 25566:ba387c302edd

4058433: RFE: tool for creating BeanInfo template Reviewed-by: alexsch, serb
author malenkov
date Thu, 03 Jul 2014 16:55:55 +0400
parents ce603b34c98d
children 93f3ca259c48
files jdk/src/share/classes/com/sun/beans/introspect/ClassInfo.java jdk/src/share/classes/com/sun/beans/introspect/EventSetInfo.java jdk/src/share/classes/com/sun/beans/introspect/MethodInfo.java jdk/src/share/classes/com/sun/beans/introspect/PropertyInfo.java jdk/src/share/classes/java/beans/BeanDescriptor.java jdk/src/share/classes/java/beans/BeanProperty.java jdk/src/share/classes/java/beans/EventSetDescriptor.java jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java jdk/src/share/classes/java/beans/Introspector.java jdk/src/share/classes/java/beans/JavaBean.java jdk/src/share/classes/java/beans/PropertyDescriptor.java jdk/src/share/classes/javax/swing/SwingContainer.java jdk/test/java/beans/Introspector/4058433/TestBeanProperty.java jdk/test/java/beans/Introspector/4058433/TestJavaBean.java jdk/test/java/beans/Introspector/4058433/TestSwingContainer.java jdk/test/java/beans/Introspector/7084904/Test7084904.java jdk/test/java/beans/Performance/Test4058433.java
diffstat 17 files changed, 1761 insertions(+), 332 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/beans/introspect/ClassInfo.java	Thu Jul 03 16:55:55 2014 +0400
@@ -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;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/beans/introspect/EventSetInfo.java	Thu Jul 03 16:55:55 2014 +0400
@@ -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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/beans/introspect/MethodInfo.java	Thu Jul 03 16:55:55 2014 +0400
@@ -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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/beans/introspect/PropertyInfo.java	Thu Jul 03 16:55:55 2014 +0400
@@ -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();
+    }
+}
--- a/jdk/src/share/classes/java/beans/BeanDescriptor.java	Wed Jul 02 23:03:27 2014 -0700
+++ b/jdk/src/share/classes/java/beans/BeanDescriptor.java	Thu Jul 03 16:55:55 2014 +0400
@@ -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 @@
             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);
+            }
+        }
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/beans/BeanProperty.java	Thu Jul 03 16:55:55 2014 +0400
@@ -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 {};
+}
--- a/jdk/src/share/classes/java/beans/EventSetDescriptor.java	Wed Jul 02 23:03:27 2014 -0700
+++ b/jdk/src/share/classes/java/beans/EventSetDescriptor.java	Thu Jul 03 16:55:55 2014 +0400
@@ -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 @@
         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>
--- a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java	Wed Jul 02 23:03:27 2014 -0700
+++ b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java	Thu Jul 03 16:55:55 2014 +0400
@@ -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 @@
     }
 
     /**
-     * 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());
     }
 
     /**
--- a/jdk/src/share/classes/java/beans/Introspector.java	Wed Jul 02 23:03:27 2014 -0700
+++ b/jdk/src/share/classes/java/beans/Introspector.java	Thu Jul 03 16:55:55 2014 +0400
@@ -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 @@
     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 @@
             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 @@
                 }
             }
         }
-
         return result;
     }
 
@@ -1003,143 +936,24 @@
             }
 
         } 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);
-                                }
-                            }
-                        }
+            for (Map.Entry<String,EventSetInfo> entry : ClassInfo.get(this.beanClass).getEventSets().entrySet()) {
+                    // generate a list of Method objects for each of the target methods:
+                List<Method> methods = new ArrayList<>();
+                for (Method method : ClassInfo.get(entry.getValue().getListenerType()).getMethods()) {
+                    if (isEventHandler(method)) {
+                        methods.add(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);
-                                }
-                            }
-                        }
-                    }
-                }
+                addEvent(new EventSetDescriptor(
+                        entry.getKey(),
+                        entry.getValue(),
+                        methods.toArray(new Method[methods.size()])));
             }
-
-            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];
-
-                    // 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]);
-                        }
-                    }
-                    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 ...
+            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 @@
             // 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 @@
             }
 
         } 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 @@
         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 @@
                                                  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 @@
                 }
             }
         }
-        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 @@
             // 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;
     }
 
     /**
@@ -1508,19 +1261,6 @@
     }
 
     /**
-     * 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
      * classloader then the class loader of the current Thread.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/beans/JavaBean.java	Thu Jul 03 16:55:55 2014 +0400
@@ -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 "";
+}
--- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java	Wed Jul 02 23:03:27 2014 -0700
+++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java	Thu Jul 03 16:55:55 2014 +0400
@@ -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 @@
     }
 
     /**
-     * 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");
+    PropertyDescriptor(Entry<String,PropertyInfo> entry, boolean bound) {
+        String base = entry.getKey();
+        PropertyInfo info = entry.getValue();
+        setName(Introspector.decapitalize(base));
+        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);
         }
-        setClass0(bean);
-        setName(Introspector.decapitalize(base));
-        setReadMethod(read);
-        setWriteMethod(write);
+        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 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 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();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/javax/swing/SwingContainer.java	Thu Jul 03 16:55:55 2014 +0400
@@ -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 "";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/4058433/TestBeanProperty.java	Thu Jul 03 16:55:55 2014 +0400
@@ -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;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/4058433/TestJavaBean.java	Thu Jul 03 16:55:55 2014 +0400
@@ -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) {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/4058433/TestSwingContainer.java	Thu Jul 03 16:55:55 2014 +0400
@@ -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 {
+    }
+}
--- a/jdk/test/java/beans/Introspector/7084904/Test7084904.java	Wed Jul 02 23:03:27 2014 -0700
+++ b/jdk/test/java/beans/Introspector/7084904/Test7084904.java	Thu Jul 03 16:55:55 2014 +0400
@@ -27,6 +27,7 @@
  * @bug 7084904
  * @summary Compares reflection and bean introspection
  * @author Sergey Malenkov
+ * @library ..
  */
 public class Test7084904 {
     public static void main(String[] args) throws Exception {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Performance/Test4058433.java	Thu Jul 03 16:55:55 2014 +0400
@@ -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");
+        }
+    }
+}