From 2914141733e7a560d030168c5a4ec82dbe444aa0 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Thu, 2 Jul 2009 19:48:11 +0400 Subject: [PATCH 01/10] 6380849: RFE: Automatic discovery of PersistanceDelegates Reviewed-by: rupashka, alexp --- .../com/sun/beans/finder/BeanInfoFinder.java | 102 +++++++++++++ .../com/sun/beans/finder/InstanceFinder.java | 111 ++++++++++++++ .../finder/PersistenceDelegateFinder.java | 63 ++++++++ .../beans/finder/PropertyEditorFinder.java | 81 ++++++++++ jdk/src/share/classes/java/beans/Encoder.java | 23 +-- .../classes/java/beans/Introspector.java | 101 ++++--------- .../java/beans/PropertyEditorManager.java | 96 ++++-------- .../Introspector/6380849/TestBeanInfo.java | 102 +++++++++++++ .../Introspector/6380849/beans/FirstBean.java | 4 + .../6380849/beans/FirstBeanBeanInfo.java | 11 ++ .../6380849/beans/SecondBean.java | 4 + .../Introspector/6380849/beans/ThirdBean.java | 4 + .../6380849/infos/SecondBeanBeanInfo.java | 13 ++ .../6380849/infos/ThirdBeanBeanInfo.java | 11 ++ .../PropertyEditor/6380849/FirstBean.java | 2 + .../6380849/FirstBeanEditor.java | 4 + .../PropertyEditor/6380849/SecondBean.java | 2 + .../6380849/TestPropertyEditor.java | 141 ++++++++++++++++++ .../PropertyEditor/6380849/ThirdBean.java | 2 + .../6380849/editors/SecondBeanEditor.java | 6 + .../6380849/editors/ThirdBeanEditor.java | 6 + .../java/beans/XMLEncoder/6380849/Bean.java | 2 + .../6380849/BeanPersistenceDelegate.java | 5 + .../6380849/TestPersistenceDelegate.java | 60 ++++++++ 24 files changed, 811 insertions(+), 145 deletions(-) create mode 100644 jdk/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java create mode 100644 jdk/src/share/classes/com/sun/beans/finder/InstanceFinder.java create mode 100644 jdk/src/share/classes/com/sun/beans/finder/PersistenceDelegateFinder.java create mode 100644 jdk/src/share/classes/com/sun/beans/finder/PropertyEditorFinder.java create mode 100644 jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java create mode 100644 jdk/test/java/beans/Introspector/6380849/beans/FirstBean.java create mode 100644 jdk/test/java/beans/Introspector/6380849/beans/FirstBeanBeanInfo.java create mode 100644 jdk/test/java/beans/Introspector/6380849/beans/SecondBean.java create mode 100644 jdk/test/java/beans/Introspector/6380849/beans/ThirdBean.java create mode 100644 jdk/test/java/beans/Introspector/6380849/infos/SecondBeanBeanInfo.java create mode 100644 jdk/test/java/beans/Introspector/6380849/infos/ThirdBeanBeanInfo.java create mode 100644 jdk/test/java/beans/PropertyEditor/6380849/FirstBean.java create mode 100644 jdk/test/java/beans/PropertyEditor/6380849/FirstBeanEditor.java create mode 100644 jdk/test/java/beans/PropertyEditor/6380849/SecondBean.java create mode 100644 jdk/test/java/beans/PropertyEditor/6380849/TestPropertyEditor.java create mode 100644 jdk/test/java/beans/PropertyEditor/6380849/ThirdBean.java create mode 100644 jdk/test/java/beans/PropertyEditor/6380849/editors/SecondBeanEditor.java create mode 100644 jdk/test/java/beans/PropertyEditor/6380849/editors/ThirdBeanEditor.java create mode 100644 jdk/test/java/beans/XMLEncoder/6380849/Bean.java create mode 100644 jdk/test/java/beans/XMLEncoder/6380849/BeanPersistenceDelegate.java create mode 100644 jdk/test/java/beans/XMLEncoder/6380849/TestPersistenceDelegate.java diff --git a/jdk/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java b/jdk/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java new file mode 100644 index 00000000000..3e1c37c2d57 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java @@ -0,0 +1,102 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +import java.beans.BeanDescriptor; +import java.beans.BeanInfo; +import java.beans.MethodDescriptor; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; + +/** + * This is utility class that provides functionality + * to find a {@link BeanInfo} for a JavaBean specified by its type. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public final class BeanInfoFinder + extends InstanceFinder { + + private static final String DEFAULT = "sun.beans.infos"; + + public BeanInfoFinder() { + super(BeanInfo.class, true, "BeanInfo", DEFAULT); + } + + private static boolean isValid(Class type, Method method) { + return (method != null) && type.equals(method.getDeclaringClass()); + } + + @Override + protected BeanInfo instantiate(Class type, String name) { + BeanInfo info = super.instantiate(type, name); + if (info != null) { + // make sure that the returned BeanInfo matches the class + BeanDescriptor bd = info.getBeanDescriptor(); + if (bd != null) { + if (type.equals(bd.getBeanClass())) { + return info; + } + } + else { + PropertyDescriptor[] pds = info.getPropertyDescriptors(); + if (pds != null) { + for (PropertyDescriptor pd : pds) { + Method method = pd.getReadMethod(); + if (method == null) { + method = pd.getWriteMethod(); + } + if (isValid(type, method)) { + return info; + } + } + } + else { + MethodDescriptor[] mds = info.getMethodDescriptors(); + if (mds != null) { + for (MethodDescriptor md : mds) { + if (isValid(type, md.getMethod())) { + return info; + } + } + } + } + } + } + return null; + } + + @Override + protected BeanInfo instantiate(Class type, String prefix, String name) { + // this optimization will only use the BeanInfo search path + // if is has changed from the original + // or trying to get the ComponentBeanInfo + return !DEFAULT.equals(prefix) || "ComponentBeanInfo".equals(name) + ? super.instantiate(type, prefix, name) + : null; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/InstanceFinder.java b/jdk/src/share/classes/com/sun/beans/finder/InstanceFinder.java new file mode 100644 index 00000000000..ddf4b80264b --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/InstanceFinder.java @@ -0,0 +1,111 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +/** + * This is utility class that provides basic functionality + * to find an auxiliary class for a JavaBean specified by its type. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +class InstanceFinder { + + private static final String[] EMPTY = { }; + + private final Class type; + private final boolean allow; + private final String suffix; + private String[] packages; + + InstanceFinder(Class type, boolean allow, String suffix, String... packages) { + this.type = type; + this.allow = allow; + this.suffix = suffix; + this.packages = packages.clone(); + } + + public String[] getPackages() { + return (this.packages.length > 0) + ? this.packages.clone() + : this.packages; + } + + public void setPackages(String... packages) { + this.packages = (packages != null) && (packages.length > 0) + ? packages.clone() + : EMPTY; + } + + public T find(Class type) { + if (type == null) { + return null; + } + String name = type.getName() + this.suffix; + T object = instantiate(type, name); + if (object != null) { + return object; + } + if (this.allow) { + object = instantiate(type, null); + if (object != null) { + return object; + } + } + int index = name.lastIndexOf('.') + 1; + if (index > 0) { + name = name.substring(index); + } + for (String prefix : this.packages) { + object = instantiate(type, prefix, name); + if (object != null) { + return object; + } + } + return null; + } + + protected T instantiate(Class type, String name) { + if (type != null) { + try { + if (name != null) { + type = ClassFinder.findClass(name, type.getClassLoader()); + } + if (this.type.isAssignableFrom(type)) { + return (T) type.newInstance(); + } + } + catch (Exception exception) { + // ignore any exceptions + } + } + return null; + } + + protected T instantiate(Class type, String prefix, String name) { + return instantiate(type, prefix + '.' + name); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/PersistenceDelegateFinder.java b/jdk/src/share/classes/com/sun/beans/finder/PersistenceDelegateFinder.java new file mode 100644 index 00000000000..f7638b65ca7 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/PersistenceDelegateFinder.java @@ -0,0 +1,63 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +import java.beans.PersistenceDelegate; +import java.util.HashMap; +import java.util.Map; + +/** + * This is utility class that provides functionality + * to find a {@link PersistenceDelegate} for a JavaBean specified by its type. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public final class PersistenceDelegateFinder + extends InstanceFinder { + + private final Map, PersistenceDelegate> registry; + + public PersistenceDelegateFinder() { + super(PersistenceDelegate.class, true, "PersistenceDelegate"); + this.registry = new HashMap, PersistenceDelegate>(); + } + + public void register(Class type, PersistenceDelegate delegate) { + if (delegate != null) { + this.registry.put(type, delegate); + } + else { + this.registry.remove(type); + } + } + + @Override + public PersistenceDelegate find(Class type) { + PersistenceDelegate delegate = this.registry.get(type); + return (delegate != null) ? delegate : super.find(type); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/PropertyEditorFinder.java b/jdk/src/share/classes/com/sun/beans/finder/PropertyEditorFinder.java new file mode 100644 index 00000000000..604952a1a23 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/PropertyEditorFinder.java @@ -0,0 +1,81 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +import com.sun.beans.WeakCache; + +import java.beans.PropertyEditor; + +import sun.beans.editors.BooleanEditor; +import sun.beans.editors.ByteEditor; +import sun.beans.editors.DoubleEditor; +import sun.beans.editors.EnumEditor; +import sun.beans.editors.FloatEditor; +import sun.beans.editors.IntegerEditor; +import sun.beans.editors.LongEditor; +import sun.beans.editors.ShortEditor; + +/** + * This is utility class that provides functionality + * to find a {@link PropertyEditor} for a JavaBean specified by its type. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public final class PropertyEditorFinder + extends InstanceFinder { + + private final WeakCache, Class> registry; + + public PropertyEditorFinder() { + super(PropertyEditor.class, false, "Editor", "sun.beans.editors"); + + this.registry = new WeakCache, Class>(); + this.registry.put(Byte.TYPE, ByteEditor.class); + this.registry.put(Short.TYPE, ShortEditor.class); + this.registry.put(Integer.TYPE, IntegerEditor.class); + this.registry.put(Long.TYPE, LongEditor.class); + this.registry.put(Boolean.TYPE, BooleanEditor.class); + this.registry.put(Float.TYPE, FloatEditor.class); + this.registry.put(Double.TYPE, DoubleEditor.class); + } + + public void register(Class type, Class editor) { + this.registry.put(type, editor); + } + + @Override + public PropertyEditor find(Class type) { + PropertyEditor editor = instantiate(this.registry.get(type), null); + if (editor == null) { + editor = super.find(type); + if ((editor == null) && (null != type.getEnumConstants())) { + editor = new EnumEditor(type); + } + } + return editor; + } +} diff --git a/jdk/src/share/classes/java/beans/Encoder.java b/jdk/src/share/classes/java/beans/Encoder.java index 2fcd5b5c727..92e3d695bcb 100644 --- a/jdk/src/share/classes/java/beans/Encoder.java +++ b/jdk/src/share/classes/java/beans/Encoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. 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 @@ -24,7 +24,8 @@ */ package java.beans; -import java.util.Collections; +import com.sun.beans.finder.PersistenceDelegateFinder; + import java.util.HashMap; import java.util.IdentityHashMap; import java.util.Map; @@ -45,8 +46,7 @@ import java.util.Map; */ public class Encoder { - private final Map, PersistenceDelegate> delegates - = Collections.synchronizedMap(new HashMap, PersistenceDelegate>()); + private final PersistenceDelegateFinder finder = new PersistenceDelegateFinder(); private Map bindings = new IdentityHashMap(); private ExceptionListener exceptionListener; boolean executeStatements = true; @@ -166,8 +166,13 @@ public class Encoder { * @see java.beans.BeanInfo#getBeanDescriptor */ public PersistenceDelegate getPersistenceDelegate(Class type) { - PersistenceDelegate pd = this.delegates.get(type); - return (pd != null) ? pd : MetaData.getPersistenceDelegate(type); + synchronized (this.finder) { + PersistenceDelegate pd = this.finder.find(type); + if (pd != null) { + return pd; + } + } + return MetaData.getPersistenceDelegate(type); } /** @@ -184,10 +189,8 @@ public class Encoder { public void setPersistenceDelegate(Class type, PersistenceDelegate persistenceDelegate) { - if (persistenceDelegate != null) { - this.delegates.put(type, persistenceDelegate); - } else { - this.delegates.remove(type); + synchronized (this.finder) { + this.finder.register(type, persistenceDelegate); } } diff --git a/jdk/src/share/classes/java/beans/Introspector.java b/jdk/src/share/classes/java/beans/Introspector.java index 6a50cbe7f7d..b43911cf123 100644 --- a/jdk/src/share/classes/java/beans/Introspector.java +++ b/jdk/src/share/classes/java/beans/Introspector.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. 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 @@ -25,6 +25,7 @@ package java.beans; +import com.sun.beans.finder.BeanInfoFinder; import com.sun.beans.finder.ClassFinder; import java.lang.ref.Reference; @@ -45,6 +46,8 @@ import java.util.EventListener; import java.util.List; import java.util.WeakHashMap; import java.util.TreeMap; + +import sun.awt.AppContext; import sun.reflect.misc.ReflectUtil; /** @@ -137,10 +140,6 @@ public class Introspector { // events maps from String names to EventSetDescriptors private Map events; - private final static String DEFAULT_INFO_PATH = "sun.beans.infos"; - - private static String[] searchPath = { DEFAULT_INFO_PATH }; - private final static EventSetDescriptor[] EMPTY_EVENTSETDESCRIPTORS = new EventSetDescriptor[0]; static final String ADD_PREFIX = "add"; @@ -149,7 +148,7 @@ public class Introspector { static final String SET_PREFIX = "set"; static final String IS_PREFIX = "is"; - private static final String BEANINFO_SUFFIX = "BeanInfo"; + private static final Object FINDER_KEY = new Object(); //====================================================================== // Public methods @@ -309,13 +308,11 @@ public class Introspector { * Sun implementation initially sets to {"sun.beans.infos"}. */ - public static synchronized String[] getBeanInfoSearchPath() { - // Return a copy of the searchPath. - String result[] = new String[searchPath.length]; - for (int i = 0; i < searchPath.length; i++) { - result[i] = searchPath[i]; + public static String[] getBeanInfoSearchPath() { + BeanInfoFinder finder = getFinder(); + synchronized (finder) { + return finder.getPackages(); } - return result; } /** @@ -334,12 +331,15 @@ public class Introspector { * @see SecurityManager#checkPropertiesAccess */ - public static synchronized void setBeanInfoSearchPath(String path[]) { + public static void setBeanInfoSearchPath(String[] path) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPropertiesAccess(); } - searchPath = path; + BeanInfoFinder finder = getFinder(); + synchronized (finder) { + finder.setPackages(path); + } } @@ -447,67 +447,14 @@ public class Introspector { * then it checks to see if the class is its own BeanInfo. Finally, * the BeanInfo search path is prepended to the class and searched. * + * @param beanClass the class type of the bean * @return Instance of an explicit BeanInfo class or null if one isn't found. */ - private static synchronized BeanInfo findExplicitBeanInfo(Class beanClass) { - String name = beanClass.getName() + BEANINFO_SUFFIX; - try { - return (java.beans.BeanInfo)instantiate(beanClass, name); - } catch (Exception ex) { - // Just drop through - + private static BeanInfo findExplicitBeanInfo(Class beanClass) { + BeanInfoFinder finder = getFinder(); + synchronized (finder) { + return finder.find(beanClass); } - // Now try checking if the bean is its own BeanInfo. - try { - if (isSubclass(beanClass, java.beans.BeanInfo.class)) { - return (java.beans.BeanInfo)beanClass.newInstance(); - } - } catch (Exception ex) { - // Just drop through - } - // Now try looking for .fooBeanInfo - name = name.substring(name.lastIndexOf('.')+1); - - for (int i = 0; i < searchPath.length; i++) { - // This optimization will only use the BeanInfo search path if is has changed - // from the original or trying to get the ComponentBeanInfo. - if (!DEFAULT_INFO_PATH.equals(searchPath[i]) || - DEFAULT_INFO_PATH.equals(searchPath[i]) && "ComponentBeanInfo".equals(name)) { - try { - String fullName = searchPath[i] + "." + name; - java.beans.BeanInfo bi = (java.beans.BeanInfo)instantiate(beanClass, fullName); - - // Make sure that the returned BeanInfo matches the class. - if (bi.getBeanDescriptor() != null) { - if (bi.getBeanDescriptor().getBeanClass() == beanClass) { - return bi; - } - } else if (bi.getPropertyDescriptors() != null) { - PropertyDescriptor[] pds = bi.getPropertyDescriptors(); - for (int j = 0; j < pds.length; j++) { - Method method = pds[j].getReadMethod(); - if (method == null) { - method = pds[j].getWriteMethod(); - } - if (method != null && method.getDeclaringClass() == beanClass) { - return bi; - } - } - } else if (bi.getMethodDescriptors() != null) { - MethodDescriptor[] mds = bi.getMethodDescriptors(); - for (int j = 0; j < mds.length; j++) { - Method method = mds[j].getMethod(); - if (method != null && method.getDeclaringClass() == beanClass) { - return bi; - } - } - } - } catch (Exception ex) { - // Silently ignore any errors. - } - } - } - return null; } /** @@ -1483,6 +1430,16 @@ public class Introspector { return false; } + private static BeanInfoFinder getFinder() { + AppContext context = AppContext.getAppContext(); + Object object = context.get(FINDER_KEY); + if (object instanceof BeanInfoFinder) { + return (BeanInfoFinder) object; + } + BeanInfoFinder finder = new BeanInfoFinder(); + context.put(FINDER_KEY, finder); + return finder; + } /** * Try to create an instance of a named class. diff --git a/jdk/src/share/classes/java/beans/PropertyEditorManager.java b/jdk/src/share/classes/java/beans/PropertyEditorManager.java index a456c2bff54..d884e9f0c0c 100644 --- a/jdk/src/share/classes/java/beans/PropertyEditorManager.java +++ b/jdk/src/share/classes/java/beans/PropertyEditorManager.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. 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 @@ -25,8 +25,8 @@ package java.beans; -import com.sun.beans.WeakCache; -import sun.beans.editors.*; +import com.sun.beans.finder.PropertyEditorFinder; +import sun.awt.AppContext; /** * The PropertyEditorManager can be used to locate a property editor for @@ -55,6 +55,8 @@ import sun.beans.editors.*; public class PropertyEditorManager { + private static final Object FINDER_KEY = new Object(); + /** * Registers an editor class to edit values of the given target class. * If the editor class is {@code null}, @@ -74,12 +76,15 @@ public class PropertyEditorManager { * * @see SecurityManager#checkPropertiesAccess */ - public static synchronized void registerEditor(Class targetType, Class editorClass) { + public static void registerEditor(Class targetType, Class editorClass) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPropertiesAccess(); } - registry.put(targetType, editorClass); + PropertyEditorFinder finder = getFinder(); + synchronized (finder) { + finder.register(targetType, editorClass); + } } /** @@ -89,46 +94,11 @@ public class PropertyEditorManager { * @return An editor object for the given target class. * The result is null if no suitable editor can be found. */ - public static synchronized PropertyEditor findEditor(Class targetType) { - Class editorClass = registry.get(targetType); - if (editorClass != null) { - try { - Object o = editorClass.newInstance(); - return (PropertyEditor)o; - } catch (Exception ex) { - System.err.println("Couldn't instantiate type editor \"" + - editorClass.getName() + "\" : " + ex); - } + public static PropertyEditor findEditor(Class targetType) { + PropertyEditorFinder finder = getFinder(); + synchronized (finder) { + return finder.find(targetType); } - - // Now try adding "Editor" to the class name. - - String editorName = targetType.getName() + "Editor"; - try { - return (PropertyEditor) Introspector.instantiate(targetType, editorName); - } catch (Exception ex) { - // Silently ignore any errors. - } - - // Now try looking for .fooEditor - int index = editorName.lastIndexOf('.') + 1; - if (index > 0) { - editorName = editorName.substring(index); - } - for (String path : searchPath) { - String name = path + '.' + editorName; - try { - return (PropertyEditor) Introspector.instantiate(targetType, name); - } catch (Exception ex) { - // Silently ignore any errors. - } - } - - if (null != targetType.getEnumConstants()) { - return new EnumEditor(targetType); - } - // We couldn't find a suitable Editor. - return null; } /** @@ -139,8 +109,11 @@ public class PropertyEditorManager { *

The default value for this array is implementation-dependent, * e.g. Sun implementation initially sets to {"sun.beans.editors"}. */ - public static synchronized String[] getEditorSearchPath() { - return searchPath.clone(); + public static String[] getEditorSearchPath() { + PropertyEditorFinder finder = getFinder(); + synchronized (finder) { + return finder.getPackages(); + } } /** @@ -156,28 +129,25 @@ public class PropertyEditorManager { * of system properties. * @see SecurityManager#checkPropertiesAccess */ - public static synchronized void setEditorSearchPath(String[] path) { + public static void setEditorSearchPath(String[] path) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPropertiesAccess(); } - searchPath = (path != null) - ? path.clone() - : EMPTY; + PropertyEditorFinder finder = getFinder(); + synchronized (finder) { + finder.setPackages(path); + } } - private static String[] searchPath = { "sun.beans.editors" }; - private static final String[] EMPTY = {}; - private static final WeakCache, Class> registry; - - static { - registry = new WeakCache, Class>(); - registry.put(Byte.TYPE, ByteEditor.class); - registry.put(Short.TYPE, ShortEditor.class); - registry.put(Integer.TYPE, IntegerEditor.class); - registry.put(Long.TYPE, LongEditor.class); - registry.put(Boolean.TYPE, BooleanEditor.class); - registry.put(Float.TYPE, FloatEditor.class); - registry.put(Double.TYPE, DoubleEditor.class); + private static PropertyEditorFinder getFinder() { + AppContext context = AppContext.getAppContext(); + Object object = context.get(FINDER_KEY); + if (object instanceof PropertyEditorFinder) { + return (PropertyEditorFinder) object; + } + PropertyEditorFinder finder = new PropertyEditorFinder(); + context.put(FINDER_KEY, finder); + return finder; } } diff --git a/jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java b/jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java new file mode 100644 index 00000000000..b149bffb820 --- /dev/null +++ b/jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java @@ -0,0 +1,102 @@ +/** + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6380849 + * @summary Tests BeanInfo finder + * @author Sergey Malenkov + */ + +import beans.FirstBean; +import beans.FirstBeanBeanInfo; +import beans.SecondBean; +import beans.ThirdBean; + +import infos.SecondBeanBeanInfo; +import infos.ThirdBeanBeanInfo; + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.lang.reflect.Field; + +import sun.awt.SunToolkit; + +public class TestBeanInfo implements Runnable { + + private static final String[] SEARCH_PATH = { "infos" }; // NON-NLS: package name + + public static void main(String[] args) throws InterruptedException { + TestBeanInfo test = new TestBeanInfo(); + test.run(); + // the following tests fails on previous build + ThreadGroup group = new ThreadGroup("$$$"); // NON-NLS: unique thread name + Thread thread = new Thread(group, test); + thread.start(); + thread.join(); + } + + private static void test(Class type, Class expected) { + BeanInfo actual; + try { + actual = Introspector.getBeanInfo(type); + type = actual.getClass(); + Field field = type.getDeclaredField("targetBeanInfo"); // NON-NLS: field name + field.setAccessible(true); + actual = (BeanInfo) field.get(actual); + } + catch (Exception exception) { + throw new Error("unexpected error", exception); + } + if ((actual == null) && (expected != null)) { + throw new Error("expected info is not found"); + } + if ((actual != null) && !actual.getClass().equals(expected)) { + throw new Error("found unexpected info"); + } + } + + private boolean passed; + + public void run() { + if (this.passed) { + SunToolkit.createNewAppContext(); + } + Introspector.flushCaches(); + + test(FirstBean.class, FirstBeanBeanInfo.class); + test(SecondBean.class, null); + test(ThirdBean.class, null); + test(ThirdBeanBeanInfo.class, ThirdBeanBeanInfo.class); + + Introspector.setBeanInfoSearchPath(SEARCH_PATH); + Introspector.flushCaches(); + + test(FirstBean.class, FirstBeanBeanInfo.class); + test(SecondBean.class, SecondBeanBeanInfo.class); + test(ThirdBean.class, null); + test(ThirdBeanBeanInfo.class, ThirdBeanBeanInfo.class); + + this.passed = true; + } +} diff --git a/jdk/test/java/beans/Introspector/6380849/beans/FirstBean.java b/jdk/test/java/beans/Introspector/6380849/beans/FirstBean.java new file mode 100644 index 00000000000..cafb44e0bab --- /dev/null +++ b/jdk/test/java/beans/Introspector/6380849/beans/FirstBean.java @@ -0,0 +1,4 @@ +package beans; + +public class FirstBean { +} diff --git a/jdk/test/java/beans/Introspector/6380849/beans/FirstBeanBeanInfo.java b/jdk/test/java/beans/Introspector/6380849/beans/FirstBeanBeanInfo.java new file mode 100644 index 00000000000..f4d1355703e --- /dev/null +++ b/jdk/test/java/beans/Introspector/6380849/beans/FirstBeanBeanInfo.java @@ -0,0 +1,11 @@ +package beans; + +import java.beans.BeanDescriptor; +import java.beans.SimpleBeanInfo; + +public class FirstBeanBeanInfo extends SimpleBeanInfo { + @Override + public BeanDescriptor getBeanDescriptor() { + return new BeanDescriptor(FirstBean.class); + } +} diff --git a/jdk/test/java/beans/Introspector/6380849/beans/SecondBean.java b/jdk/test/java/beans/Introspector/6380849/beans/SecondBean.java new file mode 100644 index 00000000000..fbde3902724 --- /dev/null +++ b/jdk/test/java/beans/Introspector/6380849/beans/SecondBean.java @@ -0,0 +1,4 @@ +package beans; + +public class SecondBean { +} diff --git a/jdk/test/java/beans/Introspector/6380849/beans/ThirdBean.java b/jdk/test/java/beans/Introspector/6380849/beans/ThirdBean.java new file mode 100644 index 00000000000..8fb8b9a92b8 --- /dev/null +++ b/jdk/test/java/beans/Introspector/6380849/beans/ThirdBean.java @@ -0,0 +1,4 @@ +package beans; + +public class ThirdBean { +} diff --git a/jdk/test/java/beans/Introspector/6380849/infos/SecondBeanBeanInfo.java b/jdk/test/java/beans/Introspector/6380849/infos/SecondBeanBeanInfo.java new file mode 100644 index 00000000000..999a6df9040 --- /dev/null +++ b/jdk/test/java/beans/Introspector/6380849/infos/SecondBeanBeanInfo.java @@ -0,0 +1,13 @@ +package infos; + +import beans.SecondBean; + +import java.beans.BeanDescriptor; +import java.beans.SimpleBeanInfo; + +public class SecondBeanBeanInfo extends SimpleBeanInfo { + @Override + public BeanDescriptor getBeanDescriptor() { + return new BeanDescriptor(SecondBean.class); + } +} diff --git a/jdk/test/java/beans/Introspector/6380849/infos/ThirdBeanBeanInfo.java b/jdk/test/java/beans/Introspector/6380849/infos/ThirdBeanBeanInfo.java new file mode 100644 index 00000000000..7d295bd07b3 --- /dev/null +++ b/jdk/test/java/beans/Introspector/6380849/infos/ThirdBeanBeanInfo.java @@ -0,0 +1,11 @@ +package infos; + +import java.beans.BeanDescriptor; +import java.beans.SimpleBeanInfo; + +public class ThirdBeanBeanInfo extends SimpleBeanInfo { + @Override + public BeanDescriptor getBeanDescriptor() { + return new BeanDescriptor(ThirdBeanBeanInfo.class); + } +} diff --git a/jdk/test/java/beans/PropertyEditor/6380849/FirstBean.java b/jdk/test/java/beans/PropertyEditor/6380849/FirstBean.java new file mode 100644 index 00000000000..e112dbfaa7e --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/6380849/FirstBean.java @@ -0,0 +1,2 @@ +public class FirstBean { +} diff --git a/jdk/test/java/beans/PropertyEditor/6380849/FirstBeanEditor.java b/jdk/test/java/beans/PropertyEditor/6380849/FirstBeanEditor.java new file mode 100644 index 00000000000..8a227be21fe --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/6380849/FirstBeanEditor.java @@ -0,0 +1,4 @@ +import java.beans.PropertyEditorSupport; + +public class FirstBeanEditor extends PropertyEditorSupport { +} diff --git a/jdk/test/java/beans/PropertyEditor/6380849/SecondBean.java b/jdk/test/java/beans/PropertyEditor/6380849/SecondBean.java new file mode 100644 index 00000000000..51eea295806 --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/6380849/SecondBean.java @@ -0,0 +1,2 @@ +public class SecondBean { +} diff --git a/jdk/test/java/beans/PropertyEditor/6380849/TestPropertyEditor.java b/jdk/test/java/beans/PropertyEditor/6380849/TestPropertyEditor.java new file mode 100644 index 00000000000..f7f4d1b1ad1 --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/6380849/TestPropertyEditor.java @@ -0,0 +1,141 @@ +/** + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6380849 + * @summary Tests PropertyEditor finder + * @author Sergey Malenkov + */ + +import editors.SecondBeanEditor; +import editors.ThirdBeanEditor; + +import java.awt.Color; +import java.awt.Font; +import java.beans.PropertyEditor; +import java.beans.PropertyEditorManager; + +import sun.awt.SunToolkit; +import sun.beans.editors.BooleanEditor; +import sun.beans.editors.ByteEditor; +import sun.beans.editors.ColorEditor; +import sun.beans.editors.DoubleEditor; +import sun.beans.editors.EnumEditor; +import sun.beans.editors.FloatEditor; +import sun.beans.editors.FontEditor; +import sun.beans.editors.IntegerEditor; +import sun.beans.editors.LongEditor; +import sun.beans.editors.ShortEditor; +import sun.beans.editors.StringEditor; + +public class TestPropertyEditor implements Runnable { + + private enum Enumeration { + FIRST, SECOND, THIRD + } + + private static final String[] SEARCH_PATH = { "editors" }; // NON-NLS: package name + + public static void main(String[] args) throws InterruptedException { + TestPropertyEditor test = new TestPropertyEditor(); + test.run(); + // the following tests fails on previous build + ThreadGroup group = new ThreadGroup("$$$"); // NON-NLS: unique thread name + Thread thread = new Thread(group, test); + thread.start(); + thread.join(); + } + + private static void test(Class type, Class expected) { + PropertyEditor actual = PropertyEditorManager.findEditor(type); + if ((actual == null) && (expected != null)) { + throw new Error("expected editor is not found"); + } + if ((actual != null) && !actual.getClass().equals(expected)) { + throw new Error("found unexpected editor"); + } + } + + private boolean passed; + + public void run() { + if (this.passed) { + SunToolkit.createNewAppContext(); + } + PropertyEditorManager.registerEditor(ThirdBean.class, ThirdBeanEditor.class); + + test(FirstBean.class, FirstBeanEditor.class); + test(SecondBean.class, null); + test(ThirdBean.class, ThirdBeanEditor.class); + // test editors for default primitive types + test(Byte.TYPE, ByteEditor.class); + test(Short.TYPE, ShortEditor.class); + test(Integer.TYPE, IntegerEditor.class); + test(Long.TYPE, LongEditor.class); + test(Boolean.TYPE, BooleanEditor.class); + test(Float.TYPE, FloatEditor.class); + test(Double.TYPE, DoubleEditor.class); + // test editors for default object types + test(Byte.class, ByteEditor.class); + test(Short.class, ShortEditor.class); + test(Integer.class, IntegerEditor.class); + test(Long.class, LongEditor.class); + test(Boolean.class, BooleanEditor.class); + test(Float.class, FloatEditor.class); + test(Double.class, DoubleEditor.class); + test(String.class, StringEditor.class); + test(Color.class, ColorEditor.class); + test(Font.class, FontEditor.class); + test(Enumeration.class, EnumEditor.class); + + PropertyEditorManager.registerEditor(ThirdBean.class, null); + PropertyEditorManager.setEditorSearchPath(SEARCH_PATH); + + test(FirstBean.class, FirstBeanEditor.class); + test(SecondBean.class, SecondBeanEditor.class); + test(ThirdBean.class, ThirdBeanEditor.class); + // test editors for default primitive types + test(Byte.TYPE, ByteEditor.class); + test(Short.TYPE, ShortEditor.class); + test(Integer.TYPE, IntegerEditor.class); + test(Long.TYPE, LongEditor.class); + test(Boolean.TYPE, BooleanEditor.class); + test(Float.TYPE, FloatEditor.class); + test(Double.TYPE, DoubleEditor.class); + // test editors for default object types + test(Byte.class, null); + test(Short.class, null); + test(Integer.class, null); + test(Long.class, null); + test(Boolean.class, null); + test(Float.class, null); + test(Double.class, null); + test(String.class, null); + test(Color.class, null); + test(Font.class, null); + test(Enumeration.class, EnumEditor.class); + + this.passed = true; + } +} diff --git a/jdk/test/java/beans/PropertyEditor/6380849/ThirdBean.java b/jdk/test/java/beans/PropertyEditor/6380849/ThirdBean.java new file mode 100644 index 00000000000..094ab830efb --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/6380849/ThirdBean.java @@ -0,0 +1,2 @@ +public class ThirdBean { +} diff --git a/jdk/test/java/beans/PropertyEditor/6380849/editors/SecondBeanEditor.java b/jdk/test/java/beans/PropertyEditor/6380849/editors/SecondBeanEditor.java new file mode 100644 index 00000000000..e8b48e0f2ea --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/6380849/editors/SecondBeanEditor.java @@ -0,0 +1,6 @@ +package editors; + +import java.beans.PropertyEditorSupport; + +public class SecondBeanEditor extends PropertyEditorSupport { +} diff --git a/jdk/test/java/beans/PropertyEditor/6380849/editors/ThirdBeanEditor.java b/jdk/test/java/beans/PropertyEditor/6380849/editors/ThirdBeanEditor.java new file mode 100644 index 00000000000..14bf7b8d168 --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/6380849/editors/ThirdBeanEditor.java @@ -0,0 +1,6 @@ +package editors; + +import java.beans.PropertyEditorSupport; + +public class ThirdBeanEditor extends PropertyEditorSupport { +} diff --git a/jdk/test/java/beans/XMLEncoder/6380849/Bean.java b/jdk/test/java/beans/XMLEncoder/6380849/Bean.java new file mode 100644 index 00000000000..54145979197 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6380849/Bean.java @@ -0,0 +1,2 @@ +public class Bean { +} diff --git a/jdk/test/java/beans/XMLEncoder/6380849/BeanPersistenceDelegate.java b/jdk/test/java/beans/XMLEncoder/6380849/BeanPersistenceDelegate.java new file mode 100644 index 00000000000..34278b419e6 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6380849/BeanPersistenceDelegate.java @@ -0,0 +1,5 @@ +import java.beans.DefaultPersistenceDelegate; + +public class BeanPersistenceDelegate + extends DefaultPersistenceDelegate { +} diff --git a/jdk/test/java/beans/XMLEncoder/6380849/TestPersistenceDelegate.java b/jdk/test/java/beans/XMLEncoder/6380849/TestPersistenceDelegate.java new file mode 100644 index 00000000000..35dde1ab794 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6380849/TestPersistenceDelegate.java @@ -0,0 +1,60 @@ +/** + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6380849 + * @summary Tests PersistenceDelegate finder + * @author Sergey Malenkov + */ + +import java.beans.PersistenceDelegate; +import java.beans.XMLEncoder; +import java.beans.DefaultPersistenceDelegate; + +public class TestPersistenceDelegate { + + private static final XMLEncoder ENCODER = new XMLEncoder(System.out); + + public static void main(String[] args) throws InterruptedException { + Class type = TestPersistenceDelegate.class; + test(type, DefaultPersistenceDelegate.class); + ENCODER.setPersistenceDelegate(type, new BeanPersistenceDelegate()); + test(type, BeanPersistenceDelegate.class); + ENCODER.setPersistenceDelegate(type, null); + test(type, DefaultPersistenceDelegate.class); + // the following tests fails on previous build + test(Bean.class, BeanPersistenceDelegate.class); + test(BeanPersistenceDelegate.class, BeanPersistenceDelegate.class); + } + + private static void test(Class type, Class expected) { + PersistenceDelegate actual = ENCODER.getPersistenceDelegate(type); + if ((actual == null) && (expected != null)) { + throw new Error("expected delegate is not found"); + } + if ((actual != null) && !actual.getClass().equals(expected)) { + throw new Error("found unexpected delegate"); + } + } +} From 64bc185e5502ed93d84f3106038b55cb5b7e6dd9 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 3 Jul 2009 16:56:29 +0400 Subject: [PATCH 02/10] 6329581: RFE: LTP: java.beans.XMLEncoder does not manage ClassLoader Reviewed-by: rupashka, alexp --- jdk/src/share/classes/java/beans/Encoder.java | 11 ++- .../share/classes/java/beans/MetaData.java | 6 +- .../share/classes/java/beans/Statement.java | 3 +- .../beans/XMLEncoder/6329581/Test6329581.java | 75 +++++++++++++++++++ 4 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 jdk/test/java/beans/XMLEncoder/6329581/Test6329581.java diff --git a/jdk/src/share/classes/java/beans/Encoder.java b/jdk/src/share/classes/java/beans/Encoder.java index 92e3d695bcb..e7f63397340 100644 --- a/jdk/src/share/classes/java/beans/Encoder.java +++ b/jdk/src/share/classes/java/beans/Encoder.java @@ -246,12 +246,11 @@ public class Encoder { for (int i = 0; i < oldArgs.length; i++) { newArgs[i] = writeObject1(oldArgs[i]); } - if (oldExp.getClass() == Statement.class) { - return new Statement(newTarget, oldExp.getMethodName(), newArgs); - } - else { - return new Expression(newTarget, oldExp.getMethodName(), newArgs); - } + Statement newExp = Statement.class.equals(oldExp.getClass()) + ? new Statement(newTarget, oldExp.getMethodName(), newArgs) + : new Expression(newTarget, oldExp.getMethodName(), newArgs); + newExp.loader = oldExp.loader; + return newExp; } /** diff --git a/jdk/src/share/classes/java/beans/MetaData.java b/jdk/src/share/classes/java/beans/MetaData.java index f4d307090a5..96607db806f 100644 --- a/jdk/src/share/classes/java/beans/MetaData.java +++ b/jdk/src/share/classes/java/beans/MetaData.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. 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 @@ -219,7 +219,9 @@ class java_lang_Class_PersistenceDelegate extends PersistenceDelegate { return new Expression(oldInstance, String.class, "getClass", new Object[]{}); } else { - return new Expression(oldInstance, Class.class, "forName", new Object[]{c.getName()}); + Expression newInstance = new Expression(oldInstance, Class.class, "forName", new Object[] { c.getName() }); + newInstance.loader = c.getClassLoader(); + return newInstance; } } } diff --git a/jdk/src/share/classes/java/beans/Statement.java b/jdk/src/share/classes/java/beans/Statement.java index 7bf2fccda56..6169f92742f 100644 --- a/jdk/src/share/classes/java/beans/Statement.java +++ b/jdk/src/share/classes/java/beans/Statement.java @@ -66,6 +66,7 @@ public class Statement { Object target; String methodName; Object[] arguments; + ClassLoader loader; /** * Creates a new Statement object with a target, @@ -157,7 +158,7 @@ public class Statement { // of core from a class inside core. Special // case this method. if (target == Class.class && methodName.equals("forName")) { - return ClassFinder.resolveClass((String)arguments[0]); + return ClassFinder.resolveClass((String)arguments[0], this.loader); } Class[] argClasses = new Class[arguments.length]; for(int i = 0; i < arguments.length; i++) { diff --git a/jdk/test/java/beans/XMLEncoder/6329581/Test6329581.java b/jdk/test/java/beans/XMLEncoder/6329581/Test6329581.java new file mode 100644 index 00000000000..c307dab1267 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6329581/Test6329581.java @@ -0,0 +1,75 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6329581 + * @summary Tests encoding of a class with custom ClassLoader + * @author Sergey Malenkov + */ + +import java.beans.ExceptionListener; +import java.beans.XMLDecoder; +import java.beans.XMLEncoder; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +public class Test6329581 implements ExceptionListener { + + public static void main(String[] args) throws Exception { + ExceptionListener listener = new Test6329581(); + // write bean to byte array + ByteArrayOutputStream out = new ByteArrayOutputStream(); + XMLEncoder encoder = new XMLEncoder(out); + encoder.setExceptionListener(listener); + encoder.writeObject(getClassLoader("beans.jar").loadClass("test.Bean").newInstance()); + encoder.close(); + // read bean from byte array + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + XMLDecoder decoder = new XMLDecoder(in, null, listener, getClassLoader("beans.jar")); + Object object = decoder.readObject(); + decoder.close(); + + if (!object.getClass().getClassLoader().getClass().equals(URLClassLoader.class)) { + throw new Error("bean is loaded with unexpected class loader"); + } + } + + private static ClassLoader getClassLoader(String name) throws Exception { + StringBuilder sb = new StringBuilder(256); + sb.append("file:"); + sb.append(System.getProperty("test.src", ".")); + sb.append(File.separatorChar); + sb.append(name); + + URL[] url = { new URL(sb.toString()) }; + return new URLClassLoader(url); + } + + public void exceptionThrown(Exception exception) { + throw new Error("unexpected exception", exception); + } +} From 8a5359c35b6c2af54520afd00bc6b86c3b43eb86 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Mon, 6 Jul 2009 14:32:04 +0400 Subject: [PATCH 03/10] 6723447: Introspector doesn't check return type for indexed property setters Reviewed-by: rupashka --- .../java/beans/IndexedPropertyDescriptor.java | 7 +- .../classes/java/beans/Introspector.java | 6 +- .../java/beans/PropertyDescriptor.java | 7 +- .../java/beans/Introspector/Test6723447.java | 88 +++++++++++++++++++ 4 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 jdk/test/java/beans/Introspector/Test6723447.java diff --git a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java index fa5b404c239..e0d2bb4bb4f 100644 --- a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java +++ b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. 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 @@ -274,6 +274,11 @@ perty. } indexedWriteMethod = Introspector.findMethod(cls, indexedWriteMethodName, 2, (type == null) ? null : new Class[] { int.class, type }); + if (indexedWriteMethod != null) { + if (!indexedWriteMethod.getReturnType().equals(void.class)) { + indexedWriteMethod = null; + } + } setIndexedWriteMethod0(indexedWriteMethod); } return indexedWriteMethod; diff --git a/jdk/src/share/classes/java/beans/Introspector.java b/jdk/src/share/classes/java/beans/Introspector.java index b43911cf123..1c90f205a88 100644 --- a/jdk/src/share/classes/java/beans/Introspector.java +++ b/jdk/src/share/classes/java/beans/Introspector.java @@ -524,9 +524,9 @@ public class Introspector { pd = new PropertyDescriptor(this.beanClass, name.substring(2), method, null); } } else if (argCount == 1) { - if (argTypes[0] == int.class && name.startsWith(GET_PREFIX)) { + if (int.class.equals(argTypes[0]) && name.startsWith(GET_PREFIX)) { pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, method, null); - } else if (resultType == void.class && name.startsWith(SET_PREFIX)) { + } 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)) { @@ -534,7 +534,7 @@ public class Introspector { } } } else if (argCount == 2) { - if (argTypes[0] == int.class && name.startsWith(SET_PREFIX)) { + 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); diff --git a/jdk/src/share/classes/java/beans/PropertyDescriptor.java b/jdk/src/share/classes/java/beans/PropertyDescriptor.java index 08ae9a45f42..70a539c81fd 100644 --- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java +++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. 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 @@ -294,6 +294,11 @@ public class PropertyDescriptor extends FeatureDescriptor { writeMethod = Introspector.findMethod(cls, writeMethodName, 1, (type == null) ? null : new Class[] { type }); + if (writeMethod != null) { + if (!writeMethod.getReturnType().equals(void.class)) { + writeMethod = null; + } + } try { setWriteMethod(writeMethod); } catch (IntrospectionException ex) { diff --git a/jdk/test/java/beans/Introspector/Test6723447.java b/jdk/test/java/beans/Introspector/Test6723447.java new file mode 100644 index 00000000000..04a3ca632d0 --- /dev/null +++ b/jdk/test/java/beans/Introspector/Test6723447.java @@ -0,0 +1,88 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6723447 + * @summary Tests return type for property setters + * @author Sergey Malenkov + */ + +import java.beans.IndexedPropertyDescriptor; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; +import java.math.BigDecimal; + +public class Test6723447 { + + public static void main(String[] args) { + test(Test6723447.class); + test(BigDecimal.class); + } + + private static void test(Class type) { + for (PropertyDescriptor pd : getPropertyDescriptors(type)) { + test(pd.getWriteMethod()); + if (pd instanceof IndexedPropertyDescriptor) { + IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd; + test(ipd.getIndexedWriteMethod()); + } + } + } + + private static void test(Method method) { + if (method != null) { + Class type = method.getReturnType(); + if (!type.equals(void.class)) { + throw new Error("unexpected return type: " + type); + } + } + } + + private static PropertyDescriptor[] getPropertyDescriptors(Class type) { + try { + return Introspector.getBeanInfo(type).getPropertyDescriptors(); + } + catch (IntrospectionException exception) { + throw new Error("unexpected exception", exception); + } + } + + public Object getValue() { + return null; + } + + public Object setValue(Object value) { + return value; + } + + public Object getValues(int index) { + return null; + } + + public Object setValues(int index, Object value) { + return value; + } +} From f3358ba3db77de135e196b2b2dc57617420c5b06 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Tue, 7 Jul 2009 14:11:06 +0400 Subject: [PATCH 04/10] 6489447: Apply the more robust fix for 6449933 to dolphin and 6ux Reviewed-by: malenkov --- jdk/src/windows/native/sun/windows/ShellFolder2.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/jdk/src/windows/native/sun/windows/ShellFolder2.cpp b/jdk/src/windows/native/sun/windows/ShellFolder2.cpp index 6799b098218..64eea69bced 100644 --- a/jdk/src/windows/native/sun/windows/ShellFolder2.cpp +++ b/jdk/src/windows/native/sun/windows/ShellFolder2.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. 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 @@ -981,6 +981,15 @@ JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getFileChooserB hBitmap = (HBITMAP)LoadImage(libShell32, IS_WINVISTA ? TEXT("IDB_TB_SH_DEF_16") : MAKEINTRESOURCE(216), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); + + if (hBitmap == NULL) { + // version of shell32.dll doesn't match OS version. + // So we either are in a Vista Compatibility Mode + // or shell32.dll was copied from OS of another version + hBitmap = (HBITMAP)LoadImage(libShell32, + IS_WINVISTA ? MAKEINTRESOURCE(216) : TEXT("IDB_TB_SH_DEF_16"), + IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); + } } if (hBitmap == NULL) { libComCtl32 = LoadLibrary(TEXT("comctl32.dll")); From b3f3644fea86f475e02ba7b139f30e7a0e191695 Mon Sep 17 00:00:00 2001 From: Anthony Petrov Date: Tue, 7 Jul 2009 17:05:50 +0400 Subject: [PATCH 05/10] 6853916: java.awt.Window.setBackground(null) throws NullPointerException Window.setBackground() should check for null. Reviewed-by: art, dcherepanov --- jdk/src/share/classes/java/awt/Window.java | 2 +- .../SetBackgroundNPE/SetBackgroundNPE.java | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/awt/Window/SetBackgroundNPE/SetBackgroundNPE.java diff --git a/jdk/src/share/classes/java/awt/Window.java b/jdk/src/share/classes/java/awt/Window.java index aac5d3789da..31c94ca77e5 100644 --- a/jdk/src/share/classes/java/awt/Window.java +++ b/jdk/src/share/classes/java/awt/Window.java @@ -3597,7 +3597,7 @@ public class Window extends Container implements Accessible { return; } int oldAlpha = oldBg != null ? oldBg.getAlpha() : 255; - int alpha = bgColor.getAlpha(); + int alpha = bgColor != null ? bgColor.getAlpha() : 255; if ((oldAlpha == 255) && (alpha < 255)) { // non-opaque window GraphicsConfiguration gc = getGraphicsConfiguration(); GraphicsDevice gd = gc.getDevice(); diff --git a/jdk/test/java/awt/Window/SetBackgroundNPE/SetBackgroundNPE.java b/jdk/test/java/awt/Window/SetBackgroundNPE/SetBackgroundNPE.java new file mode 100644 index 00000000000..10c9ac72e0f --- /dev/null +++ b/jdk/test/java/awt/Window/SetBackgroundNPE/SetBackgroundNPE.java @@ -0,0 +1,38 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + @test + @bug 6853916 + @summary Window.setBackground() should not throw NPE + @author anthony.petrov@sun.com: area=awt.toplevel + @run main SetBackgroundNPE +*/ + +import java.awt.Window; + +public class SetBackgroundNPE { + public static void main(String args[]) { + new Window(null).setBackground(null); + } +} From 74d89957476c683d095d1d99325184e82b4cd1fc Mon Sep 17 00:00:00 2001 From: Dmitry Cherepanov Date: Thu, 9 Jul 2009 15:15:28 -0400 Subject: [PATCH 06/10] 6855323: Robot(GraphicsDevice) constructor initializes LEGAL_BUTTON_MASK variable improperly Reviewed-by: art --- jdk/src/share/classes/java/awt/Robot.java | 41 ++++++----- .../java/awt/Robot/CtorTest/CtorTest.java | 71 +++++++++++++++++++ 2 files changed, 94 insertions(+), 18 deletions(-) create mode 100644 jdk/test/java/awt/Robot/CtorTest/CtorTest.java diff --git a/jdk/src/share/classes/java/awt/Robot.java b/jdk/src/share/classes/java/awt/Robot.java index f7a40c740bc..1233c291a3e 100644 --- a/jdk/src/share/classes/java/awt/Robot.java +++ b/jdk/src/share/classes/java/awt/Robot.java @@ -70,7 +70,7 @@ public class Robot { private RobotPeer peer; private boolean isAutoWaitForIdle = false; private int autoDelay = 0; - private static int LEGAL_BUTTON_MASK; + private static int LEGAL_BUTTON_MASK = 0; // location of robot's GC, used in mouseMove(), getPixelColor() and captureScreenImage() private Point gdLoc; @@ -95,23 +95,6 @@ public class Robot { } init(GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice()); - int tmpMask = 0; - - if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ - if (Toolkit.getDefaultToolkit() instanceof SunToolkit) { - final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons(); - for (int i = 0; i < buttonsNumber; i++){ - tmpMask |= InputEvent.getMaskForButton(i+1); - } - } - } - tmpMask |= InputEvent.BUTTON1_MASK| - InputEvent.BUTTON2_MASK| - InputEvent.BUTTON3_MASK| - InputEvent.BUTTON1_DOWN_MASK| - InputEvent.BUTTON2_DOWN_MASK| - InputEvent.BUTTON3_DOWN_MASK; - LEGAL_BUTTON_MASK = tmpMask; } /** @@ -156,6 +139,28 @@ public class Robot { disposer = new RobotDisposer(peer); sun.java2d.Disposer.addRecord(anchor, disposer); } + initLegalButtonMask(); + } + + private static synchronized void initLegalButtonMask() { + if (LEGAL_BUTTON_MASK != 0) return; + + int tmpMask = 0; + if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + if (Toolkit.getDefaultToolkit() instanceof SunToolkit) { + final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons(); + for (int i = 0; i < buttonsNumber; i++){ + tmpMask |= InputEvent.getMaskForButton(i+1); + } + } + } + tmpMask |= InputEvent.BUTTON1_MASK| + InputEvent.BUTTON2_MASK| + InputEvent.BUTTON3_MASK| + InputEvent.BUTTON1_DOWN_MASK| + InputEvent.BUTTON2_DOWN_MASK| + InputEvent.BUTTON3_DOWN_MASK; + LEGAL_BUTTON_MASK = tmpMask; } /* determine if the security policy allows Robot's to be created */ diff --git a/jdk/test/java/awt/Robot/CtorTest/CtorTest.java b/jdk/test/java/awt/Robot/CtorTest/CtorTest.java new file mode 100644 index 00000000000..ea9c56fa2d5 --- /dev/null +++ b/jdk/test/java/awt/Robot/CtorTest/CtorTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + @test + @bug 6855323 + @summary Robot(GraphicsDevice) constructor initializes LEGAL_BUTTON_MASK variable improperly + @author Dmitry Cherepanov area=awt.robot + @run main CtorTest +*/ + +/** + * CtorRobot.java + * + * summary: creates Robot using one parameter constructor + */ + +import java.awt.*; +import java.awt.event.*; + +import sun.awt.SunToolkit; + +public class CtorTest +{ + public static void main(String []s) throws Exception + { + // one parameter constructor + GraphicsDevice graphicsDevice = GraphicsEnvironment. + getLocalGraphicsEnvironment().getDefaultScreenDevice(); + Robot robot = new Robot(graphicsDevice); + clickOnFrame(robot); + } + + // generate mouse events + private static void clickOnFrame(Robot robot) { + Frame frame = new Frame(); + frame.setBounds(100, 100, 100, 100); + frame.setVisible(true); + + ((SunToolkit)Toolkit.getDefaultToolkit()).realSync(); + + // click in the middle of the frame + robot.mouseMove(150, 150); + robot.delay(50); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + + ((SunToolkit)Toolkit.getDefaultToolkit()).realSync(); + } +} From 4d337f68e85eda235757611ebc1dbadfe92da276 Mon Sep 17 00:00:00 2001 From: Dmitry Cherepanov Date: Thu, 9 Jul 2009 15:18:50 -0400 Subject: [PATCH 07/10] 6759726: TrayIcon constructor throws NPE instead of documented IAE Reviewed-by: art --- jdk/src/share/classes/java/awt/TrayIcon.java | 3 ++ .../java/awt/TrayIcon/CtorTest/CtorTest.java | 53 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 jdk/test/java/awt/TrayIcon/CtorTest/CtorTest.java diff --git a/jdk/src/share/classes/java/awt/TrayIcon.java b/jdk/src/share/classes/java/awt/TrayIcon.java index 9fcdd2a6af1..e0c31f8c3ee 100644 --- a/jdk/src/share/classes/java/awt/TrayIcon.java +++ b/jdk/src/share/classes/java/awt/TrayIcon.java @@ -143,6 +143,9 @@ public class TrayIcon { */ public TrayIcon(Image image) { this(); + if (image == null) { + throw new IllegalArgumentException("creating TrayIcon with null Image"); + } setImage(image); } diff --git a/jdk/test/java/awt/TrayIcon/CtorTest/CtorTest.java b/jdk/test/java/awt/TrayIcon/CtorTest/CtorTest.java new file mode 100644 index 00000000000..d16034a1a01 --- /dev/null +++ b/jdk/test/java/awt/TrayIcon/CtorTest/CtorTest.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + @test + @bug 6759726 + @summary TrayIcon constructor throws NPE instead of documented IAE + @author Dmitry Cherepanov area=awt.tray + @run main CtorTest +*/ + +/** + * CtorTest.java + * + * summary: TrayIcon ctor throws IAE if image is null + */ + +import java.awt.*; + +public class CtorTest +{ + public static void main(String []s) + { + boolean isSupported = SystemTray.isSupported(); + if (isSupported) { + try { + TrayIcon tray = new TrayIcon(null); + } catch(IllegalArgumentException e) { + // ctor should throw IAE + } + } + } +} From cd90c35e8f20b3b53ed9ed87d480c501aa6750c3 Mon Sep 17 00:00:00 2001 From: Dmitry Cherepanov Date: Thu, 9 Jul 2009 15:23:22 -0400 Subject: [PATCH 08/10] 6847958: MouseWheel event is getting triggered for the disabled Textarea in jdk7 b60 pit build Reviewed-by: art --- .../classes/sun/awt/X11/XBaseWindow.java | 5 +- .../DisabledComponent/DisabledComponent.java | 107 ++++++++++++++++++ 2 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 jdk/test/java/awt/event/MouseWheelEvent/DisabledComponent/DisabledComponent.java diff --git a/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java b/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java index 07a4fc7c265..0cd25523538 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java @@ -1000,10 +1000,7 @@ public class XBaseWindow { int buttonState = 0; final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons(); for (int i = 0; i Date: Thu, 9 Jul 2009 15:53:07 +0400 Subject: [PATCH 09/10] 6847149: test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java fails Reviewed-by: art --- jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java b/jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java index 44f43c1b3bf..dda735cb7f3 100644 --- a/jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java +++ b/jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java @@ -65,6 +65,7 @@ public class OwnedWindowsLeak break; } } + garbage = null; // Third, make sure all the weak references are null for (WeakReference ref : children) From 565f4998b5bedcac70e93aa7a893c1baac8bff03 Mon Sep 17 00:00:00 2001 From: Anthony Petrov Date: Tue, 14 Jul 2009 14:08:47 +0400 Subject: [PATCH 10/10] 6837446: Introduce Window.isOpaque() method Reviewed-by: art, alexp --- .../classes/com/sun/awt/AWTUtilities.java | 2 +- jdk/src/share/classes/java/awt/Component.java | 6 ++-- .../classes/java/awt/GraphicsDevice.java | 4 +-- jdk/src/share/classes/java/awt/Window.java | 30 ++++++++++++++----- .../javax/swing/DefaultDesktopManager.java | 2 +- .../classes/javax/swing/RepaintManager.java | 6 ++-- .../share/classes/sun/awt/AWTAccessor.java | 5 ---- jdk/src/share/classes/sun/awt/SunToolkit.java | 3 +- .../classes/sun/awt/windows/WWindowPeer.java | 3 +- 9 files changed, 34 insertions(+), 27 deletions(-) diff --git a/jdk/src/share/classes/com/sun/awt/AWTUtilities.java b/jdk/src/share/classes/com/sun/awt/AWTUtilities.java index bf0628b4712..6dd292c865e 100644 --- a/jdk/src/share/classes/com/sun/awt/AWTUtilities.java +++ b/jdk/src/share/classes/com/sun/awt/AWTUtilities.java @@ -374,7 +374,7 @@ public final class AWTUtilities { "The window argument should not be null."); } - return AWTAccessor.getWindowAccessor().isOpaque(window); + return window.isOpaque(); } /** diff --git a/jdk/src/share/classes/java/awt/Component.java b/jdk/src/share/classes/java/awt/Component.java index e07fbe7c5c7..91347ad1b18 100644 --- a/jdk/src/share/classes/java/awt/Component.java +++ b/jdk/src/share/classes/java/awt/Component.java @@ -2370,12 +2370,10 @@ public abstract class Component implements ImageObserver, MenuContainer, * rectangular region. A non-opaque component paints only some of * its pixels, allowing the pixels underneath it to "show through". * A component that does not fully paint its pixels therefore - * provides a degree of transparency. Only lightweight - * components can be transparent. + * provides a degree of transparency. *

* Subclasses that guarantee to always completely paint their - * contents should override this method and return true. All - * of the "heavyweight" AWT components are opaque. + * contents should override this method and return true. * * @return true if this component is completely opaque * @see #isLightweight diff --git a/jdk/src/share/classes/java/awt/GraphicsDevice.java b/jdk/src/share/classes/java/awt/GraphicsDevice.java index 3ad45e223aa..58061c6bc66 100644 --- a/jdk/src/share/classes/java/awt/GraphicsDevice.java +++ b/jdk/src/share/classes/java/awt/GraphicsDevice.java @@ -281,8 +281,8 @@ public abstract class GraphicsDevice { if (w.getOpacity() < 1.0f) { w.setOpacity(1.0f); } - Color bgColor = w.getBackground(); - if ((bgColor != null) && (bgColor.getAlpha() < 255)) { + if (!w.isOpaque()) { + Color bgColor = w.getBackground(); bgColor = new Color(bgColor.getRed(), bgColor.getGreen(), bgColor.getBlue(), 255); w.setBackground(bgColor); diff --git a/jdk/src/share/classes/java/awt/Window.java b/jdk/src/share/classes/java/awt/Window.java index 31c94ca77e5..b419c437c9e 100644 --- a/jdk/src/share/classes/java/awt/Window.java +++ b/jdk/src/share/classes/java/awt/Window.java @@ -3521,6 +3521,7 @@ public class Window extends Container implements Accessible { * @return this component's background color * * @see Window#setBackground + * @see Window#isOpaque * @see GraphicsDevice.WindowTranslucency */ @Override @@ -3583,6 +3584,7 @@ public class Window extends Container implements Accessible { * PERPIXEL_TRANSLUCENT} translucency is not supported * * @see Window#getBackground + * @see Window#isOpaque * @see Window#setOpacity() * @see Window#setShape() * @see GraphicsDevice.WindowTranslucency @@ -3623,6 +3625,25 @@ public class Window extends Container implements Accessible { } } + /** + * Indicates if the window is currently opaque. + *

+ * The method returns {@code false} if the background color of the window + * is not {@code null} and the alpha component of the color is less than + * 1.0f. The method returns {@code true} otherwise. + * + * @return {@code true} if the window is opaque, {@code false} otherwise + * + * @see Window#getBackground + * @see Window#setBackground + * @since 1.7 + */ + @Override + public boolean isOpaque() { + Color bg = getBackground(); + return bg != null ? bg.getAlpha() == 255 : true; + } + private void updateWindow() { synchronized (getTreeLock()) { WindowPeer peer = (WindowPeer)getPeer(); @@ -3639,12 +3660,11 @@ public class Window extends Container implements Accessible { */ @Override public void paint(Graphics g) { - Color bgColor = getBackground(); - if ((bgColor != null) && (bgColor.getAlpha() < 255)) { + if (!isOpaque()) { Graphics gg = g.create(); try { if (gg instanceof Graphics2D) { - gg.setColor(bgColor); + gg.setColor(getBackground()); ((Graphics2D)gg).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC)); gg.fillRect(0, 0, getWidth(), getHeight()); } @@ -3749,10 +3769,6 @@ public class Window extends Container implements Accessible { public void setShape(Window window, Shape shape) { window.setShape(shape); } - public boolean isOpaque(Window window) { - Color bg = window.getBackground(); - return (bg != null) ? bg.getAlpha() == 255 : true; - } public void setOpaque(Window window, boolean opaque) { Color bg = window.getBackground(); if (bg == null) { diff --git a/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java b/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java index 4bf7da1ca23..fc7977df641 100644 --- a/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java +++ b/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java @@ -708,7 +708,7 @@ public class DefaultDesktopManager implements DesktopManager, java.io.Serializab // update window if it's non-opaque Window topLevel = SwingUtilities.getWindowAncestor(f); Toolkit tk = Toolkit.getDefaultToolkit(); - if (!AWTAccessor.getWindowAccessor().isOpaque(topLevel) && + if (!topLevel.isOpaque() && (tk instanceof SunToolkit) && ((SunToolkit)tk).needUpdateWindow()) { diff --git a/jdk/src/share/classes/javax/swing/RepaintManager.java b/jdk/src/share/classes/javax/swing/RepaintManager.java index 618288bd3a0..a988b99fbd3 100644 --- a/jdk/src/share/classes/javax/swing/RepaintManager.java +++ b/jdk/src/share/classes/javax/swing/RepaintManager.java @@ -732,7 +732,7 @@ public class RepaintManager (Window)dirty : SwingUtilities.getWindowAncestor(dirty); if (window != null && - !AWTAccessor.getWindowAccessor().isOpaque(window)) + !window.isOpaque()) { windows.add(window); } @@ -996,7 +996,7 @@ public class RepaintManager // If the window is non-opaque, it's double-buffered at peer's level Window w = (c instanceof Window) ? (Window)c : SwingUtilities.getWindowAncestor(c); - if (!AWTAccessor.getWindowAccessor().isOpaque(w)) { + if (!w.isOpaque()) { Toolkit tk = Toolkit.getDefaultToolkit(); if ((tk instanceof SunToolkit) && (((SunToolkit)tk).needUpdateWindow())) { return null; @@ -1032,7 +1032,7 @@ public class RepaintManager // If the window is non-opaque, it's double-buffered at peer's level Window w = (c instanceof Window) ? (Window)c : SwingUtilities.getWindowAncestor(c); - if (!AWTAccessor.getWindowAccessor().isOpaque(w)) { + if (!w.isOpaque()) { Toolkit tk = Toolkit.getDefaultToolkit(); if ((tk instanceof SunToolkit) && (((SunToolkit)tk).needUpdateWindow())) { return null; diff --git a/jdk/src/share/classes/sun/awt/AWTAccessor.java b/jdk/src/share/classes/sun/awt/AWTAccessor.java index e427b892517..c8bbc860877 100644 --- a/jdk/src/share/classes/sun/awt/AWTAccessor.java +++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java @@ -136,11 +136,6 @@ public final class AWTAccessor { * Set a shape to the given window. */ void setShape(Window window, Shape shape); - /* - * Identify whether the given window is opaque (true) - * or translucent (false). - */ - boolean isOpaque(Window window); /* * Set the opaque preoperty to the given window. */ diff --git a/jdk/src/share/classes/sun/awt/SunToolkit.java b/jdk/src/share/classes/sun/awt/SunToolkit.java index 7f0ac590fa0..b4dd06a445c 100644 --- a/jdk/src/share/classes/sun/awt/SunToolkit.java +++ b/jdk/src/share/classes/sun/awt/SunToolkit.java @@ -1985,8 +1985,7 @@ public abstract class SunToolkit extends Toolkit */ public static boolean isContainingTopLevelOpaque(Component c) { Window w = getContainingWindow(c); - return w != null && ((Window)w).getBackground() != null && - ((Window)w).getBackground().getAlpha() == 255; + return w != null && w.isOpaque(); } /** diff --git a/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java b/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java index 165acac4e93..fbb7442ba7d 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java +++ b/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java @@ -194,8 +194,7 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer, // default value of a boolean field is 'false', so set isOpaque to // true here explicitly this.isOpaque = true; - Color bgColor = ((Window)target).getBackground(); - setOpaque((bgColor == null) || (bgColor.getAlpha() == 255)); + setOpaque(((Window)target).isOpaque()); } }