feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
90
jdkSrc/jdk8/java/beans/AppletInitializer.java
Normal file
90
jdkSrc/jdk8/java/beans/AppletInitializer.java
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, 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.applet.Applet;
|
||||
|
||||
import java.beans.beancontext.BeanContext;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This interface is designed to work in collusion with java.beans.Beans.instantiate.
|
||||
* The interface is intended to provide mechanism to allow the proper
|
||||
* initialization of JavaBeans that are also Applets, during their
|
||||
* instantiation by java.beans.Beans.instantiate().
|
||||
* </p>
|
||||
*
|
||||
* @see java.beans.Beans#instantiate
|
||||
*
|
||||
* @since 1.2
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
public interface AppletInitializer {
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* If passed to the appropriate variant of java.beans.Beans.instantiate
|
||||
* this method will be called in order to associate the newly instantiated
|
||||
* Applet (JavaBean) with its AppletContext, AppletStub, and Container.
|
||||
* </p>
|
||||
* <p>
|
||||
* Conformant implementations shall:
|
||||
* <ol>
|
||||
* <li> Associate the newly instantiated Applet with the appropriate
|
||||
* AppletContext.
|
||||
*
|
||||
* <li> Instantiate an AppletStub() and associate that AppletStub with
|
||||
* the Applet via an invocation of setStub().
|
||||
*
|
||||
* <li> If BeanContext parameter is null, then it shall associate the
|
||||
* Applet with its appropriate Container by adding that Applet to its
|
||||
* Container via an invocation of add(). If the BeanContext parameter is
|
||||
* non-null, then it is the responsibility of the BeanContext to associate
|
||||
* the Applet with its Container during the subsequent invocation of its
|
||||
* addChildren() method.
|
||||
* </ol>
|
||||
*
|
||||
* @param newAppletBean The newly instantiated JavaBean
|
||||
* @param bCtxt The BeanContext intended for this Applet, or
|
||||
* null.
|
||||
*/
|
||||
|
||||
void initialize(Applet newAppletBean, BeanContext bCtxt);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Activate, and/or mark Applet active. Implementors of this interface
|
||||
* shall mark this Applet as active, and optionally invoke its start()
|
||||
* method.
|
||||
* </p>
|
||||
*
|
||||
* @param newApplet The newly instantiated JavaBean
|
||||
*/
|
||||
|
||||
void activate(Applet newApplet);
|
||||
}
|
||||
109
jdkSrc/jdk8/java/beans/BeanDescriptor.java
Normal file
109
jdkSrc/jdk8/java/beans/BeanDescriptor.java
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2011, 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.ref.Reference;
|
||||
|
||||
/**
|
||||
* A BeanDescriptor provides global information about a "bean",
|
||||
* including its Java class, its displayName, etc.
|
||||
* <p>
|
||||
* This is one of the kinds of descriptor returned by a BeanInfo object,
|
||||
* which also returns descriptors for properties, method, and events.
|
||||
*/
|
||||
|
||||
public class BeanDescriptor extends FeatureDescriptor {
|
||||
|
||||
private Reference<? extends Class<?>> beanClassRef;
|
||||
private Reference<? extends Class<?>> customizerClassRef;
|
||||
|
||||
/**
|
||||
* Create a BeanDescriptor for a bean that doesn't have a customizer.
|
||||
*
|
||||
* @param beanClass The Class object of the Java class that implements
|
||||
* the bean. For example sun.beans.OurButton.class.
|
||||
*/
|
||||
public BeanDescriptor(Class<?> beanClass) {
|
||||
this(beanClass, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a BeanDescriptor for a bean that has a customizer.
|
||||
*
|
||||
* @param beanClass The Class object of the Java class that implements
|
||||
* the bean. For example sun.beans.OurButton.class.
|
||||
* @param customizerClass The Class object of the Java class that implements
|
||||
* the bean's Customizer. For example sun.beans.OurButtonCustomizer.class.
|
||||
*/
|
||||
public BeanDescriptor(Class<?> beanClass, Class<?> customizerClass) {
|
||||
this.beanClassRef = getWeakReference(beanClass);
|
||||
this.customizerClassRef = getWeakReference(customizerClass);
|
||||
|
||||
String name = beanClass.getName();
|
||||
while (name.indexOf('.') >= 0) {
|
||||
name = name.substring(name.indexOf('.')+1);
|
||||
}
|
||||
setName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bean's Class object.
|
||||
*
|
||||
* @return The Class object for the bean.
|
||||
*/
|
||||
public Class<?> getBeanClass() {
|
||||
return (this.beanClassRef != null)
|
||||
? this.beanClassRef.get()
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Class object for the bean's customizer.
|
||||
*
|
||||
* @return The Class object for the bean's customizer. This may
|
||||
* be null if the bean doesn't have a customizer.
|
||||
*/
|
||||
public Class<?> getCustomizerClass() {
|
||||
return (this.customizerClassRef != null)
|
||||
? this.customizerClassRef.get()
|
||||
: null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Package-private dup constructor
|
||||
* This must isolate the new object from any changes to the old object.
|
||||
*/
|
||||
BeanDescriptor(BeanDescriptor old) {
|
||||
super(old);
|
||||
beanClassRef = old.beanClassRef;
|
||||
customizerClassRef = old.customizerClassRef;
|
||||
}
|
||||
|
||||
void appendTo(StringBuilder sb) {
|
||||
appendTo(sb, "beanClass", this.beanClassRef);
|
||||
appendTo(sb, "customizerClass", this.customizerClassRef);
|
||||
}
|
||||
}
|
||||
176
jdkSrc/jdk8/java/beans/BeanInfo.java
Normal file
176
jdkSrc/jdk8/java/beans/BeanInfo.java
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2012, 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.awt.Image;
|
||||
|
||||
/**
|
||||
* Use the {@code BeanInfo} interface
|
||||
* to create a {@code BeanInfo} class
|
||||
* and provide explicit information about the methods,
|
||||
* properties, events, and other features of your beans.
|
||||
* <p>
|
||||
* When developing your bean, you can implement
|
||||
* the bean features required for your application task
|
||||
* omitting the rest of the {@code BeanInfo} features.
|
||||
* They will be obtained through the automatic analysis
|
||||
* by using the low-level reflection of the bean methods
|
||||
* and applying standard design patterns.
|
||||
* You have an opportunity to provide additional bean information
|
||||
* through various descriptor classes.
|
||||
* <p>
|
||||
* See the {@link SimpleBeanInfo} class that is
|
||||
* a convenient basic class for {@code BeanInfo} classes.
|
||||
* You can override the methods and properties of
|
||||
* the {@code SimpleBeanInfo} class to define specific information.
|
||||
* <p>
|
||||
* See also the {@link Introspector} class to learn more about bean behavior.
|
||||
*/
|
||||
public interface BeanInfo {
|
||||
|
||||
/**
|
||||
* Returns the bean descriptor
|
||||
* that provides overall information about the bean,
|
||||
* such as its display name or its customizer.
|
||||
*
|
||||
* @return a {@link BeanDescriptor} object,
|
||||
* or {@code null} if the information is to
|
||||
* be obtained through the automatic analysis
|
||||
*/
|
||||
BeanDescriptor getBeanDescriptor();
|
||||
|
||||
/**
|
||||
* Returns the event descriptors of the bean
|
||||
* that define the types of events fired by this bean.
|
||||
*
|
||||
* @return an array of {@link EventSetDescriptor} objects,
|
||||
* or {@code null} if the information is to
|
||||
* be obtained through the automatic analysis
|
||||
*/
|
||||
EventSetDescriptor[] getEventSetDescriptors();
|
||||
|
||||
/**
|
||||
* A bean may have a default event typically applied when this bean is used.
|
||||
*
|
||||
* @return index of the default event in the {@code EventSetDescriptor} array
|
||||
* returned by the {@code getEventSetDescriptors} method,
|
||||
* or -1 if there is no default event
|
||||
*/
|
||||
int getDefaultEventIndex();
|
||||
|
||||
/**
|
||||
* Returns descriptors for all properties of the bean.
|
||||
* <p>
|
||||
* If a property is indexed, then its entry in the result array
|
||||
* belongs to the {@link IndexedPropertyDescriptor} subclass
|
||||
* of the {@link PropertyDescriptor} class.
|
||||
* A client of the {@code getPropertyDescriptors} method
|
||||
* can use the {@code instanceof} operator to check
|
||||
* whether a given {@code PropertyDescriptor}
|
||||
* is an {@code IndexedPropertyDescriptor}.
|
||||
*
|
||||
* @return an array of {@code PropertyDescriptor} objects,
|
||||
* or {@code null} if the information is to
|
||||
* be obtained through the automatic analysis
|
||||
*/
|
||||
PropertyDescriptor[] getPropertyDescriptors();
|
||||
|
||||
/**
|
||||
* A bean may have a default property commonly updated when this bean is customized.
|
||||
*
|
||||
* @return index of the default property in the {@code PropertyDescriptor} array
|
||||
* returned by the {@code getPropertyDescriptors} method,
|
||||
* or -1 if there is no default property
|
||||
*/
|
||||
int getDefaultPropertyIndex();
|
||||
|
||||
/**
|
||||
* Returns the method descriptors of the bean
|
||||
* that define the externally visible methods supported by this bean.
|
||||
*
|
||||
* @return an array of {@link MethodDescriptor} objects,
|
||||
* or {@code null} if the information is to
|
||||
* be obtained through the automatic analysis
|
||||
*/
|
||||
MethodDescriptor[] getMethodDescriptors();
|
||||
|
||||
/**
|
||||
* This method enables the current {@code BeanInfo} object
|
||||
* to return an arbitrary collection of other {@code BeanInfo} objects
|
||||
* that provide additional information about the current bean.
|
||||
* <p>
|
||||
* If there are conflicts or overlaps between the information
|
||||
* provided by different {@code BeanInfo} objects,
|
||||
* the current {@code BeanInfo} object takes priority
|
||||
* over the additional {@code BeanInfo} objects.
|
||||
* Array elements with higher indices take priority
|
||||
* over the elements with lower indices.
|
||||
*
|
||||
* @return an array of {@code BeanInfo} objects,
|
||||
* or {@code null} if there are no additional {@code BeanInfo} objects
|
||||
*/
|
||||
BeanInfo[] getAdditionalBeanInfo();
|
||||
|
||||
/**
|
||||
* Returns an image that can be used to represent the bean in toolboxes or toolbars.
|
||||
* <p>
|
||||
* There are four possible types of icons:
|
||||
* 16 x 16 color, 32 x 32 color, 16 x 16 mono, and 32 x 32 mono.
|
||||
* If you implement a bean so that it supports a single icon,
|
||||
* it is recommended to use 16 x 16 color.
|
||||
* Another recommendation is to set a transparent background for the icons.
|
||||
*
|
||||
* @param iconKind the kind of icon requested
|
||||
* @return an image object representing the requested icon,
|
||||
* or {@code null} if no suitable icon is available
|
||||
*
|
||||
* @see #ICON_COLOR_16x16
|
||||
* @see #ICON_COLOR_32x32
|
||||
* @see #ICON_MONO_16x16
|
||||
* @see #ICON_MONO_32x32
|
||||
*/
|
||||
Image getIcon(int iconKind);
|
||||
|
||||
/**
|
||||
* Constant to indicate a 16 x 16 color icon.
|
||||
*/
|
||||
final static int ICON_COLOR_16x16 = 1;
|
||||
|
||||
/**
|
||||
* Constant to indicate a 32 x 32 color icon.
|
||||
*/
|
||||
final static int ICON_COLOR_32x32 = 2;
|
||||
|
||||
/**
|
||||
* Constant to indicate a 16 x 16 monochrome icon.
|
||||
*/
|
||||
final static int ICON_MONO_16x16 = 3;
|
||||
|
||||
/**
|
||||
* Constant to indicate a 32 x 32 monochrome icon.
|
||||
*/
|
||||
final static int ICON_MONO_32x32 = 4;
|
||||
}
|
||||
626
jdkSrc/jdk8/java/beans/Beans.java
Normal file
626
jdkSrc/jdk8/java/beans/Beans.java
Normal file
@@ -0,0 +1,626 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 com.sun.beans.finder.ClassFinder;
|
||||
|
||||
import java.applet.Applet;
|
||||
import java.applet.AppletContext;
|
||||
import java.applet.AppletStub;
|
||||
import java.applet.AudioClip;
|
||||
|
||||
import java.awt.Image;
|
||||
|
||||
import java.beans.beancontext.BeanContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.io.StreamCorruptedException;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* This class provides some general purpose beans control methods.
|
||||
*/
|
||||
|
||||
public class Beans {
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Instantiate a JavaBean.
|
||||
* </p>
|
||||
* @return a JavaBean
|
||||
* @param cls the class-loader from which we should create
|
||||
* the bean. If this is null, then the system
|
||||
* class-loader is used.
|
||||
* @param beanName the name of the bean within the class-loader.
|
||||
* For example "sun.beanbox.foobah"
|
||||
*
|
||||
* @exception ClassNotFoundException if the class of a serialized
|
||||
* object could not be found.
|
||||
* @exception IOException if an I/O error occurs.
|
||||
*/
|
||||
|
||||
public static Object instantiate(ClassLoader cls, String beanName) throws IOException, ClassNotFoundException {
|
||||
return Beans.instantiate(cls, beanName, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Instantiate a JavaBean.
|
||||
* </p>
|
||||
* @return a JavaBean
|
||||
*
|
||||
* @param cls the class-loader from which we should create
|
||||
* the bean. If this is null, then the system
|
||||
* class-loader is used.
|
||||
* @param beanName the name of the bean within the class-loader.
|
||||
* For example "sun.beanbox.foobah"
|
||||
* @param beanContext The BeanContext in which to nest the new bean
|
||||
*
|
||||
* @exception ClassNotFoundException if the class of a serialized
|
||||
* object could not be found.
|
||||
* @exception IOException if an I/O error occurs.
|
||||
*/
|
||||
|
||||
public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext) throws IOException, ClassNotFoundException {
|
||||
return Beans.instantiate(cls, beanName, beanContext, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a bean.
|
||||
* <p>
|
||||
* The bean is created based on a name relative to a class-loader.
|
||||
* This name should be a dot-separated name such as "a.b.c".
|
||||
* <p>
|
||||
* In Beans 1.0 the given name can indicate either a serialized object
|
||||
* or a class. Other mechanisms may be added in the future. In
|
||||
* beans 1.0 we first try to treat the beanName as a serialized object
|
||||
* name then as a class name.
|
||||
* <p>
|
||||
* When using the beanName as a serialized object name we convert the
|
||||
* given beanName to a resource pathname and add a trailing ".ser" suffix.
|
||||
* We then try to load a serialized object from that resource.
|
||||
* <p>
|
||||
* For example, given a beanName of "x.y", Beans.instantiate would first
|
||||
* try to read a serialized object from the resource "x/y.ser" and if
|
||||
* that failed it would try to load the class "x.y" and create an
|
||||
* instance of that class.
|
||||
* <p>
|
||||
* If the bean is a subtype of java.applet.Applet, then it is given
|
||||
* some special initialization. First, it is supplied with a default
|
||||
* AppletStub and AppletContext. Second, if it was instantiated from
|
||||
* a classname the applet's "init" method is called. (If the bean was
|
||||
* deserialized this step is skipped.)
|
||||
* <p>
|
||||
* Note that for beans which are applets, it is the caller's responsiblity
|
||||
* to call "start" on the applet. For correct behaviour, this should be done
|
||||
* after the applet has been added into a visible AWT container.
|
||||
* <p>
|
||||
* Note that applets created via beans.instantiate run in a slightly
|
||||
* different environment than applets running inside browsers. In
|
||||
* particular, bean applets have no access to "parameters", so they may
|
||||
* wish to provide property get/set methods to set parameter values. We
|
||||
* advise bean-applet developers to test their bean-applets against both
|
||||
* the JDK appletviewer (for a reference browser environment) and the
|
||||
* BDK BeanBox (for a reference bean container).
|
||||
*
|
||||
* @return a JavaBean
|
||||
* @param cls the class-loader from which we should create
|
||||
* the bean. If this is null, then the system
|
||||
* class-loader is used.
|
||||
* @param beanName the name of the bean within the class-loader.
|
||||
* For example "sun.beanbox.foobah"
|
||||
* @param beanContext The BeanContext in which to nest the new bean
|
||||
* @param initializer The AppletInitializer for the new bean
|
||||
*
|
||||
* @exception ClassNotFoundException if the class of a serialized
|
||||
* object could not be found.
|
||||
* @exception IOException if an I/O error occurs.
|
||||
*/
|
||||
|
||||
public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext, AppletInitializer initializer)
|
||||
throws IOException, ClassNotFoundException {
|
||||
|
||||
InputStream ins;
|
||||
ObjectInputStream oins = null;
|
||||
Object result = null;
|
||||
boolean serialized = false;
|
||||
IOException serex = null;
|
||||
|
||||
// If the given classloader is null, we check if an
|
||||
// system classloader is available and (if so)
|
||||
// use that instead.
|
||||
// Note that calls on the system class loader will
|
||||
// look in the bootstrap class loader first.
|
||||
if (cls == null) {
|
||||
try {
|
||||
cls = ClassLoader.getSystemClassLoader();
|
||||
} catch (SecurityException ex) {
|
||||
// We're not allowed to access the system class loader.
|
||||
// Drop through.
|
||||
}
|
||||
}
|
||||
|
||||
// Try to find a serialized object with this name
|
||||
final String serName = beanName.replace('.','/').concat(".ser");
|
||||
if (cls == null)
|
||||
ins = ClassLoader.getSystemResourceAsStream(serName);
|
||||
else
|
||||
ins = cls.getResourceAsStream(serName);
|
||||
if (ins != null) {
|
||||
try {
|
||||
if (cls == null) {
|
||||
oins = new ObjectInputStream(ins);
|
||||
} else {
|
||||
oins = new ObjectInputStreamWithLoader(ins, cls);
|
||||
}
|
||||
result = oins.readObject();
|
||||
serialized = true;
|
||||
oins.close();
|
||||
} catch (IOException ex) {
|
||||
ins.close();
|
||||
// Drop through and try opening the class. But remember
|
||||
// the exception in case we can't find the class either.
|
||||
serex = ex;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
ins.close();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
// No serialized object, try just instantiating the class
|
||||
Class<?> cl;
|
||||
|
||||
try {
|
||||
cl = ClassFinder.findClass(beanName, cls);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
// There is no appropriate class. If we earlier tried to
|
||||
// deserialize an object and got an IO exception, throw that,
|
||||
// otherwise rethrow the ClassNotFoundException.
|
||||
if (serex != null) {
|
||||
throw serex;
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if (!Modifier.isPublic(cl.getModifiers())) {
|
||||
throw new ClassNotFoundException("" + cl + " : no public access");
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to instantiate the class.
|
||||
*/
|
||||
|
||||
try {
|
||||
result = cl.newInstance();
|
||||
} catch (Exception ex) {
|
||||
// We have to remap the exception to one in our signature.
|
||||
// But we pass extra information in the detail message.
|
||||
throw new ClassNotFoundException("" + cl + " : " + ex, ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (result != null) {
|
||||
|
||||
// Ok, if the result is an applet initialize it.
|
||||
|
||||
AppletStub stub = null;
|
||||
|
||||
if (result instanceof Applet) {
|
||||
Applet applet = (Applet) result;
|
||||
boolean needDummies = initializer == null;
|
||||
|
||||
if (needDummies) {
|
||||
|
||||
// Figure our the codebase and docbase URLs. We do this
|
||||
// by locating the URL for a known resource, and then
|
||||
// massaging the URL.
|
||||
|
||||
// First find the "resource name" corresponding to the bean
|
||||
// itself. So a serialzied bean "a.b.c" would imply a
|
||||
// resource name of "a/b/c.ser" and a classname of "x.y"
|
||||
// would imply a resource name of "x/y.class".
|
||||
|
||||
final String resourceName;
|
||||
|
||||
if (serialized) {
|
||||
// Serialized bean
|
||||
resourceName = beanName.replace('.','/').concat(".ser");
|
||||
} else {
|
||||
// Regular class
|
||||
resourceName = beanName.replace('.','/').concat(".class");
|
||||
}
|
||||
|
||||
URL objectUrl = null;
|
||||
URL codeBase = null;
|
||||
URL docBase = null;
|
||||
|
||||
// Now get the URL correponding to the resource name.
|
||||
if (cls == null) {
|
||||
objectUrl = ClassLoader.getSystemResource(resourceName);
|
||||
} else
|
||||
objectUrl = cls.getResource(resourceName);
|
||||
|
||||
// If we found a URL, we try to locate the docbase by taking
|
||||
// of the final path name component, and the code base by taking
|
||||
// of the complete resourceName.
|
||||
// So if we had a resourceName of "a/b/c.class" and we got an
|
||||
// objectURL of "file://bert/classes/a/b/c.class" then we would
|
||||
// want to set the codebase to "file://bert/classes/" and the
|
||||
// docbase to "file://bert/classes/a/b/"
|
||||
|
||||
if (objectUrl != null) {
|
||||
String s = objectUrl.toExternalForm();
|
||||
|
||||
if (s.endsWith(resourceName)) {
|
||||
int ix = s.length() - resourceName.length();
|
||||
codeBase = new URL(s.substring(0,ix));
|
||||
docBase = codeBase;
|
||||
|
||||
ix = s.lastIndexOf('/');
|
||||
|
||||
if (ix >= 0) {
|
||||
docBase = new URL(s.substring(0,ix+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Setup a default context and stub.
|
||||
BeansAppletContext context = new BeansAppletContext(applet);
|
||||
|
||||
stub = (AppletStub)new BeansAppletStub(applet, context, codeBase, docBase);
|
||||
applet.setStub(stub);
|
||||
} else {
|
||||
initializer.initialize(applet, beanContext);
|
||||
}
|
||||
|
||||
// now, if there is a BeanContext, add the bean, if applicable.
|
||||
|
||||
if (beanContext != null) {
|
||||
unsafeBeanContextAdd(beanContext, result);
|
||||
}
|
||||
|
||||
// If it was deserialized then it was already init-ed.
|
||||
// Otherwise we need to initialize it.
|
||||
|
||||
if (!serialized) {
|
||||
// We need to set a reasonable initial size, as many
|
||||
// applets are unhappy if they are started without
|
||||
// having been explicitly sized.
|
||||
applet.setSize(100,100);
|
||||
applet.init();
|
||||
}
|
||||
|
||||
if (needDummies) {
|
||||
((BeansAppletStub)stub).active = true;
|
||||
} else initializer.activate(applet);
|
||||
|
||||
} else if (beanContext != null) unsafeBeanContextAdd(beanContext, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static void unsafeBeanContextAdd(BeanContext beanContext, Object res) {
|
||||
beanContext.add(res);
|
||||
}
|
||||
|
||||
/**
|
||||
* From a given bean, obtain an object representing a specified
|
||||
* type view of that source object.
|
||||
* <p>
|
||||
* The result may be the same object or a different object. If
|
||||
* the requested target view isn't available then the given
|
||||
* bean is returned.
|
||||
* <p>
|
||||
* This method is provided in Beans 1.0 as a hook to allow the
|
||||
* addition of more flexible bean behaviour in the future.
|
||||
*
|
||||
* @return an object representing a specified type view of the
|
||||
* source object
|
||||
* @param bean Object from which we want to obtain a view.
|
||||
* @param targetType The type of view we'd like to get.
|
||||
*
|
||||
*/
|
||||
public static Object getInstanceOf(Object bean, Class<?> targetType) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a bean can be viewed as a given target type.
|
||||
* The result will be true if the Beans.getInstanceof method
|
||||
* can be used on the given bean to obtain an object that
|
||||
* represents the specified targetType type view.
|
||||
*
|
||||
* @param bean Bean from which we want to obtain a view.
|
||||
* @param targetType The type of view we'd like to get.
|
||||
* @return "true" if the given bean supports the given targetType.
|
||||
*
|
||||
*/
|
||||
public static boolean isInstanceOf(Object bean, Class<?> targetType) {
|
||||
return Introspector.isSubclass(bean.getClass(), targetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if we are in design-mode.
|
||||
*
|
||||
* @return True if we are running in an application construction
|
||||
* environment.
|
||||
*
|
||||
* @see DesignMode
|
||||
*/
|
||||
public static boolean isDesignTime() {
|
||||
return ThreadGroupContext.getContext().isDesignTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether beans can assume a GUI is available.
|
||||
*
|
||||
* @return True if we are running in an environment where beans
|
||||
* can assume that an interactive GUI is available, so they
|
||||
* can pop up dialog boxes, etc. This will normally return
|
||||
* true in a windowing environment, and will normally return
|
||||
* false in a server environment or if an application is
|
||||
* running as part of a batch job.
|
||||
*
|
||||
* @see Visibility
|
||||
*
|
||||
*/
|
||||
public static boolean isGuiAvailable() {
|
||||
return ThreadGroupContext.getContext().isGuiAvailable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to indicate whether of not we are running in an application
|
||||
* builder environment.
|
||||
*
|
||||
* <p>Note that this method is security checked
|
||||
* and is not available to (for example) untrusted applets.
|
||||
* More specifically, if there is a security manager,
|
||||
* its <code>checkPropertiesAccess</code>
|
||||
* method is called. This could result in a SecurityException.
|
||||
*
|
||||
* @param isDesignTime True if we're in an application builder tool.
|
||||
* @exception SecurityException if a security manager exists and its
|
||||
* <code>checkPropertiesAccess</code> method doesn't allow setting
|
||||
* of system properties.
|
||||
* @see SecurityManager#checkPropertiesAccess
|
||||
*/
|
||||
|
||||
public static void setDesignTime(boolean isDesignTime)
|
||||
throws SecurityException {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPropertiesAccess();
|
||||
}
|
||||
ThreadGroupContext.getContext().setDesignTime(isDesignTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to indicate whether of not we are running in an environment
|
||||
* where GUI interaction is available.
|
||||
*
|
||||
* <p>Note that this method is security checked
|
||||
* and is not available to (for example) untrusted applets.
|
||||
* More specifically, if there is a security manager,
|
||||
* its <code>checkPropertiesAccess</code>
|
||||
* method is called. This could result in a SecurityException.
|
||||
*
|
||||
* @param isGuiAvailable True if GUI interaction is available.
|
||||
* @exception SecurityException if a security manager exists and its
|
||||
* <code>checkPropertiesAccess</code> method doesn't allow setting
|
||||
* of system properties.
|
||||
* @see SecurityManager#checkPropertiesAccess
|
||||
*/
|
||||
|
||||
public static void setGuiAvailable(boolean isGuiAvailable)
|
||||
throws SecurityException {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPropertiesAccess();
|
||||
}
|
||||
ThreadGroupContext.getContext().setGuiAvailable(isGuiAvailable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This subclass of ObjectInputStream delegates loading of classes to
|
||||
* an existing ClassLoader.
|
||||
*/
|
||||
|
||||
class ObjectInputStreamWithLoader extends ObjectInputStream
|
||||
{
|
||||
private ClassLoader loader;
|
||||
|
||||
/**
|
||||
* Loader must be non-null;
|
||||
*/
|
||||
|
||||
public ObjectInputStreamWithLoader(InputStream in, ClassLoader loader)
|
||||
throws IOException, StreamCorruptedException {
|
||||
|
||||
super(in);
|
||||
if (loader == null) {
|
||||
throw new IllegalArgumentException("Illegal null argument to ObjectInputStreamWithLoader");
|
||||
}
|
||||
this.loader = loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the given ClassLoader rather than using the system class
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
protected Class resolveClass(ObjectStreamClass classDesc)
|
||||
throws IOException, ClassNotFoundException {
|
||||
|
||||
String cname = classDesc.getName();
|
||||
return ClassFinder.resolveClass(cname, this.loader);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Package private support class. This provides a default AppletContext
|
||||
* for beans which are applets.
|
||||
*/
|
||||
|
||||
class BeansAppletContext implements AppletContext {
|
||||
Applet target;
|
||||
Hashtable<URL,Object> imageCache = new Hashtable<>();
|
||||
|
||||
BeansAppletContext(Applet target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public AudioClip getAudioClip(URL url) {
|
||||
// We don't currently support audio clips in the Beans.instantiate
|
||||
// applet context, unless by some luck there exists a URL content
|
||||
// class that can generate an AudioClip from the audio URL.
|
||||
try {
|
||||
return (AudioClip) url.getContent();
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized Image getImage(URL url) {
|
||||
Object o = imageCache.get(url);
|
||||
if (o != null) {
|
||||
return (Image)o;
|
||||
}
|
||||
try {
|
||||
o = url.getContent();
|
||||
if (o == null) {
|
||||
return null;
|
||||
}
|
||||
if (o instanceof Image) {
|
||||
imageCache.put(url, o);
|
||||
return (Image) o;
|
||||
}
|
||||
// Otherwise it must be an ImageProducer.
|
||||
Image img = target.createImage((java.awt.image.ImageProducer)o);
|
||||
imageCache.put(url, img);
|
||||
return img;
|
||||
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Applet getApplet(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Enumeration<Applet> getApplets() {
|
||||
Vector<Applet> applets = new Vector<>();
|
||||
applets.addElement(target);
|
||||
return applets.elements();
|
||||
}
|
||||
|
||||
public void showDocument(URL url) {
|
||||
// We do nothing.
|
||||
}
|
||||
|
||||
public void showDocument(URL url, String target) {
|
||||
// We do nothing.
|
||||
}
|
||||
|
||||
public void showStatus(String status) {
|
||||
// We do nothing.
|
||||
}
|
||||
|
||||
public void setStream(String key, InputStream stream)throws IOException{
|
||||
// We do nothing.
|
||||
}
|
||||
|
||||
public InputStream getStream(String key){
|
||||
// We do nothing.
|
||||
return null;
|
||||
}
|
||||
|
||||
public Iterator<String> getStreamKeys(){
|
||||
// We do nothing.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Package private support class. This provides an AppletStub
|
||||
* for beans which are applets.
|
||||
*/
|
||||
class BeansAppletStub implements AppletStub {
|
||||
transient boolean active;
|
||||
transient Applet target;
|
||||
transient AppletContext context;
|
||||
transient URL codeBase;
|
||||
transient URL docBase;
|
||||
|
||||
BeansAppletStub(Applet target,
|
||||
AppletContext context, URL codeBase,
|
||||
URL docBase) {
|
||||
this.target = target;
|
||||
this.context = context;
|
||||
this.codeBase = codeBase;
|
||||
this.docBase = docBase;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public URL getDocumentBase() {
|
||||
// use the root directory of the applet's class-loader
|
||||
return docBase;
|
||||
}
|
||||
|
||||
public URL getCodeBase() {
|
||||
// use the directory where we found the class or serialized object.
|
||||
return codeBase;
|
||||
}
|
||||
|
||||
public String getParameter(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public AppletContext getAppletContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public void appletResize(int width, int height) {
|
||||
// we do nothing.
|
||||
}
|
||||
}
|
||||
241
jdkSrc/jdk8/java/beans/ChangeListenerMap.java
Normal file
241
jdkSrc/jdk8/java/beans/ChangeListenerMap.java
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 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.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EventListener;
|
||||
import java.util.EventListenerProxy;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This is an abstract class that provides base functionality
|
||||
* for the {@link PropertyChangeSupport PropertyChangeSupport} class
|
||||
* and the {@link VetoableChangeSupport VetoableChangeSupport} class.
|
||||
*
|
||||
* @see PropertyChangeListenerMap
|
||||
* @see VetoableChangeListenerMap
|
||||
*
|
||||
* @author Sergey A. Malenkov
|
||||
*/
|
||||
abstract class ChangeListenerMap<L extends EventListener> {
|
||||
private Map<String, L[]> map;
|
||||
|
||||
/**
|
||||
* Creates an array of listeners.
|
||||
* This method can be optimized by using
|
||||
* the same instance of the empty array
|
||||
* when {@code length} is equal to {@code 0}.
|
||||
*
|
||||
* @param length the array length
|
||||
* @return an array with specified length
|
||||
*/
|
||||
protected abstract L[] newArray(int length);
|
||||
|
||||
/**
|
||||
* Creates a proxy listener for the specified property.
|
||||
*
|
||||
* @param name the name of the property to listen on
|
||||
* @param listener the listener to process events
|
||||
* @return a proxy listener
|
||||
*/
|
||||
protected abstract L newProxy(String name, L listener);
|
||||
|
||||
/**
|
||||
* Adds a listener to the list of listeners for the specified property.
|
||||
* This listener is called as many times as it was added.
|
||||
*
|
||||
* @param name the name of the property to listen on
|
||||
* @param listener the listener to process events
|
||||
*/
|
||||
public final synchronized void add(String name, L listener) {
|
||||
if (this.map == null) {
|
||||
this.map = new HashMap<>();
|
||||
}
|
||||
L[] array = this.map.get(name);
|
||||
int size = (array != null)
|
||||
? array.length
|
||||
: 0;
|
||||
|
||||
L[] clone = newArray(size + 1);
|
||||
clone[size] = listener;
|
||||
if (array != null) {
|
||||
System.arraycopy(array, 0, clone, 0, size);
|
||||
}
|
||||
this.map.put(name, clone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener from the list of listeners for the specified property.
|
||||
* If the listener was added more than once to the same event source,
|
||||
* this listener will be notified one less time after being removed.
|
||||
*
|
||||
* @param name the name of the property to listen on
|
||||
* @param listener the listener to process events
|
||||
*/
|
||||
public final synchronized void remove(String name, L listener) {
|
||||
if (this.map != null) {
|
||||
L[] array = this.map.get(name);
|
||||
if (array != null) {
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
if (listener.equals(array[i])) {
|
||||
int size = array.length - 1;
|
||||
if (size > 0) {
|
||||
L[] clone = newArray(size);
|
||||
System.arraycopy(array, 0, clone, 0, i);
|
||||
System.arraycopy(array, i + 1, clone, i, size - i);
|
||||
this.map.put(name, clone);
|
||||
}
|
||||
else {
|
||||
this.map.remove(name);
|
||||
if (this.map.isEmpty()) {
|
||||
this.map = null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of listeners for the specified property.
|
||||
*
|
||||
* @param name the name of the property
|
||||
* @return the corresponding list of listeners
|
||||
*/
|
||||
public final synchronized L[] get(String name) {
|
||||
return (this.map != null)
|
||||
? this.map.get(name)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets new list of listeners for the specified property.
|
||||
*
|
||||
* @param name the name of the property
|
||||
* @param listeners new list of listeners
|
||||
*/
|
||||
public final void set(String name, L[] listeners) {
|
||||
if (listeners != null) {
|
||||
if (this.map == null) {
|
||||
this.map = new HashMap<>();
|
||||
}
|
||||
this.map.put(name, listeners);
|
||||
}
|
||||
else if (this.map != null) {
|
||||
this.map.remove(name);
|
||||
if (this.map.isEmpty()) {
|
||||
this.map = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all listeners in the map.
|
||||
*
|
||||
* @return an array of all listeners
|
||||
*/
|
||||
public final synchronized L[] getListeners() {
|
||||
if (this.map == null) {
|
||||
return newArray(0);
|
||||
}
|
||||
List<L> list = new ArrayList<>();
|
||||
|
||||
L[] listeners = this.map.get(null);
|
||||
if (listeners != null) {
|
||||
for (L listener : listeners) {
|
||||
list.add(listener);
|
||||
}
|
||||
}
|
||||
for (Entry<String, L[]> entry : this.map.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
if (name != null) {
|
||||
for (L listener : entry.getValue()) {
|
||||
list.add(newProxy(name, listener));
|
||||
}
|
||||
}
|
||||
}
|
||||
return list.toArray(newArray(list.size()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns listeners that have been associated with the named property.
|
||||
*
|
||||
* @param name the name of the property
|
||||
* @return an array of listeners for the named property
|
||||
*/
|
||||
public final L[] getListeners(String name) {
|
||||
if (name != null) {
|
||||
L[] listeners = get(name);
|
||||
if (listeners != null) {
|
||||
return listeners.clone();
|
||||
}
|
||||
}
|
||||
return newArray(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the map contains
|
||||
* at least one listener to be notified.
|
||||
*
|
||||
* @param name the name of the property
|
||||
* @return {@code true} if at least one listener exists or
|
||||
* {@code false} otherwise
|
||||
*/
|
||||
public final synchronized boolean hasListeners(String name) {
|
||||
if (this.map == null) {
|
||||
return false;
|
||||
}
|
||||
L[] array = this.map.get(null);
|
||||
return (array != null) || ((name != null) && (null != this.map.get(name)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of entries from the map.
|
||||
* Each entry is a pair consisted of the property name
|
||||
* and the corresponding list of listeners.
|
||||
*
|
||||
* @return a set of entries from the map
|
||||
*/
|
||||
public final Set<Entry<String, L[]>> getEntries() {
|
||||
return (this.map != null)
|
||||
? this.map.entrySet()
|
||||
: Collections.<Entry<String, L[]>>emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a real listener from the proxy listener.
|
||||
* It is necessary because default proxy class is not serializable.
|
||||
*
|
||||
* @return a real listener
|
||||
*/
|
||||
public abstract L extract(L listener);
|
||||
}
|
||||
76
jdkSrc/jdk8/java/beans/ConstructorProperties.java
Normal file
76
jdkSrc/jdk8/java/beans/ConstructorProperties.java
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2013, 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.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
|
||||
/**
|
||||
<p>An annotation on a constructor that shows how the parameters of
|
||||
that constructor correspond to the constructed object's getter
|
||||
methods. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
public class Point {
|
||||
@ConstructorProperties({"x", "y"})
|
||||
public Point(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
private final int x, y;
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
The annotation shows that the first parameter of the constructor
|
||||
can be retrieved with the {@code getX()} method and the second with
|
||||
the {@code getY()} method. Since parameter names are not in
|
||||
general available at runtime, without the annotation there would be
|
||||
no way to know whether the parameters correspond to {@code getX()}
|
||||
and {@code getY()} or the other way around.
|
||||
|
||||
@since 1.6
|
||||
*/
|
||||
@Documented @Target(CONSTRUCTOR) @Retention(RUNTIME)
|
||||
public @interface ConstructorProperties {
|
||||
/**
|
||||
<p>The getter names.</p>
|
||||
@return the getter names corresponding to the parameters in the
|
||||
annotated constructor.
|
||||
*/
|
||||
String[] value();
|
||||
}
|
||||
65
jdkSrc/jdk8/java/beans/Customizer.java
Normal file
65
jdkSrc/jdk8/java/beans/Customizer.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 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;
|
||||
|
||||
/**
|
||||
* A customizer class provides a complete custom GUI for customizing
|
||||
* a target Java Bean.
|
||||
* <P>
|
||||
* Each customizer should inherit from the java.awt.Component class so
|
||||
* it can be instantiated inside an AWT dialog or panel.
|
||||
* <P>
|
||||
* Each customizer should have a null constructor.
|
||||
*/
|
||||
|
||||
public interface Customizer {
|
||||
|
||||
/**
|
||||
* Set the object to be customized. This method should be called only
|
||||
* once, before the Customizer has been added to any parent AWT container.
|
||||
* @param bean The object to be customized.
|
||||
*/
|
||||
void setObject(Object bean);
|
||||
|
||||
/**
|
||||
* Register a listener for the PropertyChange event. The customizer
|
||||
* should fire a PropertyChange event whenever it changes the target
|
||||
* bean in a way that might require the displayed properties to be
|
||||
* refreshed.
|
||||
*
|
||||
* @param listener An object to be invoked when a PropertyChange
|
||||
* event is fired.
|
||||
*/
|
||||
void addPropertyChangeListener(PropertyChangeListener listener);
|
||||
|
||||
/**
|
||||
* Remove a listener for the PropertyChange event.
|
||||
*
|
||||
* @param listener The PropertyChange listener to be removed.
|
||||
*/
|
||||
void removePropertyChangeListener(PropertyChangeListener listener);
|
||||
|
||||
}
|
||||
420
jdkSrc/jdk8/java/beans/DefaultPersistenceDelegate.java
Normal file
420
jdkSrc/jdk8/java/beans/DefaultPersistenceDelegate.java
Normal file
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, 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.util.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Objects;
|
||||
import sun.reflect.misc.*;
|
||||
|
||||
|
||||
/**
|
||||
* The <code>DefaultPersistenceDelegate</code> is a concrete implementation of
|
||||
* the abstract <code>PersistenceDelegate</code> class and
|
||||
* is the delegate used by default for classes about
|
||||
* which no information is available. The <code>DefaultPersistenceDelegate</code>
|
||||
* provides, version resilient, public API-based persistence for
|
||||
* classes that follow the JavaBeans™ conventions without any class specific
|
||||
* configuration.
|
||||
* <p>
|
||||
* The key assumptions are that the class has a nullary constructor
|
||||
* and that its state is accurately represented by matching pairs
|
||||
* of "setter" and "getter" methods in the order they are returned
|
||||
* by the Introspector.
|
||||
* In addition to providing code-free persistence for JavaBeans,
|
||||
* the <code>DefaultPersistenceDelegate</code> provides a convenient means
|
||||
* to effect persistent storage for classes that have a constructor
|
||||
* that, while not nullary, simply requires some property values
|
||||
* as arguments.
|
||||
*
|
||||
* @see #DefaultPersistenceDelegate(String[])
|
||||
* @see java.beans.Introspector
|
||||
*
|
||||
* @since 1.4
|
||||
*
|
||||
* @author Philip Milne
|
||||
*/
|
||||
|
||||
public class DefaultPersistenceDelegate extends PersistenceDelegate {
|
||||
private static final String[] EMPTY = {};
|
||||
private final String[] constructor;
|
||||
private Boolean definesEquals;
|
||||
|
||||
/**
|
||||
* Creates a persistence delegate for a class with a nullary constructor.
|
||||
*
|
||||
* @see #DefaultPersistenceDelegate(java.lang.String[])
|
||||
*/
|
||||
public DefaultPersistenceDelegate() {
|
||||
this.constructor = EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a default persistence delegate for a class with a
|
||||
* constructor whose arguments are the values of the property
|
||||
* names as specified by <code>constructorPropertyNames</code>.
|
||||
* The constructor arguments are created by
|
||||
* evaluating the property names in the order they are supplied.
|
||||
* To use this class to specify a single preferred constructor for use
|
||||
* in the serialization of a particular type, we state the
|
||||
* names of the properties that make up the constructor's
|
||||
* arguments. For example, the <code>Font</code> class which
|
||||
* does not define a nullary constructor can be handled
|
||||
* with the following persistence delegate:
|
||||
*
|
||||
* <pre>
|
||||
* new DefaultPersistenceDelegate(new String[]{"name", "style", "size"});
|
||||
* </pre>
|
||||
*
|
||||
* @param constructorPropertyNames The property names for the arguments of this constructor.
|
||||
*
|
||||
* @see #instantiate
|
||||
*/
|
||||
public DefaultPersistenceDelegate(String[] constructorPropertyNames) {
|
||||
this.constructor = (constructorPropertyNames == null) ? EMPTY : constructorPropertyNames.clone();
|
||||
}
|
||||
|
||||
private static boolean definesEquals(Class<?> type) {
|
||||
try {
|
||||
return type == type.getMethod("equals", Object.class).getDeclaringClass();
|
||||
}
|
||||
catch(NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean definesEquals(Object instance) {
|
||||
if (definesEquals != null) {
|
||||
return (definesEquals == Boolean.TRUE);
|
||||
}
|
||||
else {
|
||||
boolean result = definesEquals(instance.getClass());
|
||||
definesEquals = result ? Boolean.TRUE : Boolean.FALSE;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the number of arguments in the specified constructor is non-zero and
|
||||
* the class of <code>oldInstance</code> explicitly declares an "equals" method
|
||||
* this method returns the value of <code>oldInstance.equals(newInstance)</code>.
|
||||
* Otherwise, this method uses the superclass's definition which returns true if the
|
||||
* classes of the two instances are equal.
|
||||
*
|
||||
* @param oldInstance The instance to be copied.
|
||||
* @param newInstance The instance that is to be modified.
|
||||
* @return True if an equivalent copy of <code>newInstance</code> may be
|
||||
* created by applying a series of mutations to <code>oldInstance</code>.
|
||||
*
|
||||
* @see #DefaultPersistenceDelegate(String[])
|
||||
*/
|
||||
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
|
||||
// Assume the instance is either mutable or a singleton
|
||||
// if it has a nullary constructor.
|
||||
return (constructor.length == 0) || !definesEquals(oldInstance) ?
|
||||
super.mutatesTo(oldInstance, newInstance) :
|
||||
oldInstance.equals(newInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* This default implementation of the <code>instantiate</code> method returns
|
||||
* an expression containing the predefined method name "new" which denotes a
|
||||
* call to a constructor with the arguments as specified in
|
||||
* the <code>DefaultPersistenceDelegate</code>'s constructor.
|
||||
*
|
||||
* @param oldInstance The instance to be instantiated.
|
||||
* @param out The code output stream.
|
||||
* @return An expression whose value is <code>oldInstance</code>.
|
||||
*
|
||||
* @throws NullPointerException if {@code out} is {@code null}
|
||||
* and this value is used in the method
|
||||
*
|
||||
* @see #DefaultPersistenceDelegate(String[])
|
||||
*/
|
||||
protected Expression instantiate(Object oldInstance, Encoder out) {
|
||||
int nArgs = constructor.length;
|
||||
Class<?> type = oldInstance.getClass();
|
||||
Object[] constructorArgs = new Object[nArgs];
|
||||
for(int i = 0; i < nArgs; i++) {
|
||||
try {
|
||||
Method method = findMethod(type, this.constructor[i]);
|
||||
constructorArgs[i] = MethodUtil.invoke(method, oldInstance, new Object[0]);
|
||||
}
|
||||
catch (Exception e) {
|
||||
out.getExceptionListener().exceptionThrown(e);
|
||||
}
|
||||
}
|
||||
return new Expression(oldInstance, oldInstance.getClass(), "new", constructorArgs);
|
||||
}
|
||||
|
||||
private Method findMethod(Class<?> type, String property) {
|
||||
if (property == null) {
|
||||
throw new IllegalArgumentException("Property name is null");
|
||||
}
|
||||
PropertyDescriptor pd = getPropertyDescriptor(type, property);
|
||||
if (pd == null) {
|
||||
throw new IllegalStateException("Could not find property by the name " + property);
|
||||
}
|
||||
Method method = pd.getReadMethod();
|
||||
if (method == null) {
|
||||
throw new IllegalStateException("Could not find getter for the property " + property);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
private void doProperty(Class<?> type, PropertyDescriptor pd, Object oldInstance, Object newInstance, Encoder out) throws Exception {
|
||||
Method getter = pd.getReadMethod();
|
||||
Method setter = pd.getWriteMethod();
|
||||
|
||||
if (getter != null && setter != null) {
|
||||
Expression oldGetExp = new Expression(oldInstance, getter.getName(), new Object[]{});
|
||||
Expression newGetExp = new Expression(newInstance, getter.getName(), new Object[]{});
|
||||
Object oldValue = oldGetExp.getValue();
|
||||
Object newValue = newGetExp.getValue();
|
||||
out.writeExpression(oldGetExp);
|
||||
if (!Objects.equals(newValue, out.get(oldValue))) {
|
||||
// Search for a static constant with this value;
|
||||
Object e = (Object[])pd.getValue("enumerationValues");
|
||||
if (e instanceof Object[] && Array.getLength(e) % 3 == 0) {
|
||||
Object[] a = (Object[])e;
|
||||
for(int i = 0; i < a.length; i = i + 3) {
|
||||
try {
|
||||
Field f = type.getField((String)a[i]);
|
||||
if (f.get(null).equals(oldValue)) {
|
||||
out.remove(oldValue);
|
||||
out.writeExpression(new Expression(oldValue, f, "get", new Object[]{null}));
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {}
|
||||
}
|
||||
}
|
||||
invokeStatement(oldInstance, setter.getName(), new Object[]{oldValue}, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void invokeStatement(Object instance, String methodName, Object[] args, Encoder out) {
|
||||
out.writeStatement(new Statement(instance, methodName, args));
|
||||
}
|
||||
|
||||
// Write out the properties of this instance.
|
||||
private void initBean(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
|
||||
for (Field field : type.getFields()) {
|
||||
if (!ReflectUtil.isPackageAccessible(field.getDeclaringClass())) {
|
||||
continue;
|
||||
}
|
||||
int mod = field.getModifiers();
|
||||
if (Modifier.isFinal(mod) || Modifier.isStatic(mod) || Modifier.isTransient(mod)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
Expression oldGetExp = new Expression(field, "get", new Object[] { oldInstance });
|
||||
Expression newGetExp = new Expression(field, "get", new Object[] { newInstance });
|
||||
Object oldValue = oldGetExp.getValue();
|
||||
Object newValue = newGetExp.getValue();
|
||||
out.writeExpression(oldGetExp);
|
||||
if (!Objects.equals(newValue, out.get(oldValue))) {
|
||||
out.writeStatement(new Statement(field, "set", new Object[] { oldInstance, oldValue }));
|
||||
}
|
||||
}
|
||||
catch (Exception exception) {
|
||||
out.getExceptionListener().exceptionThrown(exception);
|
||||
}
|
||||
}
|
||||
BeanInfo info;
|
||||
try {
|
||||
info = Introspector.getBeanInfo(type);
|
||||
} catch (IntrospectionException exception) {
|
||||
return;
|
||||
}
|
||||
// Properties
|
||||
for (PropertyDescriptor d : info.getPropertyDescriptors()) {
|
||||
if (d.isTransient()) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
doProperty(type, d, oldInstance, newInstance, out);
|
||||
}
|
||||
catch (Exception e) {
|
||||
out.getExceptionListener().exceptionThrown(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Listeners
|
||||
/*
|
||||
Pending(milne). There is a general problem with the archival of
|
||||
listeners which is unresolved as of 1.4. Many of the methods
|
||||
which install one object inside another (typically "add" methods
|
||||
or setters) automatically install a listener on the "child" object
|
||||
so that its "parent" may respond to changes that are made to it.
|
||||
For example the JTable:setModel() method automatically adds a
|
||||
TableModelListener (the JTable itself in this case) to the supplied
|
||||
table model.
|
||||
|
||||
We do not need to explicitly add these listeners to the model in an
|
||||
archive as they will be added automatically by, in the above case,
|
||||
the JTable's "setModel" method. In some cases, we must specifically
|
||||
avoid trying to do this since the listener may be an inner class
|
||||
that cannot be instantiated using public API.
|
||||
|
||||
No general mechanism currently
|
||||
exists for differentiating between these kind of listeners and
|
||||
those which were added explicitly by the user. A mechanism must
|
||||
be created to provide a general means to differentiate these
|
||||
special cases so as to provide reliable persistence of listeners
|
||||
for the general case.
|
||||
*/
|
||||
if (!java.awt.Component.class.isAssignableFrom(type)) {
|
||||
return; // Just handle the listeners of Components for now.
|
||||
}
|
||||
for (EventSetDescriptor d : info.getEventSetDescriptors()) {
|
||||
if (d.isTransient()) {
|
||||
continue;
|
||||
}
|
||||
Class<?> listenerType = d.getListenerType();
|
||||
|
||||
|
||||
// The ComponentListener is added automatically, when
|
||||
// Contatiner:add is called on the parent.
|
||||
if (listenerType == java.awt.event.ComponentListener.class) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// JMenuItems have a change listener added to them in
|
||||
// their "add" methods to enable accessibility support -
|
||||
// see the add method in JMenuItem for details. We cannot
|
||||
// instantiate this instance as it is a private inner class
|
||||
// and do not need to do this anyway since it will be created
|
||||
// and installed by the "add" method. Special case this for now,
|
||||
// ignoring all change listeners on JMenuItems.
|
||||
if (listenerType == javax.swing.event.ChangeListener.class &&
|
||||
type == javax.swing.JMenuItem.class) {
|
||||
continue;
|
||||
}
|
||||
|
||||
EventListener[] oldL = new EventListener[0];
|
||||
EventListener[] newL = new EventListener[0];
|
||||
try {
|
||||
Method m = d.getGetListenerMethod();
|
||||
oldL = (EventListener[])MethodUtil.invoke(m, oldInstance, new Object[]{});
|
||||
newL = (EventListener[])MethodUtil.invoke(m, newInstance, new Object[]{});
|
||||
}
|
||||
catch (Exception e2) {
|
||||
try {
|
||||
Method m = type.getMethod("getListeners", new Class<?>[]{Class.class});
|
||||
oldL = (EventListener[])MethodUtil.invoke(m, oldInstance, new Object[]{listenerType});
|
||||
newL = (EventListener[])MethodUtil.invoke(m, newInstance, new Object[]{listenerType});
|
||||
}
|
||||
catch (Exception e3) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Asssume the listeners are in the same order and that there are no gaps.
|
||||
// Eventually, this may need to do true differencing.
|
||||
String addListenerMethodName = d.getAddListenerMethod().getName();
|
||||
for (int i = newL.length; i < oldL.length; i++) {
|
||||
// System.out.println("Adding listener: " + addListenerMethodName + oldL[i]);
|
||||
invokeStatement(oldInstance, addListenerMethodName, new Object[]{oldL[i]}, out);
|
||||
}
|
||||
|
||||
String removeListenerMethodName = d.getRemoveListenerMethod().getName();
|
||||
for (int i = oldL.length; i < newL.length; i++) {
|
||||
invokeStatement(oldInstance, removeListenerMethodName, new Object[]{newL[i]}, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This default implementation of the <code>initialize</code> method assumes
|
||||
* all state held in objects of this type is exposed via the
|
||||
* matching pairs of "setter" and "getter" methods in the order
|
||||
* they are returned by the Introspector. If a property descriptor
|
||||
* defines a "transient" attribute with a value equal to
|
||||
* <code>Boolean.TRUE</code> the property is ignored by this
|
||||
* default implementation. Note that this use of the word
|
||||
* "transient" is quite independent of the field modifier
|
||||
* that is used by the <code>ObjectOutputStream</code>.
|
||||
* <p>
|
||||
* For each non-transient property, an expression is created
|
||||
* in which the nullary "getter" method is applied
|
||||
* to the <code>oldInstance</code>. The value of this
|
||||
* expression is the value of the property in the instance that is
|
||||
* being serialized. If the value of this expression
|
||||
* in the cloned environment <code>mutatesTo</code> the
|
||||
* target value, the new value is initialized to make it
|
||||
* equivalent to the old value. In this case, because
|
||||
* the property value has not changed there is no need to
|
||||
* call the corresponding "setter" method and no statement
|
||||
* is emitted. If not however, the expression for this value
|
||||
* is replaced with another expression (normally a constructor)
|
||||
* and the corresponding "setter" method is called to install
|
||||
* the new property value in the object. This scheme removes
|
||||
* default information from the output produced by streams
|
||||
* using this delegate.
|
||||
* <p>
|
||||
* In passing these statements to the output stream, where they
|
||||
* will be executed, side effects are made to the <code>newInstance</code>.
|
||||
* In most cases this allows the problem of properties
|
||||
* whose values depend on each other to actually help the
|
||||
* serialization process by making the number of statements
|
||||
* that need to be written to the output smaller. In general,
|
||||
* the problem of handling interdependent properties is reduced to
|
||||
* that of finding an order for the properties in
|
||||
* a class such that no property value depends on the value of
|
||||
* a subsequent property.
|
||||
*
|
||||
* @param type the type of the instances
|
||||
* @param oldInstance The instance to be copied.
|
||||
* @param newInstance The instance that is to be modified.
|
||||
* @param out The stream to which any initialization statements should be written.
|
||||
*
|
||||
* @throws NullPointerException if {@code out} is {@code null}
|
||||
*
|
||||
* @see java.beans.Introspector#getBeanInfo
|
||||
* @see java.beans.PropertyDescriptor
|
||||
*/
|
||||
protected void initialize(Class<?> type,
|
||||
Object oldInstance, Object newInstance,
|
||||
Encoder out)
|
||||
{
|
||||
// System.out.println("DefulatPD:initialize" + type);
|
||||
super.initialize(type, oldInstance, newInstance, out);
|
||||
if (oldInstance.getClass() == type) { // !type.isInterface()) {
|
||||
initBean(type, oldInstance, newInstance, out);
|
||||
}
|
||||
}
|
||||
|
||||
private static PropertyDescriptor getPropertyDescriptor(Class<?> type, String property) {
|
||||
try {
|
||||
for (PropertyDescriptor pd : Introspector.getBeanInfo(type).getPropertyDescriptors()) {
|
||||
if (property.equals(pd.getName()))
|
||||
return pd;
|
||||
}
|
||||
} catch (IntrospectionException exception) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
89
jdkSrc/jdk8/java/beans/DesignMode.java
Normal file
89
jdkSrc/jdk8/java/beans/DesignMode.java
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, 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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This interface is intended to be implemented by, or delegated from, instances
|
||||
* of java.beans.beancontext.BeanContext, in order to propagate to its nested hierarchy
|
||||
* of java.beans.beancontext.BeanContextChild instances, the current "designTime" property.
|
||||
* <p>
|
||||
* The JavaBeans™ specification defines the notion of design time as is a
|
||||
* mode in which JavaBeans instances should function during their composition
|
||||
* and customization in a interactive design, composition or construction tool,
|
||||
* as opposed to runtime when the JavaBean is part of an applet, application,
|
||||
* or other live Java executable abstraction.
|
||||
*
|
||||
* @author Laurence P. G. Cable
|
||||
* @since 1.2
|
||||
*
|
||||
* @see java.beans.beancontext.BeanContext
|
||||
* @see java.beans.beancontext.BeanContextChild
|
||||
* @see java.beans.beancontext.BeanContextMembershipListener
|
||||
* @see java.beans.PropertyChangeEvent
|
||||
*/
|
||||
|
||||
public interface DesignMode {
|
||||
|
||||
/**
|
||||
* The standard value of the propertyName as fired from a BeanContext or
|
||||
* other source of PropertyChangeEvents.
|
||||
*/
|
||||
|
||||
static String PROPERTYNAME = "designTime";
|
||||
|
||||
/**
|
||||
* Sets the "value" of the "designTime" property.
|
||||
* <p>
|
||||
* If the implementing object is an instance of java.beans.beancontext.BeanContext,
|
||||
* or a subinterface thereof, then that BeanContext should fire a
|
||||
* PropertyChangeEvent, to its registered BeanContextMembershipListeners, with
|
||||
* parameters:
|
||||
* <ul>
|
||||
* <li><code>propertyName</code> - <code>java.beans.DesignMode.PROPERTYNAME</code>
|
||||
* <li><code>oldValue</code> - previous value of "designTime"
|
||||
* <li><code>newValue</code> - current value of "designTime"
|
||||
* </ul>
|
||||
* Note it is illegal for a BeanContextChild to invoke this method
|
||||
* associated with a BeanContext that it is nested within.
|
||||
*
|
||||
* @param designTime the current "value" of the "designTime" property
|
||||
* @see java.beans.beancontext.BeanContext
|
||||
* @see java.beans.beancontext.BeanContextMembershipListener
|
||||
* @see java.beans.PropertyChangeEvent
|
||||
*/
|
||||
|
||||
void setDesignTime(boolean designTime);
|
||||
|
||||
/**
|
||||
* A value of true denotes that JavaBeans should behave in design time
|
||||
* mode, a value of false denotes runtime behavior.
|
||||
*
|
||||
* @return the current "value" of the "designTime" property.
|
||||
*/
|
||||
|
||||
boolean isDesignTime();
|
||||
}
|
||||
351
jdkSrc/jdk8/java/beans/Encoder.java
Normal file
351
jdkSrc/jdk8/java/beans/Encoder.java
Normal file
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2011, 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 com.sun.beans.finder.PersistenceDelegateFinder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An <code>Encoder</code> is a class which can be used to create
|
||||
* files or streams that encode the state of a collection of
|
||||
* JavaBeans in terms of their public APIs. The <code>Encoder</code>,
|
||||
* in conjunction with its persistence delegates, is responsible for
|
||||
* breaking the object graph down into a series of <code>Statements</code>s
|
||||
* and <code>Expression</code>s which can be used to create it.
|
||||
* A subclass typically provides a syntax for these expressions
|
||||
* using some human readable form - like Java source code or XML.
|
||||
*
|
||||
* @since 1.4
|
||||
*
|
||||
* @author Philip Milne
|
||||
*/
|
||||
|
||||
public class Encoder {
|
||||
private final PersistenceDelegateFinder finder = new PersistenceDelegateFinder();
|
||||
private Map<Object, Expression> bindings = new IdentityHashMap<>();
|
||||
private ExceptionListener exceptionListener;
|
||||
boolean executeStatements = true;
|
||||
private Map<Object, Object> attributes;
|
||||
|
||||
/**
|
||||
* Write the specified object to the output stream.
|
||||
* The serialized form will denote a series of
|
||||
* expressions, the combined effect of which will create
|
||||
* an equivalent object when the input stream is read.
|
||||
* By default, the object is assumed to be a <em>JavaBean</em>
|
||||
* with a nullary constructor, whose state is defined by
|
||||
* the matching pairs of "setter" and "getter" methods
|
||||
* returned by the Introspector.
|
||||
*
|
||||
* @param o The object to be written to the stream.
|
||||
*
|
||||
* @see XMLDecoder#readObject
|
||||
*/
|
||||
protected void writeObject(Object o) {
|
||||
if (o == this) {
|
||||
return;
|
||||
}
|
||||
PersistenceDelegate info = getPersistenceDelegate(o == null ? null : o.getClass());
|
||||
info.writeObject(o, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the exception handler for this stream to <code>exceptionListener</code>.
|
||||
* The exception handler is notified when this stream catches recoverable
|
||||
* exceptions.
|
||||
*
|
||||
* @param exceptionListener The exception handler for this stream;
|
||||
* if <code>null</code> the default exception listener will be used.
|
||||
*
|
||||
* @see #getExceptionListener
|
||||
*/
|
||||
public void setExceptionListener(ExceptionListener exceptionListener) {
|
||||
this.exceptionListener = exceptionListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exception handler for this stream.
|
||||
*
|
||||
* @return The exception handler for this stream;
|
||||
* Will return the default exception listener if this has not explicitly been set.
|
||||
*
|
||||
* @see #setExceptionListener
|
||||
*/
|
||||
public ExceptionListener getExceptionListener() {
|
||||
return (exceptionListener != null) ? exceptionListener : Statement.defaultExceptionListener;
|
||||
}
|
||||
|
||||
Object getValue(Expression exp) {
|
||||
try {
|
||||
return (exp == null) ? null : exp.getValue();
|
||||
}
|
||||
catch (Exception e) {
|
||||
getExceptionListener().exceptionThrown(e);
|
||||
throw new RuntimeException("failed to evaluate: " + exp.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the persistence delegate for the given type.
|
||||
* The persistence delegate is calculated by applying
|
||||
* the following rules in order:
|
||||
* <ol>
|
||||
* <li>
|
||||
* If a persistence delegate is associated with the given type
|
||||
* by using the {@link #setPersistenceDelegate} method
|
||||
* it is returned.
|
||||
* <li>
|
||||
* A persistence delegate is then looked up by the name
|
||||
* composed of the the fully qualified name of the given type
|
||||
* and the "PersistenceDelegate" postfix.
|
||||
* For example, a persistence delegate for the {@code Bean} class
|
||||
* should be named {@code BeanPersistenceDelegate}
|
||||
* and located in the same package.
|
||||
* <pre>
|
||||
* public class Bean { ... }
|
||||
* public class BeanPersistenceDelegate { ... }</pre>
|
||||
* The instance of the {@code BeanPersistenceDelegate} class
|
||||
* is returned for the {@code Bean} class.
|
||||
* <li>
|
||||
* If the type is {@code null},
|
||||
* a shared internal persistence delegate is returned
|
||||
* that encodes {@code null} value.
|
||||
* <li>
|
||||
* If the type is a {@code enum} declaration,
|
||||
* a shared internal persistence delegate is returned
|
||||
* that encodes constants of this enumeration
|
||||
* by their names.
|
||||
* <li>
|
||||
* If the type is a primitive type or the corresponding wrapper,
|
||||
* a shared internal persistence delegate is returned
|
||||
* that encodes values of the given type.
|
||||
* <li>
|
||||
* If the type is an array,
|
||||
* a shared internal persistence delegate is returned
|
||||
* that encodes an array of the appropriate type and length,
|
||||
* and each of its elements as if they are properties.
|
||||
* <li>
|
||||
* If the type is a proxy,
|
||||
* a shared internal persistence delegate is returned
|
||||
* that encodes a proxy instance by using
|
||||
* the {@link java.lang.reflect.Proxy#newProxyInstance} method.
|
||||
* <li>
|
||||
* If the {@link BeanInfo} for this type has a {@link BeanDescriptor}
|
||||
* which defined a "persistenceDelegate" attribute,
|
||||
* the value of this named attribute is returned.
|
||||
* <li>
|
||||
* In all other cases the default persistence delegate is returned.
|
||||
* The default persistence delegate assumes the type is a <em>JavaBean</em>,
|
||||
* implying that it has a default constructor and that its state
|
||||
* may be characterized by the matching pairs of "setter" and "getter"
|
||||
* methods returned by the {@link Introspector} class.
|
||||
* The default constructor is the constructor with the greatest number
|
||||
* of parameters that has the {@link ConstructorProperties} annotation.
|
||||
* If none of the constructors has the {@code ConstructorProperties} annotation,
|
||||
* then the nullary constructor (constructor with no parameters) will be used.
|
||||
* For example, in the following code fragment, the nullary constructor
|
||||
* for the {@code Foo} class will be used,
|
||||
* while the two-parameter constructor
|
||||
* for the {@code Bar} class will be used.
|
||||
* <pre>
|
||||
* public class Foo {
|
||||
* public Foo() { ... }
|
||||
* public Foo(int x) { ... }
|
||||
* }
|
||||
* public class Bar {
|
||||
* public Bar() { ... }
|
||||
* @ConstructorProperties({"x"})
|
||||
* public Bar(int x) { ... }
|
||||
* @ConstructorProperties({"x", "y"})
|
||||
* public Bar(int x, int y) { ... }
|
||||
* }</pre>
|
||||
* </ol>
|
||||
*
|
||||
* @param type the class of the objects
|
||||
* @return the persistence delegate for the given type
|
||||
*
|
||||
* @see #setPersistenceDelegate
|
||||
* @see java.beans.Introspector#getBeanInfo
|
||||
* @see java.beans.BeanInfo#getBeanDescriptor
|
||||
*/
|
||||
public PersistenceDelegate getPersistenceDelegate(Class<?> type) {
|
||||
PersistenceDelegate pd = this.finder.find(type);
|
||||
if (pd == null) {
|
||||
pd = MetaData.getPersistenceDelegate(type);
|
||||
if (pd != null) {
|
||||
this.finder.register(type, pd);
|
||||
}
|
||||
}
|
||||
return pd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates the specified persistence delegate with the given type.
|
||||
*
|
||||
* @param type the class of objects that the specified persistence delegate applies to
|
||||
* @param delegate the persistence delegate for instances of the given type
|
||||
*
|
||||
* @see #getPersistenceDelegate
|
||||
* @see java.beans.Introspector#getBeanInfo
|
||||
* @see java.beans.BeanInfo#getBeanDescriptor
|
||||
*/
|
||||
public void setPersistenceDelegate(Class<?> type, PersistenceDelegate delegate) {
|
||||
this.finder.register(type, delegate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the entry for this instance, returning the old entry.
|
||||
*
|
||||
* @param oldInstance The entry that should be removed.
|
||||
* @return The entry that was removed.
|
||||
*
|
||||
* @see #get
|
||||
*/
|
||||
public Object remove(Object oldInstance) {
|
||||
Expression exp = bindings.remove(oldInstance);
|
||||
return getValue(exp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a tentative value for <code>oldInstance</code> in
|
||||
* the environment created by this stream. A persistence
|
||||
* delegate can use its <code>mutatesTo</code> method to
|
||||
* determine whether this value may be initialized to
|
||||
* form the equivalent object at the output or whether
|
||||
* a new object must be instantiated afresh. If the
|
||||
* stream has not yet seen this value, null is returned.
|
||||
*
|
||||
* @param oldInstance The instance to be looked up.
|
||||
* @return The object, null if the object has not been seen before.
|
||||
*/
|
||||
public Object get(Object oldInstance) {
|
||||
if (oldInstance == null || oldInstance == this ||
|
||||
oldInstance.getClass() == String.class) {
|
||||
return oldInstance;
|
||||
}
|
||||
Expression exp = bindings.get(oldInstance);
|
||||
return getValue(exp);
|
||||
}
|
||||
|
||||
private Object writeObject1(Object oldInstance) {
|
||||
Object o = get(oldInstance);
|
||||
if (o == null) {
|
||||
writeObject(oldInstance);
|
||||
o = get(oldInstance);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
private Statement cloneStatement(Statement oldExp) {
|
||||
Object oldTarget = oldExp.getTarget();
|
||||
Object newTarget = writeObject1(oldTarget);
|
||||
|
||||
Object[] oldArgs = oldExp.getArguments();
|
||||
Object[] newArgs = new Object[oldArgs.length];
|
||||
for (int i = 0; i < oldArgs.length; i++) {
|
||||
newArgs[i] = writeObject1(oldArgs[i]);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes statement <code>oldStm</code> to the stream.
|
||||
* The <code>oldStm</code> should be written entirely
|
||||
* in terms of the callers environment, i.e. the
|
||||
* target and all arguments should be part of the
|
||||
* object graph being written. These expressions
|
||||
* represent a series of "what happened" expressions
|
||||
* which tell the output stream how to produce an
|
||||
* object graph like the original.
|
||||
* <p>
|
||||
* The implementation of this method will produce
|
||||
* a second expression to represent the same expression in
|
||||
* an environment that will exist when the stream is read.
|
||||
* This is achieved simply by calling <code>writeObject</code>
|
||||
* on the target and all the arguments and building a new
|
||||
* expression with the results.
|
||||
*
|
||||
* @param oldStm The expression to be written to the stream.
|
||||
*/
|
||||
public void writeStatement(Statement oldStm) {
|
||||
// System.out.println("writeStatement: " + oldExp);
|
||||
Statement newStm = cloneStatement(oldStm);
|
||||
if (oldStm.getTarget() != this && executeStatements) {
|
||||
try {
|
||||
newStm.execute();
|
||||
} catch (Exception e) {
|
||||
getExceptionListener().exceptionThrown(new Exception("Encoder: discarding statement "
|
||||
+ newStm, e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The implementation first checks to see if an
|
||||
* expression with this value has already been written.
|
||||
* If not, the expression is cloned, using
|
||||
* the same procedure as <code>writeStatement</code>,
|
||||
* and the value of this expression is reconciled
|
||||
* with the value of the cloned expression
|
||||
* by calling <code>writeObject</code>.
|
||||
*
|
||||
* @param oldExp The expression to be written to the stream.
|
||||
*/
|
||||
public void writeExpression(Expression oldExp) {
|
||||
// System.out.println("Encoder::writeExpression: " + oldExp);
|
||||
Object oldValue = getValue(oldExp);
|
||||
if (get(oldValue) != null) {
|
||||
return;
|
||||
}
|
||||
bindings.put(oldValue, (Expression)cloneStatement(oldExp));
|
||||
writeObject(oldValue);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
bindings.clear();
|
||||
}
|
||||
|
||||
// Package private method for setting an attributes table for the encoder
|
||||
void setAttribute(Object key, Object value) {
|
||||
if (attributes == null) {
|
||||
attributes = new HashMap<>();
|
||||
}
|
||||
attributes.put(key, value);
|
||||
}
|
||||
|
||||
Object getAttribute(Object key) {
|
||||
if (attributes == null) {
|
||||
return null;
|
||||
}
|
||||
return attributes.get(key);
|
||||
}
|
||||
}
|
||||
715
jdkSrc/jdk8/java/beans/EventHandler.java
Normal file
715
jdkSrc/jdk8/java/beans/EventHandler.java
Normal file
@@ -0,0 +1,715 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, 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.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import sun.reflect.misc.MethodUtil;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
* The <code>EventHandler</code> class provides
|
||||
* support for dynamically generating event listeners whose methods
|
||||
* execute a simple statement involving an incoming event object
|
||||
* and a target object.
|
||||
* <p>
|
||||
* The <code>EventHandler</code> class is intended to be used by interactive tools, such as
|
||||
* application builders, that allow developers to make connections between
|
||||
* beans. Typically connections are made from a user interface bean
|
||||
* (the event <em>source</em>)
|
||||
* to an application logic bean (the <em>target</em>). The most effective
|
||||
* connections of this kind isolate the application logic from the user
|
||||
* interface. For example, the <code>EventHandler</code> for a
|
||||
* connection from a <code>JCheckBox</code> to a method
|
||||
* that accepts a boolean value can deal with extracting the state
|
||||
* of the check box and passing it directly to the method so that
|
||||
* the method is isolated from the user interface layer.
|
||||
* <p>
|
||||
* Inner classes are another, more general way to handle events from
|
||||
* user interfaces. The <code>EventHandler</code> class
|
||||
* handles only a subset of what is possible using inner
|
||||
* classes. However, <code>EventHandler</code> works better
|
||||
* with the long-term persistence scheme than inner classes.
|
||||
* Also, using <code>EventHandler</code> in large applications in
|
||||
* which the same interface is implemented many times can
|
||||
* reduce the disk and memory footprint of the application.
|
||||
* <p>
|
||||
* The reason that listeners created with <code>EventHandler</code>
|
||||
* have such a small
|
||||
* footprint is that the <code>Proxy</code> class, on which
|
||||
* the <code>EventHandler</code> relies, shares implementations
|
||||
* of identical
|
||||
* interfaces. For example, if you use
|
||||
* the <code>EventHandler</code> <code>create</code> methods to make
|
||||
* all the <code>ActionListener</code>s in an application,
|
||||
* all the action listeners will be instances of a single class
|
||||
* (one created by the <code>Proxy</code> class).
|
||||
* In general, listeners based on
|
||||
* the <code>Proxy</code> class require one listener class
|
||||
* to be created per <em>listener type</em> (interface),
|
||||
* whereas the inner class
|
||||
* approach requires one class to be created per <em>listener</em>
|
||||
* (object that implements the interface).
|
||||
*
|
||||
* <p>
|
||||
* You don't generally deal directly with <code>EventHandler</code>
|
||||
* instances.
|
||||
* Instead, you use one of the <code>EventHandler</code>
|
||||
* <code>create</code> methods to create
|
||||
* an object that implements a given listener interface.
|
||||
* This listener object uses an <code>EventHandler</code> object
|
||||
* behind the scenes to encapsulate information about the
|
||||
* event, the object to be sent a message when the event occurs,
|
||||
* the message (method) to be sent, and any argument
|
||||
* to the method.
|
||||
* The following section gives examples of how to create listener
|
||||
* objects using the <code>create</code> methods.
|
||||
*
|
||||
* <h2>Examples of Using EventHandler</h2>
|
||||
*
|
||||
* The simplest use of <code>EventHandler</code> is to install
|
||||
* a listener that calls a method on the target object with no arguments.
|
||||
* In the following example we create an <code>ActionListener</code>
|
||||
* that invokes the <code>toFront</code> method on an instance
|
||||
* of <code>javax.swing.JFrame</code>.
|
||||
*
|
||||
* <blockquote>
|
||||
*<pre>
|
||||
*myButton.addActionListener(
|
||||
* (ActionListener)EventHandler.create(ActionListener.class, frame, "toFront"));
|
||||
*</pre>
|
||||
* </blockquote>
|
||||
*
|
||||
* When <code>myButton</code> is pressed, the statement
|
||||
* <code>frame.toFront()</code> will be executed. One could get
|
||||
* the same effect, with some additional compile-time type safety,
|
||||
* by defining a new implementation of the <code>ActionListener</code>
|
||||
* interface and adding an instance of it to the button:
|
||||
*
|
||||
* <blockquote>
|
||||
*<pre>
|
||||
//Equivalent code using an inner class instead of EventHandler.
|
||||
*myButton.addActionListener(new ActionListener() {
|
||||
* public void actionPerformed(ActionEvent e) {
|
||||
* frame.toFront();
|
||||
* }
|
||||
*});
|
||||
*</pre>
|
||||
* </blockquote>
|
||||
*
|
||||
* The next simplest use of <code>EventHandler</code> is
|
||||
* to extract a property value from the first argument
|
||||
* of the method in the listener interface (typically an event object)
|
||||
* and use it to set the value of a property in the target object.
|
||||
* In the following example we create an <code>ActionListener</code> that
|
||||
* sets the <code>nextFocusableComponent</code> property of the target
|
||||
* (myButton) object to the value of the "source" property of the event.
|
||||
*
|
||||
* <blockquote>
|
||||
*<pre>
|
||||
*EventHandler.create(ActionListener.class, myButton, "nextFocusableComponent", "source")
|
||||
*</pre>
|
||||
* </blockquote>
|
||||
*
|
||||
* This would correspond to the following inner class implementation:
|
||||
*
|
||||
* <blockquote>
|
||||
*<pre>
|
||||
//Equivalent code using an inner class instead of EventHandler.
|
||||
*new ActionListener() {
|
||||
* public void actionPerformed(ActionEvent e) {
|
||||
* myButton.setNextFocusableComponent((Component)e.getSource());
|
||||
* }
|
||||
*}
|
||||
*</pre>
|
||||
* </blockquote>
|
||||
*
|
||||
* It's also possible to create an <code>EventHandler</code> that
|
||||
* just passes the incoming event object to the target's action.
|
||||
* If the fourth <code>EventHandler.create</code> argument is
|
||||
* an empty string, then the event is just passed along:
|
||||
*
|
||||
* <blockquote>
|
||||
*<pre>
|
||||
*EventHandler.create(ActionListener.class, target, "doActionEvent", "")
|
||||
*</pre>
|
||||
* </blockquote>
|
||||
*
|
||||
* This would correspond to the following inner class implementation:
|
||||
*
|
||||
* <blockquote>
|
||||
*<pre>
|
||||
//Equivalent code using an inner class instead of EventHandler.
|
||||
*new ActionListener() {
|
||||
* public void actionPerformed(ActionEvent e) {
|
||||
* target.doActionEvent(e);
|
||||
* }
|
||||
*}
|
||||
*</pre>
|
||||
* </blockquote>
|
||||
*
|
||||
* Probably the most common use of <code>EventHandler</code>
|
||||
* is to extract a property value from the
|
||||
* <em>source</em> of the event object and set this value as
|
||||
* the value of a property of the target object.
|
||||
* In the following example we create an <code>ActionListener</code> that
|
||||
* sets the "label" property of the target
|
||||
* object to the value of the "text" property of the
|
||||
* source (the value of the "source" property) of the event.
|
||||
*
|
||||
* <blockquote>
|
||||
*<pre>
|
||||
*EventHandler.create(ActionListener.class, myButton, "label", "source.text")
|
||||
*</pre>
|
||||
* </blockquote>
|
||||
*
|
||||
* This would correspond to the following inner class implementation:
|
||||
*
|
||||
* <blockquote>
|
||||
*<pre>
|
||||
//Equivalent code using an inner class instead of EventHandler.
|
||||
*new ActionListener {
|
||||
* public void actionPerformed(ActionEvent e) {
|
||||
* myButton.setLabel(((JTextField)e.getSource()).getText());
|
||||
* }
|
||||
*}
|
||||
*</pre>
|
||||
* </blockquote>
|
||||
*
|
||||
* The event property may be "qualified" with an arbitrary number
|
||||
* of property prefixes delimited with the "." character. The "qualifying"
|
||||
* names that appear before the "." characters are taken as the names of
|
||||
* properties that should be applied, left-most first, to
|
||||
* the event object.
|
||||
* <p>
|
||||
* For example, the following action listener
|
||||
*
|
||||
* <blockquote>
|
||||
*<pre>
|
||||
*EventHandler.create(ActionListener.class, target, "a", "b.c.d")
|
||||
*</pre>
|
||||
* </blockquote>
|
||||
*
|
||||
* might be written as the following inner class
|
||||
* (assuming all the properties had canonical getter methods and
|
||||
* returned the appropriate types):
|
||||
*
|
||||
* <blockquote>
|
||||
*<pre>
|
||||
//Equivalent code using an inner class instead of EventHandler.
|
||||
*new ActionListener {
|
||||
* public void actionPerformed(ActionEvent e) {
|
||||
* target.setA(e.getB().getC().isD());
|
||||
* }
|
||||
*}
|
||||
*</pre>
|
||||
* </blockquote>
|
||||
* The target property may also be "qualified" with an arbitrary number
|
||||
* of property prefixs delimited with the "." character. For example, the
|
||||
* following action listener:
|
||||
* <pre>
|
||||
* EventHandler.create(ActionListener.class, target, "a.b", "c.d")
|
||||
* </pre>
|
||||
* might be written as the following inner class
|
||||
* (assuming all the properties had canonical getter methods and
|
||||
* returned the appropriate types):
|
||||
* <pre>
|
||||
* //Equivalent code using an inner class instead of EventHandler.
|
||||
* new ActionListener {
|
||||
* public void actionPerformed(ActionEvent e) {
|
||||
* target.getA().setB(e.getC().isD());
|
||||
* }
|
||||
*}
|
||||
*</pre>
|
||||
* <p>
|
||||
* As <code>EventHandler</code> ultimately relies on reflection to invoke
|
||||
* a method we recommend against targeting an overloaded method. For example,
|
||||
* if the target is an instance of the class <code>MyTarget</code> which is
|
||||
* defined as:
|
||||
* <pre>
|
||||
* public class MyTarget {
|
||||
* public void doIt(String);
|
||||
* public void doIt(Object);
|
||||
* }
|
||||
* </pre>
|
||||
* Then the method <code>doIt</code> is overloaded. EventHandler will invoke
|
||||
* the method that is appropriate based on the source. If the source is
|
||||
* null, then either method is appropriate and the one that is invoked is
|
||||
* undefined. For that reason we recommend against targeting overloaded
|
||||
* methods.
|
||||
*
|
||||
* @see java.lang.reflect.Proxy
|
||||
* @see java.util.EventObject
|
||||
*
|
||||
* @since 1.4
|
||||
*
|
||||
* @author Mark Davidson
|
||||
* @author Philip Milne
|
||||
* @author Hans Muller
|
||||
*
|
||||
*/
|
||||
public class EventHandler implements InvocationHandler {
|
||||
private Object target;
|
||||
private String action;
|
||||
private final String eventPropertyName;
|
||||
private final String listenerMethodName;
|
||||
private final AccessControlContext acc = AccessController.getContext();
|
||||
|
||||
/**
|
||||
* Creates a new <code>EventHandler</code> object;
|
||||
* you generally use one of the <code>create</code> methods
|
||||
* instead of invoking this constructor directly. Refer to
|
||||
* {@link java.beans.EventHandler#create(Class, Object, String, String)
|
||||
* the general version of create} for a complete description of
|
||||
* the <code>eventPropertyName</code> and <code>listenerMethodName</code>
|
||||
* parameter.
|
||||
*
|
||||
* @param target the object that will perform the action
|
||||
* @param action the name of a (possibly qualified) property or method on
|
||||
* the target
|
||||
* @param eventPropertyName the (possibly qualified) name of a readable property of the incoming event
|
||||
* @param listenerMethodName the name of the method in the listener interface that should trigger the action
|
||||
*
|
||||
* @throws NullPointerException if <code>target</code> is null
|
||||
* @throws NullPointerException if <code>action</code> is null
|
||||
*
|
||||
* @see EventHandler
|
||||
* @see #create(Class, Object, String, String, String)
|
||||
* @see #getTarget
|
||||
* @see #getAction
|
||||
* @see #getEventPropertyName
|
||||
* @see #getListenerMethodName
|
||||
*/
|
||||
@ConstructorProperties({"target", "action", "eventPropertyName", "listenerMethodName"})
|
||||
public EventHandler(Object target, String action, String eventPropertyName, String listenerMethodName) {
|
||||
this.target = target;
|
||||
this.action = action;
|
||||
if (target == null) {
|
||||
throw new NullPointerException("target must be non-null");
|
||||
}
|
||||
if (action == null) {
|
||||
throw new NullPointerException("action must be non-null");
|
||||
}
|
||||
this.eventPropertyName = eventPropertyName;
|
||||
this.listenerMethodName = listenerMethodName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object to which this event handler will send a message.
|
||||
*
|
||||
* @return the target of this event handler
|
||||
* @see #EventHandler(Object, String, String, String)
|
||||
*/
|
||||
public Object getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the target's writable property
|
||||
* that this event handler will set,
|
||||
* or the name of the method that this event handler
|
||||
* will invoke on the target.
|
||||
*
|
||||
* @return the action of this event handler
|
||||
* @see #EventHandler(Object, String, String, String)
|
||||
*/
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property of the event that should be
|
||||
* used in the action applied to the target.
|
||||
*
|
||||
* @return the property of the event
|
||||
*
|
||||
* @see #EventHandler(Object, String, String, String)
|
||||
*/
|
||||
public String getEventPropertyName() {
|
||||
return eventPropertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the method that will trigger the action.
|
||||
* A return value of <code>null</code> signifies that all methods in the
|
||||
* listener interface trigger the action.
|
||||
*
|
||||
* @return the name of the method that will trigger the action
|
||||
*
|
||||
* @see #EventHandler(Object, String, String, String)
|
||||
*/
|
||||
public String getListenerMethodName() {
|
||||
return listenerMethodName;
|
||||
}
|
||||
|
||||
private Object applyGetters(Object target, String getters) {
|
||||
if (getters == null || getters.equals("")) {
|
||||
return target;
|
||||
}
|
||||
int firstDot = getters.indexOf('.');
|
||||
if (firstDot == -1) {
|
||||
firstDot = getters.length();
|
||||
}
|
||||
String first = getters.substring(0, firstDot);
|
||||
String rest = getters.substring(Math.min(firstDot + 1, getters.length()));
|
||||
|
||||
try {
|
||||
Method getter = null;
|
||||
if (target != null) {
|
||||
getter = Statement.getMethod(target.getClass(),
|
||||
"get" + NameGenerator.capitalize(first),
|
||||
new Class<?>[]{});
|
||||
if (getter == null) {
|
||||
getter = Statement.getMethod(target.getClass(),
|
||||
"is" + NameGenerator.capitalize(first),
|
||||
new Class<?>[]{});
|
||||
}
|
||||
if (getter == null) {
|
||||
getter = Statement.getMethod(target.getClass(), first, new Class<?>[]{});
|
||||
}
|
||||
}
|
||||
if (getter == null) {
|
||||
throw new RuntimeException("No method called: " + first +
|
||||
" defined on " + target);
|
||||
}
|
||||
Object newTarget = MethodUtil.invoke(getter, target, new Object[]{});
|
||||
return applyGetters(newTarget, rest);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException("Failed to call method: " + first +
|
||||
" on " + target, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the appropriate property value from the event and
|
||||
* pass it to the action associated with
|
||||
* this <code>EventHandler</code>.
|
||||
*
|
||||
* @param proxy the proxy object
|
||||
* @param method the method in the listener interface
|
||||
* @return the result of applying the action to the target
|
||||
*
|
||||
* @see EventHandler
|
||||
*/
|
||||
public Object invoke(final Object proxy, final Method method, final Object[] arguments) {
|
||||
AccessControlContext acc = this.acc;
|
||||
if ((acc == null) && (System.getSecurityManager() != null)) {
|
||||
throw new SecurityException("AccessControlContext is not set");
|
||||
}
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
public Object run() {
|
||||
return invokeInternal(proxy, method, arguments);
|
||||
}
|
||||
}, acc);
|
||||
}
|
||||
|
||||
private Object invokeInternal(Object proxy, Method method, Object[] arguments) {
|
||||
String methodName = method.getName();
|
||||
if (method.getDeclaringClass() == Object.class) {
|
||||
// Handle the Object public methods.
|
||||
if (methodName.equals("hashCode")) {
|
||||
return new Integer(System.identityHashCode(proxy));
|
||||
} else if (methodName.equals("equals")) {
|
||||
return (proxy == arguments[0] ? Boolean.TRUE : Boolean.FALSE);
|
||||
} else if (methodName.equals("toString")) {
|
||||
return proxy.getClass().getName() + '@' + Integer.toHexString(proxy.hashCode());
|
||||
}
|
||||
}
|
||||
|
||||
if (listenerMethodName == null || listenerMethodName.equals(methodName)) {
|
||||
Class[] argTypes = null;
|
||||
Object[] newArgs = null;
|
||||
|
||||
if (eventPropertyName == null) { // Nullary method.
|
||||
newArgs = new Object[]{};
|
||||
argTypes = new Class<?>[]{};
|
||||
}
|
||||
else {
|
||||
Object input = applyGetters(arguments[0], getEventPropertyName());
|
||||
newArgs = new Object[]{input};
|
||||
argTypes = new Class<?>[]{input == null ? null :
|
||||
input.getClass()};
|
||||
}
|
||||
try {
|
||||
int lastDot = action.lastIndexOf('.');
|
||||
if (lastDot != -1) {
|
||||
target = applyGetters(target, action.substring(0, lastDot));
|
||||
action = action.substring(lastDot + 1);
|
||||
}
|
||||
Method targetMethod = Statement.getMethod(
|
||||
target.getClass(), action, argTypes);
|
||||
if (targetMethod == null) {
|
||||
targetMethod = Statement.getMethod(target.getClass(),
|
||||
"set" + NameGenerator.capitalize(action), argTypes);
|
||||
}
|
||||
if (targetMethod == null) {
|
||||
String argTypeString = (argTypes.length == 0)
|
||||
? " with no arguments"
|
||||
: " with argument " + argTypes[0];
|
||||
throw new RuntimeException(
|
||||
"No method called " + action + " on " +
|
||||
target.getClass() + argTypeString);
|
||||
}
|
||||
return MethodUtil.invoke(targetMethod, target, newArgs);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
Throwable th = ex.getTargetException();
|
||||
throw (th instanceof RuntimeException)
|
||||
? (RuntimeException) th
|
||||
: new RuntimeException(th);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an implementation of <code>listenerInterface</code> in which
|
||||
* <em>all</em> of the methods in the listener interface apply
|
||||
* the handler's <code>action</code> to the <code>target</code>. This
|
||||
* method is implemented by calling the other, more general,
|
||||
* implementation of the <code>create</code> method with both
|
||||
* the <code>eventPropertyName</code> and the <code>listenerMethodName</code>
|
||||
* taking the value <code>null</code>. Refer to
|
||||
* {@link java.beans.EventHandler#create(Class, Object, String, String)
|
||||
* the general version of create} for a complete description of
|
||||
* the <code>action</code> parameter.
|
||||
* <p>
|
||||
* To create an <code>ActionListener</code> that shows a
|
||||
* <code>JDialog</code> with <code>dialog.show()</code>,
|
||||
* one can write:
|
||||
*
|
||||
*<blockquote>
|
||||
*<pre>
|
||||
*EventHandler.create(ActionListener.class, dialog, "show")
|
||||
*</pre>
|
||||
*</blockquote>
|
||||
*
|
||||
* @param <T> the type to create
|
||||
* @param listenerInterface the listener interface to create a proxy for
|
||||
* @param target the object that will perform the action
|
||||
* @param action the name of a (possibly qualified) property or method on
|
||||
* the target
|
||||
* @return an object that implements <code>listenerInterface</code>
|
||||
*
|
||||
* @throws NullPointerException if <code>listenerInterface</code> is null
|
||||
* @throws NullPointerException if <code>target</code> is null
|
||||
* @throws NullPointerException if <code>action</code> is null
|
||||
*
|
||||
* @see #create(Class, Object, String, String)
|
||||
*/
|
||||
public static <T> T create(Class<T> listenerInterface,
|
||||
Object target, String action)
|
||||
{
|
||||
return create(listenerInterface, target, action, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Creates an implementation of <code>listenerInterface</code> in which
|
||||
* <em>all</em> of the methods pass the value of the event
|
||||
* expression, <code>eventPropertyName</code>, to the final method in the
|
||||
* statement, <code>action</code>, which is applied to the <code>target</code>.
|
||||
* This method is implemented by calling the
|
||||
* more general, implementation of the <code>create</code> method with
|
||||
* the <code>listenerMethodName</code> taking the value <code>null</code>.
|
||||
* Refer to
|
||||
* {@link java.beans.EventHandler#create(Class, Object, String, String)
|
||||
* the general version of create} for a complete description of
|
||||
* the <code>action</code> and <code>eventPropertyName</code> parameters.
|
||||
* <p>
|
||||
* To create an <code>ActionListener</code> that sets the
|
||||
* the text of a <code>JLabel</code> to the text value of
|
||||
* the <code>JTextField</code> source of the incoming event,
|
||||
* you can use the following code:
|
||||
*
|
||||
*<blockquote>
|
||||
*<pre>
|
||||
*EventHandler.create(ActionListener.class, label, "text", "source.text");
|
||||
*</pre>
|
||||
*</blockquote>
|
||||
*
|
||||
* This is equivalent to the following code:
|
||||
*<blockquote>
|
||||
*<pre>
|
||||
//Equivalent code using an inner class instead of EventHandler.
|
||||
*new ActionListener() {
|
||||
* public void actionPerformed(ActionEvent event) {
|
||||
* label.setText(((JTextField)(event.getSource())).getText());
|
||||
* }
|
||||
*};
|
||||
*</pre>
|
||||
*</blockquote>
|
||||
*
|
||||
* @param <T> the type to create
|
||||
* @param listenerInterface the listener interface to create a proxy for
|
||||
* @param target the object that will perform the action
|
||||
* @param action the name of a (possibly qualified) property or method on
|
||||
* the target
|
||||
* @param eventPropertyName the (possibly qualified) name of a readable property of the incoming event
|
||||
*
|
||||
* @return an object that implements <code>listenerInterface</code>
|
||||
*
|
||||
* @throws NullPointerException if <code>listenerInterface</code> is null
|
||||
* @throws NullPointerException if <code>target</code> is null
|
||||
* @throws NullPointerException if <code>action</code> is null
|
||||
*
|
||||
* @see #create(Class, Object, String, String, String)
|
||||
*/
|
||||
public static <T> T create(Class<T> listenerInterface,
|
||||
Object target, String action,
|
||||
String eventPropertyName)
|
||||
{
|
||||
return create(listenerInterface, target, action, eventPropertyName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an implementation of <code>listenerInterface</code> in which
|
||||
* the method named <code>listenerMethodName</code>
|
||||
* passes the value of the event expression, <code>eventPropertyName</code>,
|
||||
* to the final method in the statement, <code>action</code>, which
|
||||
* is applied to the <code>target</code>. All of the other listener
|
||||
* methods do nothing.
|
||||
* <p>
|
||||
* The <code>eventPropertyName</code> string is used to extract a value
|
||||
* from the incoming event object that is passed to the target
|
||||
* method. The common case is the target method takes no arguments, in
|
||||
* which case a value of null should be used for the
|
||||
* <code>eventPropertyName</code>. Alternatively if you want
|
||||
* the incoming event object passed directly to the target method use
|
||||
* the empty string.
|
||||
* The format of the <code>eventPropertyName</code> string is a sequence of
|
||||
* methods or properties where each method or
|
||||
* property is applied to the value returned by the preceding method
|
||||
* starting from the incoming event object.
|
||||
* The syntax is: <code>propertyName{.propertyName}*</code>
|
||||
* where <code>propertyName</code> matches a method or
|
||||
* property. For example, to extract the <code>point</code>
|
||||
* property from a <code>MouseEvent</code>, you could use either
|
||||
* <code>"point"</code> or <code>"getPoint"</code> as the
|
||||
* <code>eventPropertyName</code>. To extract the "text" property from
|
||||
* a <code>MouseEvent</code> with a <code>JLabel</code> source use any
|
||||
* of the following as <code>eventPropertyName</code>:
|
||||
* <code>"source.text"</code>,
|
||||
* <code>"getSource.text"</code> <code>"getSource.getText"</code> or
|
||||
* <code>"source.getText"</code>. If a method can not be found, or an
|
||||
* exception is generated as part of invoking a method a
|
||||
* <code>RuntimeException</code> will be thrown at dispatch time. For
|
||||
* example, if the incoming event object is null, and
|
||||
* <code>eventPropertyName</code> is non-null and not empty, a
|
||||
* <code>RuntimeException</code> will be thrown.
|
||||
* <p>
|
||||
* The <code>action</code> argument is of the same format as the
|
||||
* <code>eventPropertyName</code> argument where the last property name
|
||||
* identifies either a method name or writable property.
|
||||
* <p>
|
||||
* If the <code>listenerMethodName</code> is <code>null</code>
|
||||
* <em>all</em> methods in the interface trigger the <code>action</code> to be
|
||||
* executed on the <code>target</code>.
|
||||
* <p>
|
||||
* For example, to create a <code>MouseListener</code> that sets the target
|
||||
* object's <code>origin</code> property to the incoming <code>MouseEvent</code>'s
|
||||
* location (that's the value of <code>mouseEvent.getPoint()</code>) each
|
||||
* time a mouse button is pressed, one would write:
|
||||
*<blockquote>
|
||||
*<pre>
|
||||
*EventHandler.create(MouseListener.class, target, "origin", "point", "mousePressed");
|
||||
*</pre>
|
||||
*</blockquote>
|
||||
*
|
||||
* This is comparable to writing a <code>MouseListener</code> in which all
|
||||
* of the methods except <code>mousePressed</code> are no-ops:
|
||||
*
|
||||
*<blockquote>
|
||||
*<pre>
|
||||
//Equivalent code using an inner class instead of EventHandler.
|
||||
*new MouseAdapter() {
|
||||
* public void mousePressed(MouseEvent e) {
|
||||
* target.setOrigin(e.getPoint());
|
||||
* }
|
||||
*};
|
||||
* </pre>
|
||||
*</blockquote>
|
||||
*
|
||||
* @param <T> the type to create
|
||||
* @param listenerInterface the listener interface to create a proxy for
|
||||
* @param target the object that will perform the action
|
||||
* @param action the name of a (possibly qualified) property or method on
|
||||
* the target
|
||||
* @param eventPropertyName the (possibly qualified) name of a readable property of the incoming event
|
||||
* @param listenerMethodName the name of the method in the listener interface that should trigger the action
|
||||
*
|
||||
* @return an object that implements <code>listenerInterface</code>
|
||||
*
|
||||
* @throws NullPointerException if <code>listenerInterface</code> is null
|
||||
* @throws NullPointerException if <code>target</code> is null
|
||||
* @throws NullPointerException if <code>action</code> is null
|
||||
*
|
||||
* @see EventHandler
|
||||
*/
|
||||
public static <T> T create(Class<T> listenerInterface,
|
||||
Object target, String action,
|
||||
String eventPropertyName,
|
||||
String listenerMethodName)
|
||||
{
|
||||
// Create this first to verify target/action are non-null
|
||||
final EventHandler handler = new EventHandler(target, action,
|
||||
eventPropertyName,
|
||||
listenerMethodName);
|
||||
if (listenerInterface == null) {
|
||||
throw new NullPointerException(
|
||||
"listenerInterface must be non-null");
|
||||
}
|
||||
final ClassLoader loader = getClassLoader(listenerInterface);
|
||||
final Class<?>[] interfaces = {listenerInterface};
|
||||
return AccessController.doPrivileged(new PrivilegedAction<T>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public T run() {
|
||||
return (T) Proxy.newProxyInstance(loader, interfaces, handler);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static ClassLoader getClassLoader(Class<?> type) {
|
||||
ReflectUtil.checkPackageAccess(type);
|
||||
ClassLoader loader = type.getClassLoader();
|
||||
if (loader == null) {
|
||||
loader = Thread.currentThread().getContextClassLoader(); // avoid use of BCP
|
||||
if (loader == null) {
|
||||
loader = ClassLoader.getSystemClassLoader();
|
||||
}
|
||||
}
|
||||
return loader;
|
||||
}
|
||||
}
|
||||
540
jdkSrc/jdk8/java/beans/EventSetDescriptor.java
Normal file
540
jdkSrc/jdk8/java/beans/EventSetDescriptor.java
Normal file
@@ -0,0 +1,540 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2012, 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.ref.Reference;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
/**
|
||||
* An EventSetDescriptor describes a group of events that a given Java
|
||||
* bean fires.
|
||||
* <P>
|
||||
* The given group of events are all delivered as method calls on a single
|
||||
* event listener interface, and an event listener object can be registered
|
||||
* via a call on a registration method supplied by the event source.
|
||||
*/
|
||||
public class EventSetDescriptor extends FeatureDescriptor {
|
||||
|
||||
private MethodDescriptor[] listenerMethodDescriptors;
|
||||
private MethodDescriptor addMethodDescriptor;
|
||||
private MethodDescriptor removeMethodDescriptor;
|
||||
private MethodDescriptor getMethodDescriptor;
|
||||
|
||||
private Reference<Method[]> listenerMethodsRef;
|
||||
private Reference<? extends Class<?>> listenerTypeRef;
|
||||
|
||||
private boolean unicast;
|
||||
private boolean inDefaultEventSet = true;
|
||||
|
||||
/**
|
||||
* Creates an <TT>EventSetDescriptor</TT> assuming that you are
|
||||
* following the most simple standard design pattern where a named
|
||||
* event "fred" is (1) delivered as a call on the single method of
|
||||
* interface FredListener, (2) has a single argument of type FredEvent,
|
||||
* and (3) where the FredListener may be registered with a call on an
|
||||
* addFredListener method of the source component and removed with a
|
||||
* call on a removeFredListener method.
|
||||
*
|
||||
* @param sourceClass The class firing the event.
|
||||
* @param eventSetName The programmatic name of the event. E.g. "fred".
|
||||
* Note that this should normally start with a lower-case character.
|
||||
* @param listenerType The target interface that events
|
||||
* will get delivered to.
|
||||
* @param listenerMethodName The method that will get called when the event gets
|
||||
* delivered to its target listener interface.
|
||||
* @exception IntrospectionException if an exception occurs during
|
||||
* introspection.
|
||||
*/
|
||||
public EventSetDescriptor(Class<?> sourceClass, String eventSetName,
|
||||
Class<?> listenerType, String listenerMethodName)
|
||||
throws IntrospectionException {
|
||||
this(sourceClass, eventSetName, listenerType,
|
||||
new String[] { listenerMethodName },
|
||||
Introspector.ADD_PREFIX + getListenerClassName(listenerType),
|
||||
Introspector.REMOVE_PREFIX + getListenerClassName(listenerType),
|
||||
Introspector.GET_PREFIX + getListenerClassName(listenerType) + "s");
|
||||
|
||||
String eventName = NameGenerator.capitalize(eventSetName) + "Event";
|
||||
Method[] listenerMethods = getListenerMethods();
|
||||
if (listenerMethods.length > 0) {
|
||||
Class[] args = getParameterTypes(getClass0(), listenerMethods[0]);
|
||||
// Check for EventSet compliance. Special case for vetoableChange. See 4529996
|
||||
if (!"vetoableChange".equals(eventSetName) && !args[0].getName().endsWith(eventName)) {
|
||||
throw new IntrospectionException("Method \"" + listenerMethodName +
|
||||
"\" should have argument \"" +
|
||||
eventName + "\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getListenerClassName(Class<?> cls) {
|
||||
String className = cls.getName();
|
||||
return className.substring(className.lastIndexOf('.') + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an <TT>EventSetDescriptor</TT> from scratch using
|
||||
* string names.
|
||||
*
|
||||
* @param sourceClass The class firing the event.
|
||||
* @param eventSetName The programmatic name of the event set.
|
||||
* Note that this should normally start with a lower-case character.
|
||||
* @param listenerType The Class of the target interface that events
|
||||
* will get delivered to.
|
||||
* @param listenerMethodNames The names of the methods that will get called
|
||||
* when the event gets delivered to its target listener interface.
|
||||
* @param addListenerMethodName The name of the method on the event source
|
||||
* that can be used to register an event listener object.
|
||||
* @param removeListenerMethodName The name of the method on the event source
|
||||
* that can be used to de-register an event listener object.
|
||||
* @exception IntrospectionException if an exception occurs during
|
||||
* introspection.
|
||||
*/
|
||||
public EventSetDescriptor(Class<?> sourceClass,
|
||||
String eventSetName,
|
||||
Class<?> listenerType,
|
||||
String listenerMethodNames[],
|
||||
String addListenerMethodName,
|
||||
String removeListenerMethodName)
|
||||
throws IntrospectionException {
|
||||
this(sourceClass, eventSetName, listenerType,
|
||||
listenerMethodNames, addListenerMethodName,
|
||||
removeListenerMethodName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor creates an EventSetDescriptor from scratch using
|
||||
* string names.
|
||||
*
|
||||
* @param sourceClass The class firing the event.
|
||||
* @param eventSetName The programmatic name of the event set.
|
||||
* Note that this should normally start with a lower-case character.
|
||||
* @param listenerType The Class of the target interface that events
|
||||
* will get delivered to.
|
||||
* @param listenerMethodNames The names of the methods that will get called
|
||||
* when the event gets delivered to its target listener interface.
|
||||
* @param addListenerMethodName The name of the method on the event source
|
||||
* that can be used to register an event listener object.
|
||||
* @param removeListenerMethodName The name of the method on the event source
|
||||
* that can be used to de-register an event listener object.
|
||||
* @param getListenerMethodName The method on the event source that
|
||||
* can be used to access the array of event listener objects.
|
||||
* @exception IntrospectionException if an exception occurs during
|
||||
* introspection.
|
||||
* @since 1.4
|
||||
*/
|
||||
public EventSetDescriptor(Class<?> sourceClass,
|
||||
String eventSetName,
|
||||
Class<?> listenerType,
|
||||
String listenerMethodNames[],
|
||||
String addListenerMethodName,
|
||||
String removeListenerMethodName,
|
||||
String getListenerMethodName)
|
||||
throws IntrospectionException {
|
||||
if (sourceClass == null || eventSetName == null || listenerType == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
setName(eventSetName);
|
||||
setClass0(sourceClass);
|
||||
setListenerType(listenerType);
|
||||
|
||||
Method[] listenerMethods = new Method[listenerMethodNames.length];
|
||||
for (int i = 0; i < listenerMethodNames.length; i++) {
|
||||
// Check for null names
|
||||
if (listenerMethodNames[i] == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
listenerMethods[i] = getMethod(listenerType, listenerMethodNames[i], 1);
|
||||
}
|
||||
setListenerMethods(listenerMethods);
|
||||
|
||||
setAddListenerMethod(getMethod(sourceClass, addListenerMethodName, 1));
|
||||
setRemoveListenerMethod(getMethod(sourceClass, removeListenerMethodName, 1));
|
||||
|
||||
// Be more forgiving of not finding the getListener method.
|
||||
Method method = Introspector.findMethod(sourceClass, getListenerMethodName, 0);
|
||||
if (method != null) {
|
||||
setGetListenerMethod(method);
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getMethod(Class<?> cls, String name, int args)
|
||||
throws IntrospectionException {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
Method method = Introspector.findMethod(cls, name, args);
|
||||
if ((method == null) || Modifier.isStatic(method.getModifiers())) {
|
||||
throw new IntrospectionException("Method not found: " + name +
|
||||
" on class " + cls.getName());
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an <TT>EventSetDescriptor</TT> from scratch using
|
||||
* <TT>java.lang.reflect.Method</TT> and <TT>java.lang.Class</TT> objects.
|
||||
*
|
||||
* @param eventSetName The programmatic name of the event set.
|
||||
* @param listenerType The Class for the listener interface.
|
||||
* @param listenerMethods An array of Method objects describing each
|
||||
* of the event handling methods in the target listener.
|
||||
* @param addListenerMethod The method on the event source
|
||||
* that can be used to register an event listener object.
|
||||
* @param removeListenerMethod The method on the event source
|
||||
* that can be used to de-register an event listener object.
|
||||
* @exception IntrospectionException if an exception occurs during
|
||||
* introspection.
|
||||
*/
|
||||
public EventSetDescriptor(String eventSetName,
|
||||
Class<?> listenerType,
|
||||
Method listenerMethods[],
|
||||
Method addListenerMethod,
|
||||
Method removeListenerMethod)
|
||||
throws IntrospectionException {
|
||||
this(eventSetName, listenerType, listenerMethods,
|
||||
addListenerMethod, removeListenerMethod, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor creates an EventSetDescriptor from scratch using
|
||||
* java.lang.reflect.Method and java.lang.Class objects.
|
||||
*
|
||||
* @param eventSetName The programmatic name of the event set.
|
||||
* @param listenerType The Class for the listener interface.
|
||||
* @param listenerMethods An array of Method objects describing each
|
||||
* of the event handling methods in the target listener.
|
||||
* @param addListenerMethod The method on the event source
|
||||
* that can be used to register an event listener object.
|
||||
* @param removeListenerMethod The method on the event source
|
||||
* that can be used to de-register an event listener object.
|
||||
* @param getListenerMethod The method on the event source
|
||||
* that can be used to access the array of event listener objects.
|
||||
* @exception IntrospectionException if an exception occurs during
|
||||
* introspection.
|
||||
* @since 1.4
|
||||
*/
|
||||
public EventSetDescriptor(String eventSetName,
|
||||
Class<?> listenerType,
|
||||
Method listenerMethods[],
|
||||
Method addListenerMethod,
|
||||
Method removeListenerMethod,
|
||||
Method getListenerMethod)
|
||||
throws IntrospectionException {
|
||||
setName(eventSetName);
|
||||
setListenerMethods(listenerMethods);
|
||||
setAddListenerMethod(addListenerMethod);
|
||||
setRemoveListenerMethod( removeListenerMethod);
|
||||
setGetListenerMethod(getListenerMethod);
|
||||
setListenerType(listenerType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an <TT>EventSetDescriptor</TT> from scratch using
|
||||
* <TT>java.lang.reflect.MethodDescriptor</TT> and <TT>java.lang.Class</TT>
|
||||
* objects.
|
||||
*
|
||||
* @param eventSetName The programmatic name of the event set.
|
||||
* @param listenerType The Class for the listener interface.
|
||||
* @param listenerMethodDescriptors An array of MethodDescriptor objects
|
||||
* describing each of the event handling methods in the
|
||||
* target listener.
|
||||
* @param addListenerMethod The method on the event source
|
||||
* that can be used to register an event listener object.
|
||||
* @param removeListenerMethod The method on the event source
|
||||
* that can be used to de-register an event listener object.
|
||||
* @exception IntrospectionException if an exception occurs during
|
||||
* introspection.
|
||||
*/
|
||||
public EventSetDescriptor(String eventSetName,
|
||||
Class<?> listenerType,
|
||||
MethodDescriptor listenerMethodDescriptors[],
|
||||
Method addListenerMethod,
|
||||
Method removeListenerMethod)
|
||||
throws IntrospectionException {
|
||||
setName(eventSetName);
|
||||
this.listenerMethodDescriptors = (listenerMethodDescriptors != null)
|
||||
? listenerMethodDescriptors.clone()
|
||||
: null;
|
||||
setAddListenerMethod(addListenerMethod);
|
||||
setRemoveListenerMethod(removeListenerMethod);
|
||||
setListenerType(listenerType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the <TT>Class</TT> object for the target interface.
|
||||
*
|
||||
* @return The Class object for the target interface that will
|
||||
* get invoked when the event is fired.
|
||||
*/
|
||||
public Class<?> getListenerType() {
|
||||
return (this.listenerTypeRef != null)
|
||||
? this.listenerTypeRef.get()
|
||||
: null;
|
||||
}
|
||||
|
||||
private void setListenerType(Class<?> cls) {
|
||||
this.listenerTypeRef = getWeakReference(cls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the methods of the target listener interface.
|
||||
*
|
||||
* @return An array of <TT>Method</TT> objects for the target methods
|
||||
* within the target listener interface that will get called when
|
||||
* events are fired.
|
||||
*/
|
||||
public synchronized Method[] getListenerMethods() {
|
||||
Method[] methods = getListenerMethods0();
|
||||
if (methods == null) {
|
||||
if (listenerMethodDescriptors != null) {
|
||||
methods = new Method[listenerMethodDescriptors.length];
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
methods[i] = listenerMethodDescriptors[i].getMethod();
|
||||
}
|
||||
}
|
||||
setListenerMethods(methods);
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
private void setListenerMethods(Method[] methods) {
|
||||
if (methods == null) {
|
||||
return;
|
||||
}
|
||||
if (listenerMethodDescriptors == null) {
|
||||
listenerMethodDescriptors = new MethodDescriptor[methods.length];
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
listenerMethodDescriptors[i] = new MethodDescriptor(methods[i]);
|
||||
}
|
||||
}
|
||||
this.listenerMethodsRef = getSoftReference(methods);
|
||||
}
|
||||
|
||||
private Method[] getListenerMethods0() {
|
||||
return (this.listenerMethodsRef != null)
|
||||
? this.listenerMethodsRef.get()
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the <code>MethodDescriptor</code>s of the target listener interface.
|
||||
*
|
||||
* @return An array of <code>MethodDescriptor</code> objects for the target methods
|
||||
* within the target listener interface that will get called when
|
||||
* events are fired.
|
||||
*/
|
||||
public synchronized MethodDescriptor[] getListenerMethodDescriptors() {
|
||||
return (this.listenerMethodDescriptors != null)
|
||||
? this.listenerMethodDescriptors.clone()
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the method used to add event listeners.
|
||||
*
|
||||
* @return The method used to register a listener at the event source.
|
||||
*/
|
||||
public synchronized Method getAddListenerMethod() {
|
||||
return getMethod(this.addMethodDescriptor);
|
||||
}
|
||||
|
||||
private synchronized void setAddListenerMethod(Method method) {
|
||||
if (method == null) {
|
||||
return;
|
||||
}
|
||||
if (getClass0() == null) {
|
||||
setClass0(method.getDeclaringClass());
|
||||
}
|
||||
addMethodDescriptor = new MethodDescriptor(method);
|
||||
setTransient(method.getAnnotation(Transient.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the method used to remove event listeners.
|
||||
*
|
||||
* @return The method used to remove a listener at the event source.
|
||||
*/
|
||||
public synchronized Method getRemoveListenerMethod() {
|
||||
return getMethod(this.removeMethodDescriptor);
|
||||
}
|
||||
|
||||
private synchronized void setRemoveListenerMethod(Method method) {
|
||||
if (method == null) {
|
||||
return;
|
||||
}
|
||||
if (getClass0() == null) {
|
||||
setClass0(method.getDeclaringClass());
|
||||
}
|
||||
removeMethodDescriptor = new MethodDescriptor(method);
|
||||
setTransient(method.getAnnotation(Transient.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the method used to access the registered event listeners.
|
||||
*
|
||||
* @return The method used to access the array of listeners at the event
|
||||
* source or null if it doesn't exist.
|
||||
* @since 1.4
|
||||
*/
|
||||
public synchronized Method getGetListenerMethod() {
|
||||
return getMethod(this.getMethodDescriptor);
|
||||
}
|
||||
|
||||
private synchronized void setGetListenerMethod(Method method) {
|
||||
if (method == null) {
|
||||
return;
|
||||
}
|
||||
if (getClass0() == null) {
|
||||
setClass0(method.getDeclaringClass());
|
||||
}
|
||||
getMethodDescriptor = new MethodDescriptor(method);
|
||||
setTransient(method.getAnnotation(Transient.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark an event set as unicast (or not).
|
||||
*
|
||||
* @param unicast True if the event set is unicast.
|
||||
*/
|
||||
public void setUnicast(boolean unicast) {
|
||||
this.unicast = unicast;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normally event sources are multicast. However there are some
|
||||
* exceptions that are strictly unicast.
|
||||
*
|
||||
* @return <TT>true</TT> if the event set is unicast.
|
||||
* Defaults to <TT>false</TT>.
|
||||
*/
|
||||
public boolean isUnicast() {
|
||||
return unicast;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks an event set as being in the "default" set (or not).
|
||||
* By default this is <TT>true</TT>.
|
||||
*
|
||||
* @param inDefaultEventSet <code>true</code> if the event set is in
|
||||
* the "default" set,
|
||||
* <code>false</code> if not
|
||||
*/
|
||||
public void setInDefaultEventSet(boolean inDefaultEventSet) {
|
||||
this.inDefaultEventSet = inDefaultEventSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports if an event set is in the "default" set.
|
||||
*
|
||||
* @return <TT>true</TT> if the event set is in
|
||||
* the "default" set. Defaults to <TT>true</TT>.
|
||||
*/
|
||||
public boolean isInDefaultEventSet() {
|
||||
return inDefaultEventSet;
|
||||
}
|
||||
|
||||
/*
|
||||
* Package-private constructor
|
||||
* Merge two event set descriptors. Where they conflict, give the
|
||||
* second argument (y) priority over the first argument (x).
|
||||
*
|
||||
* @param x The first (lower priority) EventSetDescriptor
|
||||
* @param y The second (higher priority) EventSetDescriptor
|
||||
*/
|
||||
EventSetDescriptor(EventSetDescriptor x, EventSetDescriptor y) {
|
||||
super(x,y);
|
||||
listenerMethodDescriptors = x.listenerMethodDescriptors;
|
||||
if (y.listenerMethodDescriptors != null) {
|
||||
listenerMethodDescriptors = y.listenerMethodDescriptors;
|
||||
}
|
||||
|
||||
listenerTypeRef = x.listenerTypeRef;
|
||||
if (y.listenerTypeRef != null) {
|
||||
listenerTypeRef = y.listenerTypeRef;
|
||||
}
|
||||
|
||||
addMethodDescriptor = x.addMethodDescriptor;
|
||||
if (y.addMethodDescriptor != null) {
|
||||
addMethodDescriptor = y.addMethodDescriptor;
|
||||
}
|
||||
|
||||
removeMethodDescriptor = x.removeMethodDescriptor;
|
||||
if (y.removeMethodDescriptor != null) {
|
||||
removeMethodDescriptor = y.removeMethodDescriptor;
|
||||
}
|
||||
|
||||
getMethodDescriptor = x.getMethodDescriptor;
|
||||
if (y.getMethodDescriptor != null) {
|
||||
getMethodDescriptor = y.getMethodDescriptor;
|
||||
}
|
||||
|
||||
unicast = y.unicast;
|
||||
if (!x.inDefaultEventSet || !y.inDefaultEventSet) {
|
||||
inDefaultEventSet = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Package-private dup constructor
|
||||
* This must isolate the new object from any changes to the old object.
|
||||
*/
|
||||
EventSetDescriptor(EventSetDescriptor old) {
|
||||
super(old);
|
||||
if (old.listenerMethodDescriptors != null) {
|
||||
int len = old.listenerMethodDescriptors.length;
|
||||
listenerMethodDescriptors = new MethodDescriptor[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
listenerMethodDescriptors[i] = new MethodDescriptor(
|
||||
old.listenerMethodDescriptors[i]);
|
||||
}
|
||||
}
|
||||
listenerTypeRef = old.listenerTypeRef;
|
||||
|
||||
addMethodDescriptor = old.addMethodDescriptor;
|
||||
removeMethodDescriptor = old.removeMethodDescriptor;
|
||||
getMethodDescriptor = old.getMethodDescriptor;
|
||||
|
||||
unicast = old.unicast;
|
||||
inDefaultEventSet = old.inDefaultEventSet;
|
||||
}
|
||||
|
||||
void appendTo(StringBuilder sb) {
|
||||
appendTo(sb, "unicast", this.unicast);
|
||||
appendTo(sb, "inDefaultEventSet", this.inDefaultEventSet);
|
||||
appendTo(sb, "listenerType", this.listenerTypeRef);
|
||||
appendTo(sb, "getListenerMethod", getMethod(this.getMethodDescriptor));
|
||||
appendTo(sb, "addListenerMethod", getMethod(this.addMethodDescriptor));
|
||||
appendTo(sb, "removeListenerMethod", getMethod(this.removeMethodDescriptor));
|
||||
}
|
||||
|
||||
private static Method getMethod(MethodDescriptor descriptor) {
|
||||
return (descriptor != null)
|
||||
? descriptor.getMethod()
|
||||
: null;
|
||||
}
|
||||
}
|
||||
43
jdkSrc/jdk8/java/beans/ExceptionListener.java
Normal file
43
jdkSrc/jdk8/java/beans/ExceptionListener.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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;
|
||||
|
||||
/**
|
||||
* An ExceptionListener is notified of internal exceptions.
|
||||
*
|
||||
* @since 1.4
|
||||
*
|
||||
* @author Philip Milne
|
||||
*/
|
||||
public interface ExceptionListener {
|
||||
/**
|
||||
* This method is called when a recoverable exception has
|
||||
* been caught.
|
||||
*
|
||||
* @param e The exception that was caught.
|
||||
*
|
||||
*/
|
||||
public void exceptionThrown(Exception e);
|
||||
}
|
||||
184
jdkSrc/jdk8/java/beans/Expression.java
Normal file
184
jdkSrc/jdk8/java/beans/Expression.java
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, 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;
|
||||
|
||||
/**
|
||||
* An <code>Expression</code> object represents a primitive expression
|
||||
* in which a single method is applied to a target and a set of
|
||||
* arguments to return a result - as in <code>"a.getFoo()"</code>.
|
||||
* <p>
|
||||
* In addition to the properties of the super class, the
|
||||
* <code>Expression</code> object provides a <em>value</em> which
|
||||
* is the object returned when this expression is evaluated.
|
||||
* The return value is typically not provided by the caller and
|
||||
* is instead computed by dynamically finding the method and invoking
|
||||
* it when the first call to <code>getValue</code> is made.
|
||||
*
|
||||
* @see #getValue
|
||||
* @see #setValue
|
||||
*
|
||||
* @since 1.4
|
||||
*
|
||||
* @author Philip Milne
|
||||
*/
|
||||
public class Expression extends Statement {
|
||||
|
||||
private static Object unbound = new Object();
|
||||
|
||||
private Object value = unbound;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Expression} object
|
||||
* for the specified target object to invoke the method
|
||||
* specified by the name and by the array of arguments.
|
||||
* <p>
|
||||
* The {@code target} and the {@code methodName} values should not be {@code null}.
|
||||
* Otherwise an attempt to execute this {@code Expression}
|
||||
* will result in a {@code NullPointerException}.
|
||||
* If the {@code arguments} value is {@code null},
|
||||
* an empty array is used as the value of the {@code arguments} property.
|
||||
*
|
||||
* @param target the target object of this expression
|
||||
* @param methodName the name of the method to invoke on the specified target
|
||||
* @param arguments the array of arguments to invoke the specified method
|
||||
*
|
||||
* @see #getValue
|
||||
*/
|
||||
@ConstructorProperties({"target", "methodName", "arguments"})
|
||||
public Expression(Object target, String methodName, Object[] arguments) {
|
||||
super(target, methodName, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Expression} object with the specified value
|
||||
* for the specified target object to invoke the method
|
||||
* specified by the name and by the array of arguments.
|
||||
* The {@code value} value is used as the value of the {@code value} property,
|
||||
* so the {@link #getValue} method will return it
|
||||
* without executing this {@code Expression}.
|
||||
* <p>
|
||||
* The {@code target} and the {@code methodName} values should not be {@code null}.
|
||||
* Otherwise an attempt to execute this {@code Expression}
|
||||
* will result in a {@code NullPointerException}.
|
||||
* If the {@code arguments} value is {@code null},
|
||||
* an empty array is used as the value of the {@code arguments} property.
|
||||
*
|
||||
* @param value the value of this expression
|
||||
* @param target the target object of this expression
|
||||
* @param methodName the name of the method to invoke on the specified target
|
||||
* @param arguments the array of arguments to invoke the specified method
|
||||
*
|
||||
* @see #setValue
|
||||
*/
|
||||
public Expression(Object value, Object target, String methodName, Object[] arguments) {
|
||||
this(target, methodName, arguments);
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* If the invoked method completes normally,
|
||||
* the value it returns is copied in the {@code value} property.
|
||||
* Note that the {@code value} property is set to {@code null},
|
||||
* if the return type of the underlying method is {@code void}.
|
||||
*
|
||||
* @throws NullPointerException if the value of the {@code target} or
|
||||
* {@code methodName} property is {@code null}
|
||||
* @throws NoSuchMethodException if a matching method is not found
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* it denies the method invocation
|
||||
* @throws Exception that is thrown by the invoked method
|
||||
*
|
||||
* @see java.lang.reflect.Method
|
||||
* @since 1.7
|
||||
*/
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
setValue(invoke());
|
||||
}
|
||||
|
||||
/**
|
||||
* If the value property of this instance is not already set,
|
||||
* this method dynamically finds the method with the specified
|
||||
* methodName on this target with these arguments and calls it.
|
||||
* The result of the method invocation is first copied
|
||||
* into the value property of this expression and then returned
|
||||
* as the result of <code>getValue</code>. If the value property
|
||||
* was already set, either by a call to <code>setValue</code>
|
||||
* or a previous call to <code>getValue</code> then the value
|
||||
* property is returned without either looking up or calling the method.
|
||||
* <p>
|
||||
* The value property of an <code>Expression</code> is set to
|
||||
* a unique private (non-<code>null</code>) value by default and
|
||||
* this value is used as an internal indication that the method
|
||||
* has not yet been called. A return value of <code>null</code>
|
||||
* replaces this default value in the same way that any other value
|
||||
* would, ensuring that expressions are never evaluated more than once.
|
||||
* <p>
|
||||
* See the <code>execute</code> method for details on how
|
||||
* methods are chosen using the dynamic types of the target
|
||||
* and arguments.
|
||||
*
|
||||
* @see Statement#execute
|
||||
* @see #setValue
|
||||
*
|
||||
* @return The result of applying this method to these arguments.
|
||||
* @throws Exception if the method with the specified methodName
|
||||
* throws an exception
|
||||
*/
|
||||
public Object getValue() throws Exception {
|
||||
if (value == unbound) {
|
||||
setValue(invoke());
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of this expression to <code>value</code>.
|
||||
* This value will be returned by the getValue method
|
||||
* without calling the method associated with this
|
||||
* expression.
|
||||
*
|
||||
* @param value The value of this expression.
|
||||
*
|
||||
* @see #getValue
|
||||
*/
|
||||
public void setValue(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/*pp*/ String instanceName(Object instance) {
|
||||
return instance == unbound ? "<unbound>" : super.instanceName(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the value of this expression using a Java-style syntax.
|
||||
*/
|
||||
public String toString() {
|
||||
return instanceName(value) + "=" + super.toString();
|
||||
}
|
||||
}
|
||||
445
jdkSrc/jdk8/java/beans/FeatureDescriptor.java
Normal file
445
jdkSrc/jdk8/java/beans/FeatureDescriptor.java
Normal file
@@ -0,0 +1,445 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2011, 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 com.sun.beans.TypeResolver;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.ref.SoftReference;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* The FeatureDescriptor class is the common baseclass for PropertyDescriptor,
|
||||
* EventSetDescriptor, and MethodDescriptor, etc.
|
||||
* <p>
|
||||
* It supports some common information that can be set and retrieved for
|
||||
* any of the introspection descriptors.
|
||||
* <p>
|
||||
* In addition it provides an extension mechanism so that arbitrary
|
||||
* attribute/value pairs can be associated with a design feature.
|
||||
*/
|
||||
|
||||
public class FeatureDescriptor {
|
||||
private static final String TRANSIENT = "transient";
|
||||
|
||||
private Reference<? extends Class<?>> classRef;
|
||||
|
||||
/**
|
||||
* Constructs a <code>FeatureDescriptor</code>.
|
||||
*/
|
||||
public FeatureDescriptor() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the programmatic name of this feature.
|
||||
*
|
||||
* @return The programmatic name of the property/method/event
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the programmatic name of this feature.
|
||||
*
|
||||
* @param name The programmatic name of the property/method/event
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the localized display name of this feature.
|
||||
*
|
||||
* @return The localized display name for the property/method/event.
|
||||
* This defaults to the same as its programmatic name from getName.
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
if (displayName == null) {
|
||||
return getName();
|
||||
}
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the localized display name of this feature.
|
||||
*
|
||||
* @param displayName The localized display name for the
|
||||
* property/method/event.
|
||||
*/
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "expert" flag is used to distinguish between those features that are
|
||||
* intended for expert users from those that are intended for normal users.
|
||||
*
|
||||
* @return True if this feature is intended for use by experts only.
|
||||
*/
|
||||
public boolean isExpert() {
|
||||
return expert;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "expert" flag is used to distinguish between features that are
|
||||
* intended for expert users from those that are intended for normal users.
|
||||
*
|
||||
* @param expert True if this feature is intended for use by experts only.
|
||||
*/
|
||||
public void setExpert(boolean expert) {
|
||||
this.expert = expert;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "hidden" flag is used to identify features that are intended only
|
||||
* for tool use, and which should not be exposed to humans.
|
||||
*
|
||||
* @return True if this feature should be hidden from human users.
|
||||
*/
|
||||
public boolean isHidden() {
|
||||
return hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "hidden" flag is used to identify features that are intended only
|
||||
* for tool use, and which should not be exposed to humans.
|
||||
*
|
||||
* @param hidden True if this feature should be hidden from human users.
|
||||
*/
|
||||
public void setHidden(boolean hidden) {
|
||||
this.hidden = hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "preferred" flag is used to identify features that are particularly
|
||||
* important for presenting to humans.
|
||||
*
|
||||
* @return True if this feature should be preferentially shown to human users.
|
||||
*/
|
||||
public boolean isPreferred() {
|
||||
return preferred;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "preferred" flag is used to identify features that are particularly
|
||||
* important for presenting to humans.
|
||||
*
|
||||
* @param preferred True if this feature should be preferentially shown
|
||||
* to human users.
|
||||
*/
|
||||
public void setPreferred(boolean preferred) {
|
||||
this.preferred = preferred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the short description of this feature.
|
||||
*
|
||||
* @return A localized short description associated with this
|
||||
* property/method/event. This defaults to be the display name.
|
||||
*/
|
||||
public String getShortDescription() {
|
||||
if (shortDescription == null) {
|
||||
return getDisplayName();
|
||||
}
|
||||
return shortDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* You can associate a short descriptive string with a feature. Normally
|
||||
* these descriptive strings should be less than about 40 characters.
|
||||
* @param text A (localized) short description to be associated with
|
||||
* this property/method/event.
|
||||
*/
|
||||
public void setShortDescription(String text) {
|
||||
shortDescription = text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate a named attribute with this feature.
|
||||
*
|
||||
* @param attributeName The locale-independent name of the attribute
|
||||
* @param value The value.
|
||||
*/
|
||||
public void setValue(String attributeName, Object value) {
|
||||
getTable().put(attributeName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a named attribute with this feature.
|
||||
*
|
||||
* @param attributeName The locale-independent name of the attribute
|
||||
* @return The value of the attribute. May be null if
|
||||
* the attribute is unknown.
|
||||
*/
|
||||
public Object getValue(String attributeName) {
|
||||
return (this.table != null)
|
||||
? this.table.get(attributeName)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an enumeration of the locale-independent names of this
|
||||
* feature.
|
||||
*
|
||||
* @return An enumeration of the locale-independent names of any
|
||||
* attributes that have been registered with setValue.
|
||||
*/
|
||||
public Enumeration<String> attributeNames() {
|
||||
return getTable().keys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Package-private constructor,
|
||||
* Merge information from two FeatureDescriptors.
|
||||
* The merged hidden and expert flags are formed by or-ing the values.
|
||||
* In the event of other conflicts, the second argument (y) is
|
||||
* given priority over the first argument (x).
|
||||
*
|
||||
* @param x The first (lower priority) MethodDescriptor
|
||||
* @param y The second (higher priority) MethodDescriptor
|
||||
*/
|
||||
FeatureDescriptor(FeatureDescriptor x, FeatureDescriptor y) {
|
||||
expert = x.expert | y.expert;
|
||||
hidden = x.hidden | y.hidden;
|
||||
preferred = x.preferred | y.preferred;
|
||||
name = y.name;
|
||||
shortDescription = x.shortDescription;
|
||||
if (y.shortDescription != null) {
|
||||
shortDescription = y.shortDescription;
|
||||
}
|
||||
displayName = x.displayName;
|
||||
if (y.displayName != null) {
|
||||
displayName = y.displayName;
|
||||
}
|
||||
classRef = x.classRef;
|
||||
if (y.classRef != null) {
|
||||
classRef = y.classRef;
|
||||
}
|
||||
addTable(x.table);
|
||||
addTable(y.table);
|
||||
}
|
||||
|
||||
/*
|
||||
* Package-private dup constructor
|
||||
* This must isolate the new object from any changes to the old object.
|
||||
*/
|
||||
FeatureDescriptor(FeatureDescriptor old) {
|
||||
expert = old.expert;
|
||||
hidden = old.hidden;
|
||||
preferred = old.preferred;
|
||||
name = old.name;
|
||||
shortDescription = old.shortDescription;
|
||||
displayName = old.displayName;
|
||||
classRef = old.classRef;
|
||||
|
||||
addTable(old.table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all values from the specified attribute table.
|
||||
* If some attribute is exist its value should be overridden.
|
||||
*
|
||||
* @param table the attribute table with new values
|
||||
*/
|
||||
private void addTable(Hashtable<String, Object> table) {
|
||||
if ((table != null) && !table.isEmpty()) {
|
||||
getTable().putAll(table);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the initialized attribute table.
|
||||
*
|
||||
* @return the initialized attribute table
|
||||
*/
|
||||
private Hashtable<String, Object> getTable() {
|
||||
if (this.table == null) {
|
||||
this.table = new Hashtable<>();
|
||||
}
|
||||
return this.table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the "transient" attribute according to the annotation.
|
||||
* If the "transient" attribute is already set
|
||||
* it should not be changed.
|
||||
*
|
||||
* @param annotation the annotation of the element of the feature
|
||||
*/
|
||||
void setTransient(Transient annotation) {
|
||||
if ((annotation != null) && (null == getValue(TRANSIENT))) {
|
||||
setValue(TRANSIENT, annotation.value());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the feature is transient.
|
||||
*
|
||||
* @return {@code true} if the feature is transient,
|
||||
* {@code false} otherwise
|
||||
*/
|
||||
boolean isTransient() {
|
||||
Object value = getValue(TRANSIENT);
|
||||
return (value instanceof Boolean)
|
||||
? (Boolean) value
|
||||
: false;
|
||||
}
|
||||
|
||||
// Package private methods for recreating the weak/soft referent
|
||||
|
||||
void setClass0(Class<?> cls) {
|
||||
this.classRef = getWeakReference(cls);
|
||||
}
|
||||
|
||||
Class<?> getClass0() {
|
||||
return (this.classRef != null)
|
||||
? this.classRef.get()
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new soft reference that refers to the given object.
|
||||
*
|
||||
* @return a new soft reference or <code>null</code> if object is <code>null</code>
|
||||
*
|
||||
* @see SoftReference
|
||||
*/
|
||||
static <T> Reference<T> getSoftReference(T object) {
|
||||
return (object != null)
|
||||
? new SoftReference<>(object)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new weak reference that refers to the given object.
|
||||
*
|
||||
* @return a new weak reference or <code>null</code> if object is <code>null</code>
|
||||
*
|
||||
* @see WeakReference
|
||||
*/
|
||||
static <T> Reference<T> getWeakReference(T object) {
|
||||
return (object != null)
|
||||
? new WeakReference<>(object)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the return type of the method.
|
||||
*
|
||||
* @param base the class that contains the method in the hierarchy
|
||||
* @param method the object that represents the method
|
||||
* @return a class identifying the return type of the method
|
||||
*
|
||||
* @see Method#getGenericReturnType
|
||||
* @see Method#getReturnType
|
||||
*/
|
||||
static Class<?> getReturnType(Class<?> base, Method method) {
|
||||
if (base == null) {
|
||||
base = method.getDeclaringClass();
|
||||
}
|
||||
return TypeResolver.erase(TypeResolver.resolveInClass(base, method.getGenericReturnType()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the parameter types of the method.
|
||||
*
|
||||
* @param base the class that contains the method in the hierarchy
|
||||
* @param method the object that represents the method
|
||||
* @return an array of classes identifying the parameter types of the method
|
||||
*
|
||||
* @see Method#getGenericParameterTypes
|
||||
* @see Method#getParameterTypes
|
||||
*/
|
||||
static Class<?>[] getParameterTypes(Class<?> base, Method method) {
|
||||
if (base == null) {
|
||||
base = method.getDeclaringClass();
|
||||
}
|
||||
return TypeResolver.erase(TypeResolver.resolveInClass(base, method.getGenericParameterTypes()));
|
||||
}
|
||||
|
||||
private boolean expert;
|
||||
private boolean hidden;
|
||||
private boolean preferred;
|
||||
private String shortDescription;
|
||||
private String name;
|
||||
private String displayName;
|
||||
private Hashtable<String, Object> table;
|
||||
|
||||
/**
|
||||
* Returns a string representation of the object.
|
||||
*
|
||||
* @return a string representation of the object
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder(getClass().getName());
|
||||
sb.append("[name=").append(this.name);
|
||||
appendTo(sb, "displayName", this.displayName);
|
||||
appendTo(sb, "shortDescription", this.shortDescription);
|
||||
appendTo(sb, "preferred", this.preferred);
|
||||
appendTo(sb, "hidden", this.hidden);
|
||||
appendTo(sb, "expert", this.expert);
|
||||
if ((this.table != null) && !this.table.isEmpty()) {
|
||||
sb.append("; values={");
|
||||
for (Entry<String, Object> entry : this.table.entrySet()) {
|
||||
sb.append(entry.getKey()).append("=").append(entry.getValue()).append("; ");
|
||||
}
|
||||
sb.setLength(sb.length() - 2);
|
||||
sb.append("}");
|
||||
}
|
||||
appendTo(sb);
|
||||
return sb.append("]").toString();
|
||||
}
|
||||
|
||||
void appendTo(StringBuilder sb) {
|
||||
}
|
||||
|
||||
static void appendTo(StringBuilder sb, String name, Reference<?> reference) {
|
||||
if (reference != null) {
|
||||
appendTo(sb, name, reference.get());
|
||||
}
|
||||
}
|
||||
|
||||
static void appendTo(StringBuilder sb, String name, Object value) {
|
||||
if (value != null) {
|
||||
sb.append("; ").append(name).append("=").append(value);
|
||||
}
|
||||
}
|
||||
|
||||
static void appendTo(StringBuilder sb, String name, boolean value) {
|
||||
if (value) {
|
||||
sb.append("; ").append(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
78
jdkSrc/jdk8/java/beans/IndexedPropertyChangeEvent.java
Normal file
78
jdkSrc/jdk8/java/beans/IndexedPropertyChangeEvent.java
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2011, 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;
|
||||
|
||||
/**
|
||||
* An "IndexedPropertyChange" event gets delivered whenever a component that
|
||||
* conforms to the JavaBeans™ specification (a "bean") changes a bound
|
||||
* indexed property. This class is an extension of <code>PropertyChangeEvent</code>
|
||||
* but contains the index of the property that has changed.
|
||||
* <P>
|
||||
* Null values may be provided for the old and the new values if their
|
||||
* true values are not known.
|
||||
* <P>
|
||||
* An event source may send a null object as the name to indicate that an
|
||||
* arbitrary set of if its properties have changed. In this case the
|
||||
* old and new values should also be null.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Mark Davidson
|
||||
*/
|
||||
public class IndexedPropertyChangeEvent extends PropertyChangeEvent {
|
||||
private static final long serialVersionUID = -320227448495806870L;
|
||||
|
||||
private int index;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>IndexedPropertyChangeEvent</code> object.
|
||||
*
|
||||
* @param source The bean that fired the event.
|
||||
* @param propertyName The programmatic name of the property that
|
||||
* was changed.
|
||||
* @param oldValue The old value of the property.
|
||||
* @param newValue The new value of the property.
|
||||
* @param index index of the property element that was changed.
|
||||
*/
|
||||
public IndexedPropertyChangeEvent(Object source, String propertyName,
|
||||
Object oldValue, Object newValue,
|
||||
int index) {
|
||||
super (source, propertyName, oldValue, newValue);
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of the property that was changed.
|
||||
*
|
||||
* @return The index specifying the property element that was
|
||||
* changed.
|
||||
*/
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
void appendTo(StringBuilder sb) {
|
||||
sb.append("; index=").append(getIndex());
|
||||
}
|
||||
}
|
||||
523
jdkSrc/jdk8/java/beans/IndexedPropertyDescriptor.java
Normal file
523
jdkSrc/jdk8/java/beans/IndexedPropertyDescriptor.java
Normal file
@@ -0,0 +1,523 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2013, 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.ref.Reference;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* An IndexedPropertyDescriptor describes a property that acts like an
|
||||
* array and has an indexed read and/or indexed write method to access
|
||||
* specific elements of the array.
|
||||
* <p>
|
||||
* An indexed property may also provide simple non-indexed read and write
|
||||
* methods. If these are present, they read and write arrays of the type
|
||||
* returned by the indexed read method.
|
||||
*/
|
||||
|
||||
public class IndexedPropertyDescriptor extends PropertyDescriptor {
|
||||
|
||||
private Reference<? extends Class<?>> indexedPropertyTypeRef;
|
||||
private final MethodRef indexedReadMethodRef = new MethodRef();
|
||||
private final MethodRef indexedWriteMethodRef = new MethodRef();
|
||||
|
||||
private String indexedReadMethodName;
|
||||
private String indexedWriteMethodName;
|
||||
|
||||
/**
|
||||
* This constructor constructs an IndexedPropertyDescriptor for a property
|
||||
* that follows the standard Java conventions by having getFoo and setFoo
|
||||
* accessor methods, for both indexed access and array access.
|
||||
* <p>
|
||||
* Thus if the argument name is "fred", it will assume that there
|
||||
* is an indexed reader method "getFred", a non-indexed (array) reader
|
||||
* method also called "getFred", an indexed writer method "setFred",
|
||||
* and finally a non-indexed writer method "setFred".
|
||||
*
|
||||
* @param propertyName The programmatic name of the property.
|
||||
* @param beanClass The Class object for the target bean.
|
||||
* @exception IntrospectionException if an exception occurs during
|
||||
* introspection.
|
||||
*/
|
||||
public IndexedPropertyDescriptor(String propertyName, Class<?> beanClass)
|
||||
throws IntrospectionException {
|
||||
this(propertyName, beanClass,
|
||||
Introspector.GET_PREFIX + NameGenerator.capitalize(propertyName),
|
||||
Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName),
|
||||
Introspector.GET_PREFIX + NameGenerator.capitalize(propertyName),
|
||||
Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName));
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor takes the name of a simple property, and method
|
||||
* names for reading and writing the property, both indexed
|
||||
* and non-indexed.
|
||||
*
|
||||
* @param propertyName The programmatic name of the property.
|
||||
* @param beanClass The Class object for the target bean.
|
||||
* @param readMethodName The name of the method used for reading the property
|
||||
* values as an array. May be null if the property is write-only
|
||||
* or must be indexed.
|
||||
* @param writeMethodName The name of the method used for writing the property
|
||||
* values as an array. May be null if the property is read-only
|
||||
* or must be indexed.
|
||||
* @param indexedReadMethodName The name of the method used for reading
|
||||
* an indexed property value.
|
||||
* May be null if the property is write-only.
|
||||
* @param indexedWriteMethodName The name of the method used for writing
|
||||
* an indexed property value.
|
||||
* May be null if the property is read-only.
|
||||
* @exception IntrospectionException if an exception occurs during
|
||||
* introspection.
|
||||
*/
|
||||
public IndexedPropertyDescriptor(String propertyName, Class<?> beanClass,
|
||||
String readMethodName, String writeMethodName,
|
||||
String indexedReadMethodName, String indexedWriteMethodName)
|
||||
throws IntrospectionException {
|
||||
super(propertyName, beanClass, readMethodName, writeMethodName);
|
||||
|
||||
this.indexedReadMethodName = indexedReadMethodName;
|
||||
if (indexedReadMethodName != null && getIndexedReadMethod() == null) {
|
||||
throw new IntrospectionException("Method not found: " + indexedReadMethodName);
|
||||
}
|
||||
|
||||
this.indexedWriteMethodName = indexedWriteMethodName;
|
||||
if (indexedWriteMethodName != null && getIndexedWriteMethod() == null) {
|
||||
throw new IntrospectionException("Method not found: " + indexedWriteMethodName);
|
||||
}
|
||||
// Implemented only for type checking.
|
||||
findIndexedPropertyType(getIndexedReadMethod(), getIndexedWriteMethod());
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor takes the name of a simple property, and Method
|
||||
* objects for reading and writing the property.
|
||||
*
|
||||
* @param propertyName The programmatic name of the property.
|
||||
* @param readMethod The method used for reading the property values as an array.
|
||||
* May be null if the property is write-only or must be indexed.
|
||||
* @param writeMethod The method used for writing the property values as an array.
|
||||
* May be null if the property is read-only or must be indexed.
|
||||
* @param indexedReadMethod The method used for reading an indexed property value.
|
||||
* May be null if the property is write-only.
|
||||
* @param indexedWriteMethod The method used for writing an indexed property value.
|
||||
* May be null if the property is read-only.
|
||||
* @exception IntrospectionException if an exception occurs during
|
||||
* introspection.
|
||||
*/
|
||||
public IndexedPropertyDescriptor(String propertyName, Method readMethod, Method writeMethod,
|
||||
Method indexedReadMethod, Method indexedWriteMethod)
|
||||
throws IntrospectionException {
|
||||
super(propertyName, readMethod, writeMethod);
|
||||
|
||||
setIndexedReadMethod0(indexedReadMethod);
|
||||
setIndexedWriteMethod0(indexedWriteMethod);
|
||||
|
||||
// Type checking
|
||||
setIndexedPropertyType(findIndexedPropertyType(indexedReadMethod, indexedWriteMethod));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates <code>PropertyDescriptor</code> for the specified bean
|
||||
* with the specified name and methods to read/write the property value.
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the method that should be used to read an indexed
|
||||
* property value.
|
||||
*
|
||||
* @return The method that should be used to read an indexed
|
||||
* property value.
|
||||
* May return null if the property isn't indexed or is write-only.
|
||||
*/
|
||||
public synchronized Method getIndexedReadMethod() {
|
||||
Method indexedReadMethod = this.indexedReadMethodRef.get();
|
||||
if (indexedReadMethod == null) {
|
||||
Class<?> cls = getClass0();
|
||||
if (cls == null ||
|
||||
(indexedReadMethodName == null && !this.indexedReadMethodRef.isSet())) {
|
||||
// the Indexed readMethod was explicitly set to null.
|
||||
return null;
|
||||
}
|
||||
String nextMethodName = Introspector.GET_PREFIX + getBaseName();
|
||||
if (indexedReadMethodName == null) {
|
||||
Class<?> type = getIndexedPropertyType0();
|
||||
if (type == boolean.class || type == null) {
|
||||
indexedReadMethodName = Introspector.IS_PREFIX + getBaseName();
|
||||
} else {
|
||||
indexedReadMethodName = nextMethodName;
|
||||
}
|
||||
}
|
||||
|
||||
Class<?>[] args = { int.class };
|
||||
indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 1, args);
|
||||
if ((indexedReadMethod == null) && !indexedReadMethodName.equals(nextMethodName)) {
|
||||
// no "is" method, so look for a "get" method.
|
||||
indexedReadMethodName = nextMethodName;
|
||||
indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 1, args);
|
||||
}
|
||||
setIndexedReadMethod0(indexedReadMethod);
|
||||
}
|
||||
return indexedReadMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the method that should be used to read an indexed property value.
|
||||
*
|
||||
* @param readMethod The new indexed read method.
|
||||
* @throws IntrospectionException if an exception occurs during
|
||||
* introspection.
|
||||
*/
|
||||
public synchronized void setIndexedReadMethod(Method readMethod)
|
||||
throws IntrospectionException {
|
||||
|
||||
// the indexed property type is set by the reader.
|
||||
setIndexedPropertyType(findIndexedPropertyType(readMethod,
|
||||
this.indexedWriteMethodRef.get()));
|
||||
setIndexedReadMethod0(readMethod);
|
||||
}
|
||||
|
||||
private void setIndexedReadMethod0(Method readMethod) {
|
||||
this.indexedReadMethodRef.set(readMethod);
|
||||
if (readMethod == null) {
|
||||
indexedReadMethodName = null;
|
||||
return;
|
||||
}
|
||||
setClass0(readMethod.getDeclaringClass());
|
||||
|
||||
indexedReadMethodName = readMethod.getName();
|
||||
setTransient(readMethod.getAnnotation(Transient.class));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the method that should be used to write an indexed property value.
|
||||
*
|
||||
* @return The method that should be used to write an indexed
|
||||
* property value.
|
||||
* May return null if the property isn't indexed or is read-only.
|
||||
*/
|
||||
public synchronized Method getIndexedWriteMethod() {
|
||||
Method indexedWriteMethod = this.indexedWriteMethodRef.get();
|
||||
if (indexedWriteMethod == null) {
|
||||
Class<?> cls = getClass0();
|
||||
if (cls == null ||
|
||||
(indexedWriteMethodName == null && !this.indexedWriteMethodRef.isSet())) {
|
||||
// the Indexed writeMethod was explicitly set to null.
|
||||
return null;
|
||||
}
|
||||
|
||||
// We need the indexed type to ensure that we get the correct method.
|
||||
// Cannot use the getIndexedPropertyType method since that could
|
||||
// result in an infinite loop.
|
||||
Class<?> type = getIndexedPropertyType0();
|
||||
if (type == null) {
|
||||
try {
|
||||
type = findIndexedPropertyType(getIndexedReadMethod(), null);
|
||||
setIndexedPropertyType(type);
|
||||
} catch (IntrospectionException ex) {
|
||||
// Set iprop type to be the classic type
|
||||
Class<?> propType = getPropertyType();
|
||||
if (propType.isArray()) {
|
||||
type = propType.getComponentType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (indexedWriteMethodName == null) {
|
||||
indexedWriteMethodName = Introspector.SET_PREFIX + getBaseName();
|
||||
}
|
||||
|
||||
Class<?>[] args = (type == null) ? null : new Class<?>[] { int.class, type };
|
||||
indexedWriteMethod = Introspector.findMethod(cls, indexedWriteMethodName, 2, args);
|
||||
if (indexedWriteMethod != null) {
|
||||
if (!indexedWriteMethod.getReturnType().equals(void.class)) {
|
||||
indexedWriteMethod = null;
|
||||
}
|
||||
}
|
||||
setIndexedWriteMethod0(indexedWriteMethod);
|
||||
}
|
||||
return indexedWriteMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the method that should be used to write an indexed property value.
|
||||
*
|
||||
* @param writeMethod The new indexed write method.
|
||||
* @throws IntrospectionException if an exception occurs during
|
||||
* introspection.
|
||||
*/
|
||||
public synchronized void setIndexedWriteMethod(Method writeMethod)
|
||||
throws IntrospectionException {
|
||||
|
||||
// If the indexed property type has not been set, then set it.
|
||||
Class<?> type = findIndexedPropertyType(getIndexedReadMethod(),
|
||||
writeMethod);
|
||||
setIndexedPropertyType(type);
|
||||
setIndexedWriteMethod0(writeMethod);
|
||||
}
|
||||
|
||||
private void setIndexedWriteMethod0(Method writeMethod) {
|
||||
this.indexedWriteMethodRef.set(writeMethod);
|
||||
if (writeMethod == null) {
|
||||
indexedWriteMethodName = null;
|
||||
return;
|
||||
}
|
||||
setClass0(writeMethod.getDeclaringClass());
|
||||
|
||||
indexedWriteMethodName = writeMethod.getName();
|
||||
setTransient(writeMethod.getAnnotation(Transient.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Java type info for the indexed property.
|
||||
* Note that the {@code Class} object may describe
|
||||
* primitive Java types such as {@code int}.
|
||||
* This type is returned by the indexed read method
|
||||
* or is used as the parameter type of the indexed write method.
|
||||
*
|
||||
* @return the {@code Class} object that represents the Java type info,
|
||||
* or {@code null} if the type cannot be determined
|
||||
*/
|
||||
public synchronized Class<?> getIndexedPropertyType() {
|
||||
Class<?> type = getIndexedPropertyType0();
|
||||
if (type == null) {
|
||||
try {
|
||||
type = findIndexedPropertyType(getIndexedReadMethod(),
|
||||
getIndexedWriteMethod());
|
||||
setIndexedPropertyType(type);
|
||||
} catch (IntrospectionException ex) {
|
||||
// fall
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
// Private methods which set get/set the Reference objects
|
||||
|
||||
private void setIndexedPropertyType(Class<?> type) {
|
||||
this.indexedPropertyTypeRef = getWeakReference(type);
|
||||
}
|
||||
|
||||
private Class<?> getIndexedPropertyType0() {
|
||||
return (this.indexedPropertyTypeRef != null)
|
||||
? this.indexedPropertyTypeRef.get()
|
||||
: null;
|
||||
}
|
||||
|
||||
private Class<?> findIndexedPropertyType(Method indexedReadMethod,
|
||||
Method indexedWriteMethod)
|
||||
throws IntrospectionException {
|
||||
Class<?> indexedPropertyType = null;
|
||||
|
||||
if (indexedReadMethod != null) {
|
||||
Class params[] = getParameterTypes(getClass0(), indexedReadMethod);
|
||||
if (params.length != 1) {
|
||||
throw new IntrospectionException("bad indexed read method arg count");
|
||||
}
|
||||
if (params[0] != Integer.TYPE) {
|
||||
throw new IntrospectionException("non int index to indexed read method");
|
||||
}
|
||||
indexedPropertyType = getReturnType(getClass0(), indexedReadMethod);
|
||||
if (indexedPropertyType == Void.TYPE) {
|
||||
throw new IntrospectionException("indexed read method returns void");
|
||||
}
|
||||
}
|
||||
if (indexedWriteMethod != null) {
|
||||
Class params[] = getParameterTypes(getClass0(), indexedWriteMethod);
|
||||
if (params.length != 2) {
|
||||
throw new IntrospectionException("bad indexed write method arg count");
|
||||
}
|
||||
if (params[0] != Integer.TYPE) {
|
||||
throw new IntrospectionException("non int index to indexed write method");
|
||||
}
|
||||
if (indexedPropertyType == null || params[1].isAssignableFrom(indexedPropertyType)) {
|
||||
indexedPropertyType = params[1];
|
||||
} else if (!indexedPropertyType.isAssignableFrom(params[1])) {
|
||||
throw new IntrospectionException(
|
||||
"type mismatch between indexed read and indexed write methods: "
|
||||
+ getName());
|
||||
}
|
||||
}
|
||||
Class<?> propertyType = getPropertyType();
|
||||
if (propertyType != null && (!propertyType.isArray() ||
|
||||
propertyType.getComponentType() != indexedPropertyType)) {
|
||||
throw new IntrospectionException("type mismatch between indexed and non-indexed methods: "
|
||||
+ getName());
|
||||
}
|
||||
return indexedPropertyType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this <code>PropertyDescriptor</code> against the specified object.
|
||||
* Returns true if the objects are the same. Two <code>PropertyDescriptor</code>s
|
||||
* are the same if the read, write, property types, property editor and
|
||||
* flags are equivalent.
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
// Note: This would be identical to PropertyDescriptor but they don't
|
||||
// share the same fields.
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj != null && obj instanceof IndexedPropertyDescriptor) {
|
||||
IndexedPropertyDescriptor other = (IndexedPropertyDescriptor)obj;
|
||||
Method otherIndexedReadMethod = other.getIndexedReadMethod();
|
||||
Method otherIndexedWriteMethod = other.getIndexedWriteMethod();
|
||||
|
||||
if (!compareMethods(getIndexedReadMethod(), otherIndexedReadMethod)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!compareMethods(getIndexedWriteMethod(), otherIndexedWriteMethod)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getIndexedPropertyType() != other.getIndexedPropertyType()) {
|
||||
return false;
|
||||
}
|
||||
return super.equals(obj);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Package-private constructor.
|
||||
* Merge two property descriptors. Where they conflict, give the
|
||||
* second argument (y) priority over the first argument (x).
|
||||
*
|
||||
* @param x The first (lower priority) PropertyDescriptor
|
||||
* @param y The second (higher priority) PropertyDescriptor
|
||||
*/
|
||||
|
||||
IndexedPropertyDescriptor(PropertyDescriptor x, PropertyDescriptor y) {
|
||||
super(x,y);
|
||||
Method tr = null;
|
||||
Method tw = null;
|
||||
|
||||
if (x instanceof IndexedPropertyDescriptor) {
|
||||
IndexedPropertyDescriptor ix = (IndexedPropertyDescriptor) x;
|
||||
tr = ix.getIndexedReadMethod();
|
||||
tw = ix.getIndexedWriteMethod();
|
||||
}
|
||||
if (y instanceof IndexedPropertyDescriptor) {
|
||||
IndexedPropertyDescriptor iy = (IndexedPropertyDescriptor) y;
|
||||
Method yr = iy.getIndexedReadMethod();
|
||||
if (isAssignable(tr, yr)) {
|
||||
tr = yr;
|
||||
}
|
||||
|
||||
Method yw = iy.getIndexedWriteMethod();
|
||||
if (isAssignable(tw, yw)) {
|
||||
tw = yw;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if(tr != null) {
|
||||
setIndexedReadMethod(tr);
|
||||
}
|
||||
if(tw != null) {
|
||||
setIndexedWriteMethod(tw);
|
||||
}
|
||||
} catch(IntrospectionException ex) {
|
||||
// Should not happen
|
||||
throw new AssertionError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Package-private dup constructor
|
||||
* This must isolate the new object from any changes to the old object.
|
||||
*/
|
||||
IndexedPropertyDescriptor(IndexedPropertyDescriptor old) {
|
||||
super(old);
|
||||
this.indexedReadMethodRef.set(old.indexedReadMethodRef.get());
|
||||
this.indexedWriteMethodRef.set(old.indexedWriteMethodRef.get());
|
||||
indexedPropertyTypeRef = old.indexedPropertyTypeRef;
|
||||
indexedWriteMethodName = old.indexedWriteMethodName;
|
||||
indexedReadMethodName = old.indexedReadMethodName;
|
||||
}
|
||||
|
||||
void updateGenericsFor(Class<?> type) {
|
||||
super.updateGenericsFor(type);
|
||||
try {
|
||||
setIndexedPropertyType(findIndexedPropertyType(this.indexedReadMethodRef.get(), this.indexedWriteMethodRef.get()));
|
||||
}
|
||||
catch (IntrospectionException exception) {
|
||||
setIndexedPropertyType(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code value for the object.
|
||||
* See {@link java.lang.Object#hashCode} for a complete description.
|
||||
*
|
||||
* @return a hash code value for this object.
|
||||
* @since 1.5
|
||||
*/
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
|
||||
result = 37 * result + ((indexedWriteMethodName == null) ? 0 :
|
||||
indexedWriteMethodName.hashCode());
|
||||
result = 37 * result + ((indexedReadMethodName == null) ? 0 :
|
||||
indexedReadMethodName.hashCode());
|
||||
result = 37 * result + ((getIndexedPropertyType() == null) ? 0 :
|
||||
getIndexedPropertyType().hashCode());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void appendTo(StringBuilder sb) {
|
||||
super.appendTo(sb);
|
||||
appendTo(sb, "indexedPropertyType", this.indexedPropertyTypeRef);
|
||||
appendTo(sb, "indexedReadMethod", this.indexedReadMethodRef.get());
|
||||
appendTo(sb, "indexedWriteMethod", this.indexedWriteMethodRef.get());
|
||||
}
|
||||
}
|
||||
50
jdkSrc/jdk8/java/beans/IntrospectionException.java
Normal file
50
jdkSrc/jdk8/java/beans/IntrospectionException.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2009, 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;
|
||||
|
||||
/**
|
||||
* Thrown when an exception happens during Introspection.
|
||||
* <p>
|
||||
* Typical causes include not being able to map a string class name
|
||||
* to a Class object, not being able to resolve a string method name,
|
||||
* or specifying a method name that has the wrong type signature for
|
||||
* its intended use.
|
||||
*/
|
||||
|
||||
public
|
||||
class IntrospectionException extends Exception {
|
||||
private static final long serialVersionUID = -3728150539969542619L;
|
||||
|
||||
/**
|
||||
* Constructs an <code>IntrospectionException</code> with a
|
||||
* detailed message.
|
||||
*
|
||||
* @param mess Descriptive message
|
||||
*/
|
||||
public IntrospectionException(String mess) {
|
||||
super(mess);
|
||||
}
|
||||
}
|
||||
1633
jdkSrc/jdk8/java/beans/Introspector.java
Normal file
1633
jdkSrc/jdk8/java/beans/Introspector.java
Normal file
File diff suppressed because it is too large
Load Diff
1454
jdkSrc/jdk8/java/beans/MetaData.java
Normal file
1454
jdkSrc/jdk8/java/beans/MetaData.java
Normal file
File diff suppressed because it is too large
Load Diff
233
jdkSrc/jdk8/java/beans/MethodDescriptor.java
Normal file
233
jdkSrc/jdk8/java/beans/MethodDescriptor.java
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2013, 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.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A MethodDescriptor describes a particular method that a Java Bean
|
||||
* supports for external access from other components.
|
||||
*/
|
||||
|
||||
public class MethodDescriptor extends FeatureDescriptor {
|
||||
|
||||
private final MethodRef methodRef = new MethodRef();
|
||||
|
||||
private String[] paramNames;
|
||||
|
||||
private List<WeakReference<Class<?>>> params;
|
||||
|
||||
private ParameterDescriptor parameterDescriptors[];
|
||||
|
||||
/**
|
||||
* Constructs a <code>MethodDescriptor</code> from a
|
||||
* <code>Method</code>.
|
||||
*
|
||||
* @param method The low-level method information.
|
||||
*/
|
||||
public MethodDescriptor(Method method) {
|
||||
this(method, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a <code>MethodDescriptor</code> from a
|
||||
* <code>Method</code> providing descriptive information for each
|
||||
* of the method's parameters.
|
||||
*
|
||||
* @param method The low-level method information.
|
||||
* @param parameterDescriptors Descriptive information for each of the
|
||||
* method's parameters.
|
||||
*/
|
||||
public MethodDescriptor(Method method,
|
||||
ParameterDescriptor parameterDescriptors[]) {
|
||||
setName(method.getName());
|
||||
setMethod(method);
|
||||
this.parameterDescriptors = (parameterDescriptors != null)
|
||||
? parameterDescriptors.clone()
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the method that this MethodDescriptor encapsulates.
|
||||
*
|
||||
* @return The low-level description of the method
|
||||
*/
|
||||
public synchronized Method getMethod() {
|
||||
Method method = this.methodRef.get();
|
||||
if (method == null) {
|
||||
Class<?> cls = getClass0();
|
||||
String name = getName();
|
||||
if ((cls != null) && (name != null)) {
|
||||
Class<?>[] params = getParams();
|
||||
if (params == null) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// Find methods for up to 2 params. We are guessing here.
|
||||
// This block should never execute unless the classloader
|
||||
// that loaded the argument classes disappears.
|
||||
method = Introspector.findMethod(cls, name, i, null);
|
||||
if (method != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
method = Introspector.findMethod(cls, name, params.length, params);
|
||||
}
|
||||
setMethod(method);
|
||||
}
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
private synchronized void setMethod(Method method) {
|
||||
if (method == null) {
|
||||
return;
|
||||
}
|
||||
if (getClass0() == null) {
|
||||
setClass0(method.getDeclaringClass());
|
||||
}
|
||||
setParams(getParameterTypes(getClass0(), method));
|
||||
this.methodRef.set(method);
|
||||
}
|
||||
|
||||
private synchronized void setParams(Class<?>[] param) {
|
||||
if (param == null) {
|
||||
return;
|
||||
}
|
||||
paramNames = new String[param.length];
|
||||
params = new ArrayList<>(param.length);
|
||||
for (int i = 0; i < param.length; i++) {
|
||||
paramNames[i] = param[i].getName();
|
||||
params.add(new WeakReference<Class<?>>(param[i]));
|
||||
}
|
||||
}
|
||||
|
||||
// pp getParamNames used as an optimization to avoid method.getParameterTypes.
|
||||
String[] getParamNames() {
|
||||
return paramNames;
|
||||
}
|
||||
|
||||
private synchronized Class<?>[] getParams() {
|
||||
Class<?>[] clss = new Class<?>[params.size()];
|
||||
|
||||
for (int i = 0; i < params.size(); i++) {
|
||||
Reference<? extends Class<?>> ref = (Reference<? extends Class<?>>)params.get(i);
|
||||
Class<?> cls = ref.get();
|
||||
if (cls == null) {
|
||||
return null;
|
||||
} else {
|
||||
clss[i] = cls;
|
||||
}
|
||||
}
|
||||
return clss;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ParameterDescriptor for each of this MethodDescriptor's
|
||||
* method's parameters.
|
||||
*
|
||||
* @return The locale-independent names of the parameters. May return
|
||||
* a null array if the parameter names aren't known.
|
||||
*/
|
||||
public ParameterDescriptor[] getParameterDescriptors() {
|
||||
return (this.parameterDescriptors != null)
|
||||
? this.parameterDescriptors.clone()
|
||||
: null;
|
||||
}
|
||||
|
||||
private static Method resolve(Method oldMethod, Method newMethod) {
|
||||
if (oldMethod == null) {
|
||||
return newMethod;
|
||||
}
|
||||
if (newMethod == null) {
|
||||
return oldMethod;
|
||||
}
|
||||
return !oldMethod.isSynthetic() && newMethod.isSynthetic() ? oldMethod : newMethod;
|
||||
}
|
||||
|
||||
/*
|
||||
* Package-private constructor
|
||||
* Merge two method descriptors. Where they conflict, give the
|
||||
* second argument (y) priority over the first argument (x).
|
||||
* @param x The first (lower priority) MethodDescriptor
|
||||
* @param y The second (higher priority) MethodDescriptor
|
||||
*/
|
||||
|
||||
MethodDescriptor(MethodDescriptor x, MethodDescriptor y) {
|
||||
super(x, y);
|
||||
|
||||
this.methodRef.set(resolve(x.methodRef.get(), y.methodRef.get()));
|
||||
params = x.params;
|
||||
if (y.params != null) {
|
||||
params = y.params;
|
||||
}
|
||||
paramNames = x.paramNames;
|
||||
if (y.paramNames != null) {
|
||||
paramNames = y.paramNames;
|
||||
}
|
||||
|
||||
parameterDescriptors = x.parameterDescriptors;
|
||||
if (y.parameterDescriptors != null) {
|
||||
parameterDescriptors = y.parameterDescriptors;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Package-private dup constructor
|
||||
* This must isolate the new object from any changes to the old object.
|
||||
*/
|
||||
MethodDescriptor(MethodDescriptor old) {
|
||||
super(old);
|
||||
|
||||
this.methodRef.set(old.getMethod());
|
||||
params = old.params;
|
||||
paramNames = old.paramNames;
|
||||
|
||||
if (old.parameterDescriptors != null) {
|
||||
int len = old.parameterDescriptors.length;
|
||||
parameterDescriptors = new ParameterDescriptor[len];
|
||||
for (int i = 0; i < len ; i++) {
|
||||
parameterDescriptors[i] = new ParameterDescriptor(old.parameterDescriptors[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void appendTo(StringBuilder sb) {
|
||||
appendTo(sb, "method", this.methodRef.get());
|
||||
if (this.parameterDescriptors != null) {
|
||||
sb.append("; parameterDescriptors={");
|
||||
for (ParameterDescriptor pd : this.parameterDescriptors) {
|
||||
sb.append(pd).append(", ");
|
||||
}
|
||||
sb.setLength(sb.length() - 2);
|
||||
sb.append("}");
|
||||
}
|
||||
}
|
||||
}
|
||||
86
jdkSrc/jdk8/java/beans/MethodRef.java
Normal file
86
jdkSrc/jdk8/java/beans/MethodRef.java
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2016, 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.ref.SoftReference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static sun.reflect.misc.ReflectUtil.isPackageAccessible;
|
||||
|
||||
final class MethodRef {
|
||||
private String signature;
|
||||
private SoftReference<Method> methodRef;
|
||||
private WeakReference<Class<?>> typeRef;
|
||||
|
||||
void set(Method method) {
|
||||
if (method == null) {
|
||||
this.signature = null;
|
||||
this.methodRef = null;
|
||||
this.typeRef = null;
|
||||
}
|
||||
else {
|
||||
this.signature = method.toGenericString();
|
||||
this.methodRef = new SoftReference<>(method);
|
||||
this.typeRef = new WeakReference<Class<?>>(method.getDeclaringClass());
|
||||
}
|
||||
}
|
||||
|
||||
boolean isSet() {
|
||||
return this.methodRef != null;
|
||||
}
|
||||
|
||||
Method get() {
|
||||
if (this.methodRef == null) {
|
||||
return null;
|
||||
}
|
||||
Method method = this.methodRef.get();
|
||||
if (method == null) {
|
||||
method = find(this.typeRef.get(), this.signature);
|
||||
if (method == null) {
|
||||
this.signature = null;
|
||||
this.methodRef = null;
|
||||
this.typeRef = null;
|
||||
return null;
|
||||
}
|
||||
this.methodRef = new SoftReference<>(method);
|
||||
}
|
||||
return isPackageAccessible(method.getDeclaringClass()) ? method : null;
|
||||
}
|
||||
|
||||
private static Method find(Class<?> type, String signature) {
|
||||
if (type != null) {
|
||||
for (Method method : type.getMethods()) {
|
||||
if (type.equals(method.getDeclaringClass())) {
|
||||
if (method.toGenericString().equals(signature)) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
117
jdkSrc/jdk8/java/beans/NameGenerator.java
Normal file
117
jdkSrc/jdk8/java/beans/NameGenerator.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2011, 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.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Locale.ENGLISH;
|
||||
|
||||
/**
|
||||
* A utility class which generates unique names for object instances.
|
||||
* The name will be a concatenation of the unqualified class name
|
||||
* and an instance number.
|
||||
* <p>
|
||||
* For example, if the first object instance javax.swing.JButton
|
||||
* is passed into <code>instanceName</code> then the returned
|
||||
* string identifier will be "JButton0".
|
||||
*
|
||||
* @author Philip Milne
|
||||
*/
|
||||
class NameGenerator {
|
||||
|
||||
private Map<Object, String> valueToName;
|
||||
private Map<String, Integer> nameToCount;
|
||||
|
||||
public NameGenerator() {
|
||||
valueToName = new IdentityHashMap<>();
|
||||
nameToCount = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the name cache. Should be called to near the end of
|
||||
* the encoding cycle.
|
||||
*/
|
||||
public void clear() {
|
||||
valueToName.clear();
|
||||
nameToCount.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root name of the class.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static String unqualifiedClassName(Class type) {
|
||||
if (type.isArray()) {
|
||||
return unqualifiedClassName(type.getComponentType())+"Array";
|
||||
}
|
||||
String name = type.getName();
|
||||
return name.substring(name.lastIndexOf('.')+1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a String which capitalizes the first letter of the string.
|
||||
*/
|
||||
public static String capitalize(String name) {
|
||||
if (name == null || name.length() == 0) {
|
||||
return name;
|
||||
}
|
||||
return name.substring(0, 1).toUpperCase(ENGLISH) + name.substring(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a unique string which identifies the object instance.
|
||||
* Invocations are cached so that if an object has been previously
|
||||
* passed into this method then the same identifier is returned.
|
||||
*
|
||||
* @param instance object used to generate string
|
||||
* @return a unique string representing the object
|
||||
*/
|
||||
public String instanceName(Object instance) {
|
||||
if (instance == null) {
|
||||
return "null";
|
||||
}
|
||||
if (instance instanceof Class) {
|
||||
return unqualifiedClassName((Class)instance);
|
||||
}
|
||||
else {
|
||||
String result = valueToName.get(instance);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
Class<?> type = instance.getClass();
|
||||
String className = unqualifiedClassName(type);
|
||||
|
||||
Integer size = nameToCount.get(className);
|
||||
int instanceNumber = (size == null) ? 0 : (size).intValue() + 1;
|
||||
nameToCount.put(className, new Integer(instanceNumber));
|
||||
|
||||
result = className + instanceNumber;
|
||||
valueToName.put(instance, result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
53
jdkSrc/jdk8/java/beans/ParameterDescriptor.java
Normal file
53
jdkSrc/jdk8/java/beans/ParameterDescriptor.java
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 1997, 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;
|
||||
|
||||
/**
|
||||
* The ParameterDescriptor class allows bean implementors to provide
|
||||
* additional information on each of their parameters, beyond the
|
||||
* low level type information provided by the java.lang.reflect.Method
|
||||
* class.
|
||||
* <p>
|
||||
* Currently all our state comes from the FeatureDescriptor base class.
|
||||
*/
|
||||
|
||||
public class ParameterDescriptor extends FeatureDescriptor {
|
||||
|
||||
/**
|
||||
* Public default constructor.
|
||||
*/
|
||||
public ParameterDescriptor() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Package private dup constructor.
|
||||
* This must isolate the new object from any changes to the old object.
|
||||
*/
|
||||
ParameterDescriptor(ParameterDescriptor old) {
|
||||
super(old);
|
||||
}
|
||||
|
||||
}
|
||||
216
jdkSrc/jdk8/java/beans/PersistenceDelegate.java
Normal file
216
jdkSrc/jdk8/java/beans/PersistenceDelegate.java
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, 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;
|
||||
|
||||
/**
|
||||
* The PersistenceDelegate class takes the responsibility
|
||||
* for expressing the state of an instance of a given class
|
||||
* in terms of the methods in the class's public API. Instead
|
||||
* of associating the responsibility of persistence with
|
||||
* the class itself as is done, for example, by the
|
||||
* <code>readObject</code> and <code>writeObject</code>
|
||||
* methods used by the <code>ObjectOutputStream</code>, streams like
|
||||
* the <code>XMLEncoder</code> which
|
||||
* use this delegation model can have their behavior controlled
|
||||
* independently of the classes themselves. Normally, the class
|
||||
* is the best place to put such information and conventions
|
||||
* can easily be expressed in this delegation scheme to do just that.
|
||||
* Sometimes however, it is the case that a minor problem
|
||||
* in a single class prevents an entire object graph from
|
||||
* being written and this can leave the application
|
||||
* developer with no recourse but to attempt to shadow
|
||||
* the problematic classes locally or use alternative
|
||||
* persistence techniques. In situations like these, the
|
||||
* delegation model gives a relatively clean mechanism for
|
||||
* the application developer to intervene in all parts of the
|
||||
* serialization process without requiring that modifications
|
||||
* be made to the implementation of classes which are not part
|
||||
* of the application itself.
|
||||
* <p>
|
||||
* In addition to using a delegation model, this persistence
|
||||
* scheme differs from traditional serialization schemes
|
||||
* in requiring an analog of the <code>writeObject</code>
|
||||
* method without a corresponding <code>readObject</code>
|
||||
* method. The <code>writeObject</code> analog encodes each
|
||||
* instance in terms of its public API and there is no need to
|
||||
* define a <code>readObject</code> analog
|
||||
* since the procedure for reading the serialized form
|
||||
* is defined by the semantics of method invocation as laid
|
||||
* out in the Java Language Specification.
|
||||
* Breaking the dependency between <code>writeObject</code>
|
||||
* and <code>readObject</code> implementations, which may
|
||||
* change from version to version, is the key factor
|
||||
* in making the archives produced by this technique immune
|
||||
* to changes in the private implementations of the classes
|
||||
* to which they refer.
|
||||
* <p>
|
||||
* A persistence delegate, may take control of all
|
||||
* aspects of the persistence of an object including:
|
||||
* <ul>
|
||||
* <li>
|
||||
* Deciding whether or not an instance can be mutated
|
||||
* into another instance of the same class.
|
||||
* <li>
|
||||
* Instantiating the object, either by calling a
|
||||
* public constructor or a public factory method.
|
||||
* <li>
|
||||
* Performing the initialization of the object.
|
||||
* </ul>
|
||||
* @see XMLEncoder
|
||||
*
|
||||
* @since 1.4
|
||||
*
|
||||
* @author Philip Milne
|
||||
*/
|
||||
|
||||
public abstract class PersistenceDelegate {
|
||||
|
||||
/**
|
||||
* The <code>writeObject</code> is a single entry point to the persistence
|
||||
* and is used by a <code>Encoder</code> in the traditional
|
||||
* mode of delegation. Although this method is not final,
|
||||
* it should not need to be subclassed under normal circumstances.
|
||||
* <p>
|
||||
* This implementation first checks to see if the stream
|
||||
* has already encountered this object. Next the
|
||||
* <code>mutatesTo</code> method is called to see if
|
||||
* that candidate returned from the stream can
|
||||
* be mutated into an accurate copy of <code>oldInstance</code>.
|
||||
* If it can, the <code>initialize</code> method is called to
|
||||
* perform the initialization. If not, the candidate is removed
|
||||
* from the stream, and the <code>instantiate</code> method
|
||||
* is called to create a new candidate for this object.
|
||||
*
|
||||
* @param oldInstance The instance that will be created by this expression.
|
||||
* @param out The stream to which this expression will be written.
|
||||
*
|
||||
* @throws NullPointerException if {@code out} is {@code null}
|
||||
*/
|
||||
public void writeObject(Object oldInstance, Encoder out) {
|
||||
Object newInstance = out.get(oldInstance);
|
||||
if (!mutatesTo(oldInstance, newInstance)) {
|
||||
out.remove(oldInstance);
|
||||
out.writeExpression(instantiate(oldInstance, out));
|
||||
}
|
||||
else {
|
||||
initialize(oldInstance.getClass(), oldInstance, newInstance, out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if an <em>equivalent</em> copy of <code>oldInstance</code> may be
|
||||
* created by applying a series of statements to <code>newInstance</code>.
|
||||
* In the specification of this method, we mean by equivalent that the modified instance
|
||||
* is indistinguishable from <code>oldInstance</code> in the behavior
|
||||
* of the relevant methods in its public API. [Note: we use the
|
||||
* phrase <em>relevant</em> methods rather than <em>all</em> methods
|
||||
* here only because, to be strictly correct, methods like <code>hashCode</code>
|
||||
* and <code>toString</code> prevent most classes from producing truly
|
||||
* indistinguishable copies of their instances].
|
||||
* <p>
|
||||
* The default behavior returns <code>true</code>
|
||||
* if the classes of the two instances are the same.
|
||||
*
|
||||
* @param oldInstance The instance to be copied.
|
||||
* @param newInstance The instance that is to be modified.
|
||||
* @return True if an equivalent copy of <code>newInstance</code> may be
|
||||
* created by applying a series of mutations to <code>oldInstance</code>.
|
||||
*/
|
||||
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
|
||||
return (newInstance != null && oldInstance != null &&
|
||||
oldInstance.getClass() == newInstance.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an expression whose value is <code>oldInstance</code>.
|
||||
* This method is used to characterize the constructor
|
||||
* or factory method that should be used to create the given object.
|
||||
* For example, the <code>instantiate</code> method of the persistence
|
||||
* delegate for the <code>Field</code> class could be defined as follows:
|
||||
* <pre>
|
||||
* Field f = (Field)oldInstance;
|
||||
* return new Expression(f, f.getDeclaringClass(), "getField", new Object[]{f.getName()});
|
||||
* </pre>
|
||||
* Note that we declare the value of the returned expression so that
|
||||
* the value of the expression (as returned by <code>getValue</code>)
|
||||
* will be identical to <code>oldInstance</code>.
|
||||
*
|
||||
* @param oldInstance The instance that will be created by this expression.
|
||||
* @param out The stream to which this expression will be written.
|
||||
* @return An expression whose value is <code>oldInstance</code>.
|
||||
*
|
||||
* @throws NullPointerException if {@code out} is {@code null}
|
||||
* and this value is used in the method
|
||||
*/
|
||||
protected abstract Expression instantiate(Object oldInstance, Encoder out);
|
||||
|
||||
/**
|
||||
* Produce a series of statements with side effects on <code>newInstance</code>
|
||||
* so that the new instance becomes <em>equivalent</em> to <code>oldInstance</code>.
|
||||
* In the specification of this method, we mean by equivalent that, after the method
|
||||
* returns, the modified instance is indistinguishable from
|
||||
* <code>newInstance</code> in the behavior of all methods in its
|
||||
* public API.
|
||||
* <p>
|
||||
* The implementation typically achieves this goal by producing a series of
|
||||
* "what happened" statements involving the <code>oldInstance</code>
|
||||
* and its publicly available state. These statements are sent
|
||||
* to the output stream using its <code>writeExpression</code>
|
||||
* method which returns an expression involving elements in
|
||||
* a cloned environment simulating the state of an input stream during
|
||||
* reading. Each statement returned will have had all instances
|
||||
* the old environment replaced with objects which exist in the new
|
||||
* one. In particular, references to the target of these statements,
|
||||
* which start out as references to <code>oldInstance</code> are returned
|
||||
* as references to the <code>newInstance</code> instead.
|
||||
* Executing these statements effects an incremental
|
||||
* alignment of the state of the two objects as a series of
|
||||
* modifications to the objects in the new environment.
|
||||
* By the time the initialize method returns it should be impossible
|
||||
* to tell the two instances apart by using their public APIs.
|
||||
* Most importantly, the sequence of steps that were used to make
|
||||
* these objects appear equivalent will have been recorded
|
||||
* by the output stream and will form the actual output when
|
||||
* the stream is flushed.
|
||||
* <p>
|
||||
* The default implementation, calls the <code>initialize</code>
|
||||
* method of the type's superclass.
|
||||
*
|
||||
* @param type the type of the instances
|
||||
* @param oldInstance The instance to be copied.
|
||||
* @param newInstance The instance that is to be modified.
|
||||
* @param out The stream to which any initialization statements should be written.
|
||||
*
|
||||
* @throws NullPointerException if {@code out} is {@code null}
|
||||
*/
|
||||
protected void initialize(Class<?> type,
|
||||
Object oldInstance, Object newInstance,
|
||||
Encoder out)
|
||||
{
|
||||
Class<?> superType = type.getSuperclass();
|
||||
PersistenceDelegate info = out.getPersistenceDelegate(superType);
|
||||
info.initialize(superType, oldInstance, newInstance, out);
|
||||
}
|
||||
}
|
||||
166
jdkSrc/jdk8/java/beans/PropertyChangeEvent.java
Normal file
166
jdkSrc/jdk8/java/beans/PropertyChangeEvent.java
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2011, 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.util.EventObject;
|
||||
|
||||
/**
|
||||
* A "PropertyChange" event gets delivered whenever a bean changes a "bound"
|
||||
* or "constrained" property. A PropertyChangeEvent object is sent as an
|
||||
* argument to the PropertyChangeListener and VetoableChangeListener methods.
|
||||
* <P>
|
||||
* Normally PropertyChangeEvents are accompanied by the name and the old
|
||||
* and new value of the changed property. If the new value is a primitive
|
||||
* type (such as int or boolean) it must be wrapped as the
|
||||
* corresponding java.lang.* Object type (such as Integer or Boolean).
|
||||
* <P>
|
||||
* Null values may be provided for the old and the new values if their
|
||||
* true values are not known.
|
||||
* <P>
|
||||
* An event source may send a null object as the name to indicate that an
|
||||
* arbitrary set of if its properties have changed. In this case the
|
||||
* old and new values should also be null.
|
||||
*/
|
||||
public class PropertyChangeEvent extends EventObject {
|
||||
private static final long serialVersionUID = 7042693688939648123L;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PropertyChangeEvent}.
|
||||
*
|
||||
* @param source the bean that fired the event
|
||||
* @param propertyName the programmatic name of the property that was changed
|
||||
* @param oldValue the old value of the property
|
||||
* @param newValue the new value of the property
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code source} is {@code null}
|
||||
*/
|
||||
public PropertyChangeEvent(Object source, String propertyName,
|
||||
Object oldValue, Object newValue) {
|
||||
super(source);
|
||||
this.propertyName = propertyName;
|
||||
this.newValue = newValue;
|
||||
this.oldValue = oldValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the programmatic name of the property that was changed.
|
||||
*
|
||||
* @return The programmatic name of the property that was changed.
|
||||
* May be null if multiple properties have changed.
|
||||
*/
|
||||
public String getPropertyName() {
|
||||
return propertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the new value for the property, expressed as an Object.
|
||||
*
|
||||
* @return The new value for the property, expressed as an Object.
|
||||
* May be null if multiple properties have changed.
|
||||
*/
|
||||
public Object getNewValue() {
|
||||
return newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the old value for the property, expressed as an Object.
|
||||
*
|
||||
* @return The old value for the property, expressed as an Object.
|
||||
* May be null if multiple properties have changed.
|
||||
*/
|
||||
public Object getOldValue() {
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the propagationId object for the event.
|
||||
*
|
||||
* @param propagationId The propagationId object for the event.
|
||||
*/
|
||||
public void setPropagationId(Object propagationId) {
|
||||
this.propagationId = propagationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "propagationId" field is reserved for future use. In Beans 1.0
|
||||
* the sole requirement is that if a listener catches a PropertyChangeEvent
|
||||
* and then fires a PropertyChangeEvent of its own, then it should
|
||||
* make sure that it propagates the propagationId field from its
|
||||
* incoming event to its outgoing event.
|
||||
*
|
||||
* @return the propagationId object associated with a bound/constrained
|
||||
* property update.
|
||||
*/
|
||||
public Object getPropagationId() {
|
||||
return propagationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* name of the property that changed. May be null, if not known.
|
||||
* @serial
|
||||
*/
|
||||
private String propertyName;
|
||||
|
||||
/**
|
||||
* New value for property. May be null if not known.
|
||||
* @serial
|
||||
*/
|
||||
private Object newValue;
|
||||
|
||||
/**
|
||||
* Previous value for property. May be null if not known.
|
||||
* @serial
|
||||
*/
|
||||
private Object oldValue;
|
||||
|
||||
/**
|
||||
* Propagation ID. May be null.
|
||||
* @serial
|
||||
* @see #getPropagationId
|
||||
*/
|
||||
private Object propagationId;
|
||||
|
||||
/**
|
||||
* Returns a string representation of the object.
|
||||
*
|
||||
* @return a string representation of the object
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder(getClass().getName());
|
||||
sb.append("[propertyName=").append(getPropertyName());
|
||||
appendTo(sb);
|
||||
sb.append("; oldValue=").append(getOldValue());
|
||||
sb.append("; newValue=").append(getNewValue());
|
||||
sb.append("; propagationId=").append(getPropagationId());
|
||||
sb.append("; source=").append(getSource());
|
||||
return sb.append("]").toString();
|
||||
}
|
||||
|
||||
void appendTo(StringBuilder sb) {
|
||||
}
|
||||
}
|
||||
44
jdkSrc/jdk8/java/beans/PropertyChangeListener.java
Normal file
44
jdkSrc/jdk8/java/beans/PropertyChangeListener.java
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 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;
|
||||
|
||||
/**
|
||||
* A "PropertyChange" event gets fired whenever a bean changes a "bound"
|
||||
* property. You can register a PropertyChangeListener with a source
|
||||
* bean so as to be notified of any bound property updates.
|
||||
*/
|
||||
|
||||
public interface PropertyChangeListener extends java.util.EventListener {
|
||||
|
||||
/**
|
||||
* This method gets called when a bound property is changed.
|
||||
* @param evt A PropertyChangeEvent object describing the event source
|
||||
* and the property that has changed.
|
||||
*/
|
||||
|
||||
void propertyChange(PropertyChangeEvent evt);
|
||||
|
||||
}
|
||||
81
jdkSrc/jdk8/java/beans/PropertyChangeListenerProxy.java
Normal file
81
jdkSrc/jdk8/java/beans/PropertyChangeListenerProxy.java
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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.util.EventListenerProxy;
|
||||
|
||||
/**
|
||||
* A class which extends the {@code EventListenerProxy}
|
||||
* specifically for adding a {@code PropertyChangeListener}
|
||||
* with a "bound" property.
|
||||
* Instances of this class can be added
|
||||
* as {@code PropertyChangeListener}s to a bean
|
||||
* which supports firing property change events.
|
||||
* <p>
|
||||
* If the object has a {@code getPropertyChangeListeners} method
|
||||
* then the array returned could be a mixture of {@code PropertyChangeListener}
|
||||
* and {@code PropertyChangeListenerProxy} objects.
|
||||
*
|
||||
* @see java.util.EventListenerProxy
|
||||
* @see PropertyChangeSupport#getPropertyChangeListeners
|
||||
* @since 1.4
|
||||
*/
|
||||
public class PropertyChangeListenerProxy
|
||||
extends EventListenerProxy<PropertyChangeListener>
|
||||
implements PropertyChangeListener {
|
||||
|
||||
private final String propertyName;
|
||||
|
||||
/**
|
||||
* Constructor which binds the {@code PropertyChangeListener}
|
||||
* to a specific property.
|
||||
*
|
||||
* @param propertyName the name of the property to listen on
|
||||
* @param listener the listener object
|
||||
*/
|
||||
public PropertyChangeListenerProxy(String propertyName, PropertyChangeListener listener) {
|
||||
super(listener);
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards the property change event to the listener delegate.
|
||||
*
|
||||
* @param event the property change event
|
||||
*/
|
||||
public void propertyChange(PropertyChangeEvent event) {
|
||||
getListener().propertyChange(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the named property associated with the listener.
|
||||
*
|
||||
* @return the name of the named property associated with the listener
|
||||
*/
|
||||
public String getPropertyName() {
|
||||
return this.propertyName;
|
||||
}
|
||||
}
|
||||
547
jdkSrc/jdk8/java/beans/PropertyChangeSupport.java
Normal file
547
jdkSrc/jdk8/java/beans/PropertyChangeSupport.java
Normal file
@@ -0,0 +1,547 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2013, 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.io.Serializable;
|
||||
import java.io.ObjectStreamField;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* This is a utility class that can be used by beans that support bound
|
||||
* properties. It manages a list of listeners and dispatches
|
||||
* {@link PropertyChangeEvent}s to them. You can use an instance of this class
|
||||
* as a member field of your bean and delegate these types of work to it.
|
||||
* The {@link PropertyChangeListener} can be registered for all properties
|
||||
* or for a property specified by name.
|
||||
* <p>
|
||||
* Here is an example of {@code PropertyChangeSupport} usage that follows
|
||||
* the rules and recommendations laid out in the JavaBeans™ specification:
|
||||
* <pre>
|
||||
* public class MyBean {
|
||||
* private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
*
|
||||
* public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
* this.pcs.addPropertyChangeListener(listener);
|
||||
* }
|
||||
*
|
||||
* public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
* this.pcs.removePropertyChangeListener(listener);
|
||||
* }
|
||||
*
|
||||
* private String value;
|
||||
*
|
||||
* public String getValue() {
|
||||
* return this.value;
|
||||
* }
|
||||
*
|
||||
* public void setValue(String newValue) {
|
||||
* String oldValue = this.value;
|
||||
* this.value = newValue;
|
||||
* this.pcs.firePropertyChange("value", oldValue, newValue);
|
||||
* }
|
||||
*
|
||||
* [...]
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* A {@code PropertyChangeSupport} instance is thread-safe.
|
||||
* <p>
|
||||
* This class is serializable. When it is serialized it will save
|
||||
* (and restore) any listeners that are themselves serializable. Any
|
||||
* non-serializable listeners will be skipped during serialization.
|
||||
*
|
||||
* @see VetoableChangeSupport
|
||||
*/
|
||||
public class PropertyChangeSupport implements Serializable {
|
||||
private PropertyChangeListenerMap map = new PropertyChangeListenerMap();
|
||||
|
||||
/**
|
||||
* Constructs a <code>PropertyChangeSupport</code> object.
|
||||
*
|
||||
* @param sourceBean The bean to be given as the source for any events.
|
||||
*/
|
||||
public PropertyChangeSupport(Object sourceBean) {
|
||||
if (sourceBean == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
source = sourceBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a PropertyChangeListener to the listener list.
|
||||
* The listener is registered for all properties.
|
||||
* The same listener object may be added more than once, and will be called
|
||||
* as many times as it is added.
|
||||
* If <code>listener</code> is null, no exception is thrown and no action
|
||||
* is taken.
|
||||
*
|
||||
* @param listener The PropertyChangeListener to be added
|
||||
*/
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
if (listener == null) {
|
||||
return;
|
||||
}
|
||||
if (listener instanceof PropertyChangeListenerProxy) {
|
||||
PropertyChangeListenerProxy proxy =
|
||||
(PropertyChangeListenerProxy)listener;
|
||||
// Call two argument add method.
|
||||
addPropertyChangeListener(proxy.getPropertyName(),
|
||||
proxy.getListener());
|
||||
} else {
|
||||
this.map.add(null, listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a PropertyChangeListener from the listener list.
|
||||
* This removes a PropertyChangeListener that was registered
|
||||
* for all properties.
|
||||
* If <code>listener</code> was added more than once to the same event
|
||||
* source, it will be notified one less time after being removed.
|
||||
* If <code>listener</code> is null, or was never added, no exception is
|
||||
* thrown and no action is taken.
|
||||
*
|
||||
* @param listener The PropertyChangeListener to be removed
|
||||
*/
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
if (listener == null) {
|
||||
return;
|
||||
}
|
||||
if (listener instanceof PropertyChangeListenerProxy) {
|
||||
PropertyChangeListenerProxy proxy =
|
||||
(PropertyChangeListenerProxy)listener;
|
||||
// Call two argument remove method.
|
||||
removePropertyChangeListener(proxy.getPropertyName(),
|
||||
proxy.getListener());
|
||||
} else {
|
||||
this.map.remove(null, listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all the listeners that were added to the
|
||||
* PropertyChangeSupport object with addPropertyChangeListener().
|
||||
* <p>
|
||||
* If some listeners have been added with a named property, then
|
||||
* the returned array will be a mixture of PropertyChangeListeners
|
||||
* and <code>PropertyChangeListenerProxy</code>s. If the calling
|
||||
* method is interested in distinguishing the listeners then it must
|
||||
* test each element to see if it's a
|
||||
* <code>PropertyChangeListenerProxy</code>, perform the cast, and examine
|
||||
* the parameter.
|
||||
*
|
||||
* <pre>{@code
|
||||
* PropertyChangeListener[] listeners = bean.getPropertyChangeListeners();
|
||||
* for (int i = 0; i < listeners.length; i++) {
|
||||
* if (listeners[i] instanceof PropertyChangeListenerProxy) {
|
||||
* PropertyChangeListenerProxy proxy =
|
||||
* (PropertyChangeListenerProxy)listeners[i];
|
||||
* if (proxy.getPropertyName().equals("foo")) {
|
||||
* // proxy is a PropertyChangeListener which was associated
|
||||
* // with the property named "foo"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @see PropertyChangeListenerProxy
|
||||
* @return all of the <code>PropertyChangeListeners</code> added or an
|
||||
* empty array if no listeners have been added
|
||||
* @since 1.4
|
||||
*/
|
||||
public PropertyChangeListener[] getPropertyChangeListeners() {
|
||||
return this.map.getListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a PropertyChangeListener for a specific property. The listener
|
||||
* will be invoked only when a call on firePropertyChange names that
|
||||
* specific property.
|
||||
* The same listener object may be added more than once. For each
|
||||
* property, the listener will be invoked the number of times it was added
|
||||
* for that property.
|
||||
* If <code>propertyName</code> or <code>listener</code> is null, no
|
||||
* exception is thrown and no action is taken.
|
||||
*
|
||||
* @param propertyName The name of the property to listen on.
|
||||
* @param listener The PropertyChangeListener to be added
|
||||
*/
|
||||
public void addPropertyChangeListener(
|
||||
String propertyName,
|
||||
PropertyChangeListener listener) {
|
||||
if (listener == null || propertyName == null) {
|
||||
return;
|
||||
}
|
||||
listener = this.map.extract(listener);
|
||||
if (listener != null) {
|
||||
this.map.add(propertyName, listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a PropertyChangeListener for a specific property.
|
||||
* If <code>listener</code> was added more than once to the same event
|
||||
* source for the specified property, it will be notified one less time
|
||||
* after being removed.
|
||||
* If <code>propertyName</code> is null, no exception is thrown and no
|
||||
* action is taken.
|
||||
* If <code>listener</code> is null, or was never added for the specified
|
||||
* property, no exception is thrown and no action is taken.
|
||||
*
|
||||
* @param propertyName The name of the property that was listened on.
|
||||
* @param listener The PropertyChangeListener to be removed
|
||||
*/
|
||||
public void removePropertyChangeListener(
|
||||
String propertyName,
|
||||
PropertyChangeListener listener) {
|
||||
if (listener == null || propertyName == null) {
|
||||
return;
|
||||
}
|
||||
listener = this.map.extract(listener);
|
||||
if (listener != null) {
|
||||
this.map.remove(propertyName, listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all the listeners which have been associated
|
||||
* with the named property.
|
||||
*
|
||||
* @param propertyName The name of the property being listened to
|
||||
* @return all of the <code>PropertyChangeListeners</code> associated with
|
||||
* the named property. If no such listeners have been added,
|
||||
* or if <code>propertyName</code> is null, an empty array is
|
||||
* returned.
|
||||
* @since 1.4
|
||||
*/
|
||||
public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
|
||||
return this.map.getListeners(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports a bound property update to listeners
|
||||
* that have been registered to track updates of
|
||||
* all properties or a property with the specified name.
|
||||
* <p>
|
||||
* No event is fired if old and new values are equal and non-null.
|
||||
* <p>
|
||||
* This is merely a convenience wrapper around the more general
|
||||
* {@link #firePropertyChange(PropertyChangeEvent)} method.
|
||||
*
|
||||
* @param propertyName the programmatic name of the property that was changed
|
||||
* @param oldValue the old value of the property
|
||||
* @param newValue the new value of the property
|
||||
*/
|
||||
public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
|
||||
if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
|
||||
firePropertyChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports an integer bound property update to listeners
|
||||
* that have been registered to track updates of
|
||||
* all properties or a property with the specified name.
|
||||
* <p>
|
||||
* No event is fired if old and new values are equal.
|
||||
* <p>
|
||||
* This is merely a convenience wrapper around the more general
|
||||
* {@link #firePropertyChange(String, Object, Object)} method.
|
||||
*
|
||||
* @param propertyName the programmatic name of the property that was changed
|
||||
* @param oldValue the old value of the property
|
||||
* @param newValue the new value of the property
|
||||
*/
|
||||
public void firePropertyChange(String propertyName, int oldValue, int newValue) {
|
||||
if (oldValue != newValue) {
|
||||
firePropertyChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports a boolean bound property update to listeners
|
||||
* that have been registered to track updates of
|
||||
* all properties or a property with the specified name.
|
||||
* <p>
|
||||
* No event is fired if old and new values are equal.
|
||||
* <p>
|
||||
* This is merely a convenience wrapper around the more general
|
||||
* {@link #firePropertyChange(String, Object, Object)} method.
|
||||
*
|
||||
* @param propertyName the programmatic name of the property that was changed
|
||||
* @param oldValue the old value of the property
|
||||
* @param newValue the new value of the property
|
||||
*/
|
||||
public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
|
||||
if (oldValue != newValue) {
|
||||
firePropertyChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires a property change event to listeners
|
||||
* that have been registered to track updates of
|
||||
* all properties or a property with the specified name.
|
||||
* <p>
|
||||
* No event is fired if the given event's old and new values are equal and non-null.
|
||||
*
|
||||
* @param event the {@code PropertyChangeEvent} to be fired
|
||||
*/
|
||||
public void firePropertyChange(PropertyChangeEvent event) {
|
||||
Object oldValue = event.getOldValue();
|
||||
Object newValue = event.getNewValue();
|
||||
if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
|
||||
String name = event.getPropertyName();
|
||||
|
||||
PropertyChangeListener[] common = this.map.get(null);
|
||||
PropertyChangeListener[] named = (name != null)
|
||||
? this.map.get(name)
|
||||
: null;
|
||||
|
||||
fire(common, event);
|
||||
fire(named, event);
|
||||
}
|
||||
}
|
||||
|
||||
private static void fire(PropertyChangeListener[] listeners, PropertyChangeEvent event) {
|
||||
if (listeners != null) {
|
||||
for (PropertyChangeListener listener : listeners) {
|
||||
listener.propertyChange(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports a bound indexed property update to listeners
|
||||
* that have been registered to track updates of
|
||||
* all properties or a property with the specified name.
|
||||
* <p>
|
||||
* No event is fired if old and new values are equal and non-null.
|
||||
* <p>
|
||||
* This is merely a convenience wrapper around the more general
|
||||
* {@link #firePropertyChange(PropertyChangeEvent)} method.
|
||||
*
|
||||
* @param propertyName the programmatic name of the property that was changed
|
||||
* @param index the index of the property element that was changed
|
||||
* @param oldValue the old value of the property
|
||||
* @param newValue the new value of the property
|
||||
* @since 1.5
|
||||
*/
|
||||
public void fireIndexedPropertyChange(String propertyName, int index, Object oldValue, Object newValue) {
|
||||
if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
|
||||
firePropertyChange(new IndexedPropertyChangeEvent(source, propertyName, oldValue, newValue, index));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports an integer bound indexed property update to listeners
|
||||
* that have been registered to track updates of
|
||||
* all properties or a property with the specified name.
|
||||
* <p>
|
||||
* No event is fired if old and new values are equal.
|
||||
* <p>
|
||||
* This is merely a convenience wrapper around the more general
|
||||
* {@link #fireIndexedPropertyChange(String, int, Object, Object)} method.
|
||||
*
|
||||
* @param propertyName the programmatic name of the property that was changed
|
||||
* @param index the index of the property element that was changed
|
||||
* @param oldValue the old value of the property
|
||||
* @param newValue the new value of the property
|
||||
* @since 1.5
|
||||
*/
|
||||
public void fireIndexedPropertyChange(String propertyName, int index, int oldValue, int newValue) {
|
||||
if (oldValue != newValue) {
|
||||
fireIndexedPropertyChange(propertyName, index, Integer.valueOf(oldValue), Integer.valueOf(newValue));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports a boolean bound indexed property update to listeners
|
||||
* that have been registered to track updates of
|
||||
* all properties or a property with the specified name.
|
||||
* <p>
|
||||
* No event is fired if old and new values are equal.
|
||||
* <p>
|
||||
* This is merely a convenience wrapper around the more general
|
||||
* {@link #fireIndexedPropertyChange(String, int, Object, Object)} method.
|
||||
*
|
||||
* @param propertyName the programmatic name of the property that was changed
|
||||
* @param index the index of the property element that was changed
|
||||
* @param oldValue the old value of the property
|
||||
* @param newValue the new value of the property
|
||||
* @since 1.5
|
||||
*/
|
||||
public void fireIndexedPropertyChange(String propertyName, int index, boolean oldValue, boolean newValue) {
|
||||
if (oldValue != newValue) {
|
||||
fireIndexedPropertyChange(propertyName, index, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there are any listeners for a specific property, including
|
||||
* those registered on all properties. If <code>propertyName</code>
|
||||
* is null, only check for listeners registered on all properties.
|
||||
*
|
||||
* @param propertyName the property name.
|
||||
* @return true if there are one or more listeners for the given property
|
||||
*/
|
||||
public boolean hasListeners(String propertyName) {
|
||||
return this.map.hasListeners(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @serialData Null terminated list of <code>PropertyChangeListeners</code>.
|
||||
* <p>
|
||||
* At serialization time we skip non-serializable listeners and
|
||||
* only serialize the serializable listeners.
|
||||
*/
|
||||
private void writeObject(ObjectOutputStream s) throws IOException {
|
||||
Hashtable<String, PropertyChangeSupport> children = null;
|
||||
PropertyChangeListener[] listeners = null;
|
||||
synchronized (this.map) {
|
||||
for (Entry<String, PropertyChangeListener[]> entry : this.map.getEntries()) {
|
||||
String property = entry.getKey();
|
||||
if (property == null) {
|
||||
listeners = entry.getValue();
|
||||
} else {
|
||||
if (children == null) {
|
||||
children = new Hashtable<>();
|
||||
}
|
||||
PropertyChangeSupport pcs = new PropertyChangeSupport(this.source);
|
||||
pcs.map.set(null, entry.getValue());
|
||||
children.put(property, pcs);
|
||||
}
|
||||
}
|
||||
}
|
||||
ObjectOutputStream.PutField fields = s.putFields();
|
||||
fields.put("children", children);
|
||||
fields.put("source", this.source);
|
||||
fields.put("propertyChangeSupportSerializedDataVersion", 2);
|
||||
s.writeFields();
|
||||
|
||||
if (listeners != null) {
|
||||
for (PropertyChangeListener l : listeners) {
|
||||
if (l instanceof Serializable) {
|
||||
s.writeObject(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
s.writeObject(null);
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
|
||||
this.map = new PropertyChangeListenerMap();
|
||||
|
||||
ObjectInputStream.GetField fields = s.readFields();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Hashtable<String, PropertyChangeSupport> children = (Hashtable<String, PropertyChangeSupport>) fields.get("children", null);
|
||||
this.source = fields.get("source", null);
|
||||
fields.get("propertyChangeSupportSerializedDataVersion", 2);
|
||||
|
||||
Object listenerOrNull;
|
||||
while (null != (listenerOrNull = s.readObject())) {
|
||||
this.map.add(null, (PropertyChangeListener)listenerOrNull);
|
||||
}
|
||||
if (children != null) {
|
||||
for (Entry<String, PropertyChangeSupport> entry : children.entrySet()) {
|
||||
for (PropertyChangeListener listener : entry.getValue().getPropertyChangeListeners()) {
|
||||
this.map.add(entry.getKey(), listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The object to be provided as the "source" for any generated events.
|
||||
*/
|
||||
private Object source;
|
||||
|
||||
/**
|
||||
* @serialField children Hashtable
|
||||
* @serialField source Object
|
||||
* @serialField propertyChangeSupportSerializedDataVersion int
|
||||
*/
|
||||
private static final ObjectStreamField[] serialPersistentFields = {
|
||||
new ObjectStreamField("children", Hashtable.class),
|
||||
new ObjectStreamField("source", Object.class),
|
||||
new ObjectStreamField("propertyChangeSupportSerializedDataVersion", Integer.TYPE)
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialization version ID, so we're compatible with JDK 1.1
|
||||
*/
|
||||
static final long serialVersionUID = 6401253773779951803L;
|
||||
|
||||
/**
|
||||
* This is a {@link ChangeListenerMap ChangeListenerMap} implementation
|
||||
* that works with {@link PropertyChangeListener PropertyChangeListener} objects.
|
||||
*/
|
||||
private static final class PropertyChangeListenerMap extends ChangeListenerMap<PropertyChangeListener> {
|
||||
private static final PropertyChangeListener[] EMPTY = {};
|
||||
|
||||
/**
|
||||
* Creates an array of {@link PropertyChangeListener PropertyChangeListener} objects.
|
||||
* This method uses the same instance of the empty array
|
||||
* when {@code length} equals {@code 0}.
|
||||
*
|
||||
* @param length the array length
|
||||
* @return an array with specified length
|
||||
*/
|
||||
@Override
|
||||
protected PropertyChangeListener[] newArray(int length) {
|
||||
return (0 < length)
|
||||
? new PropertyChangeListener[length]
|
||||
: EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link PropertyChangeListenerProxy PropertyChangeListenerProxy}
|
||||
* object for the specified property.
|
||||
*
|
||||
* @param name the name of the property to listen on
|
||||
* @param listener the listener to process events
|
||||
* @return a {@code PropertyChangeListenerProxy} object
|
||||
*/
|
||||
@Override
|
||||
protected PropertyChangeListener newProxy(String name, PropertyChangeListener listener) {
|
||||
return new PropertyChangeListenerProxy(name, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public final PropertyChangeListener extract(PropertyChangeListener listener) {
|
||||
while (listener instanceof PropertyChangeListenerProxy) {
|
||||
listener = ((PropertyChangeListenerProxy) listener).getListener();
|
||||
}
|
||||
return listener;
|
||||
}
|
||||
}
|
||||
}
|
||||
750
jdkSrc/jdk8/java/beans/PropertyDescriptor.java
Normal file
750
jdkSrc/jdk8/java/beans/PropertyDescriptor.java
Normal file
@@ -0,0 +1,750 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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.ref.Reference;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Constructor;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
* A PropertyDescriptor describes one property that a Java Bean
|
||||
* exports via a pair of accessor methods.
|
||||
*/
|
||||
public class PropertyDescriptor extends FeatureDescriptor {
|
||||
|
||||
private Reference<? extends Class<?>> propertyTypeRef;
|
||||
private final MethodRef readMethodRef = new MethodRef();
|
||||
private final MethodRef writeMethodRef = new MethodRef();
|
||||
private Reference<? extends Class<?>> propertyEditorClassRef;
|
||||
|
||||
private boolean bound;
|
||||
private boolean constrained;
|
||||
|
||||
// The base name of the method name which will be prefixed with the
|
||||
// read and write method. If name == "foo" then the baseName is "Foo"
|
||||
private String baseName;
|
||||
|
||||
private String writeMethodName;
|
||||
private String readMethodName;
|
||||
|
||||
/**
|
||||
* Constructs a PropertyDescriptor for a property that follows
|
||||
* the standard Java convention by having getFoo and setFoo
|
||||
* accessor methods. Thus if the argument name is "fred", it will
|
||||
* assume that the writer method is "setFred" and the reader method
|
||||
* is "getFred" (or "isFred" for a boolean property). Note that the
|
||||
* property name should start with a lower case character, which will
|
||||
* be capitalized in the method names.
|
||||
*
|
||||
* @param propertyName The programmatic name of the property.
|
||||
* @param beanClass The Class object for the target bean. For
|
||||
* example sun.beans.OurButton.class.
|
||||
* @exception IntrospectionException if an exception occurs during
|
||||
* introspection.
|
||||
*/
|
||||
public PropertyDescriptor(String propertyName, Class<?> beanClass)
|
||||
throws IntrospectionException {
|
||||
this(propertyName, beanClass,
|
||||
Introspector.IS_PREFIX + NameGenerator.capitalize(propertyName),
|
||||
Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName));
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor takes the name of a simple property, and method
|
||||
* names for reading and writing the property.
|
||||
*
|
||||
* @param propertyName The programmatic name of the property.
|
||||
* @param beanClass The Class object for the target bean. For
|
||||
* example sun.beans.OurButton.class.
|
||||
* @param readMethodName The name of the method used for reading the property
|
||||
* value. May be null if the property is write-only.
|
||||
* @param writeMethodName The name of the method used for writing the property
|
||||
* value. May be null if the property is read-only.
|
||||
* @exception IntrospectionException if an exception occurs during
|
||||
* introspection.
|
||||
*/
|
||||
public PropertyDescriptor(String propertyName, Class<?> beanClass,
|
||||
String readMethodName, String writeMethodName)
|
||||
throws IntrospectionException {
|
||||
if (beanClass == null) {
|
||||
throw new IntrospectionException("Target Bean class is null");
|
||||
}
|
||||
if (propertyName == null || propertyName.length() == 0) {
|
||||
throw new IntrospectionException("bad property name");
|
||||
}
|
||||
if ("".equals(readMethodName) || "".equals(writeMethodName)) {
|
||||
throw new IntrospectionException("read or write method name should not be the empty string");
|
||||
}
|
||||
setName(propertyName);
|
||||
setClass0(beanClass);
|
||||
|
||||
this.readMethodName = readMethodName;
|
||||
if (readMethodName != null && getReadMethod() == null) {
|
||||
throw new IntrospectionException("Method not found: " + readMethodName);
|
||||
}
|
||||
this.writeMethodName = writeMethodName;
|
||||
if (writeMethodName != null && getWriteMethod() == null) {
|
||||
throw new IntrospectionException("Method not found: " + writeMethodName);
|
||||
}
|
||||
// If this class or one of its base classes allow PropertyChangeListener,
|
||||
// then we assume that any properties we discover are "bound".
|
||||
// See Introspector.getTargetPropertyInfo() method.
|
||||
Class[] args = { PropertyChangeListener.class };
|
||||
this.bound = null != Introspector.findMethod(beanClass, "addPropertyChangeListener", args.length, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor takes the name of a simple property, and Method
|
||||
* objects for reading and writing the property.
|
||||
*
|
||||
* @param propertyName The programmatic name of the property.
|
||||
* @param readMethod The method used for reading the property value.
|
||||
* May be null if the property is write-only.
|
||||
* @param writeMethod The method used for writing the property value.
|
||||
* May be null if the property is read-only.
|
||||
* @exception IntrospectionException if an exception occurs during
|
||||
* introspection.
|
||||
*/
|
||||
public PropertyDescriptor(String propertyName, Method readMethod, Method writeMethod)
|
||||
throws IntrospectionException {
|
||||
if (propertyName == null || propertyName.length() == 0) {
|
||||
throw new IntrospectionException("bad property name");
|
||||
}
|
||||
setName(propertyName);
|
||||
setReadMethod(readMethod);
|
||||
setWriteMethod(writeMethod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates <code>PropertyDescriptor</code> for the specified bean
|
||||
* with the specified name and methods to read/write the property value.
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
PropertyDescriptor(Class<?> bean, String base, Method read, Method write) throws IntrospectionException {
|
||||
if (bean == null) {
|
||||
throw new IntrospectionException("Target Bean class is null");
|
||||
}
|
||||
setClass0(bean);
|
||||
setName(Introspector.decapitalize(base));
|
||||
setReadMethod(read);
|
||||
setWriteMethod(write);
|
||||
this.baseName = base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Java type info for the property.
|
||||
* Note that the {@code Class} object may describe
|
||||
* primitive Java types such as {@code int}.
|
||||
* This type is returned by the read method
|
||||
* or is used as the parameter type of the write method.
|
||||
* Returns {@code null} if the type is an indexed property
|
||||
* that does not support non-indexed access.
|
||||
*
|
||||
* @return the {@code Class} object that represents the Java type info,
|
||||
* or {@code null} if the type cannot be determined
|
||||
*/
|
||||
public synchronized Class<?> getPropertyType() {
|
||||
Class<?> type = getPropertyType0();
|
||||
if (type == null) {
|
||||
try {
|
||||
type = findPropertyType(getReadMethod(), getWriteMethod());
|
||||
setPropertyType(type);
|
||||
} catch (IntrospectionException ex) {
|
||||
// Fall
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private void setPropertyType(Class<?> type) {
|
||||
this.propertyTypeRef = getWeakReference(type);
|
||||
}
|
||||
|
||||
private Class<?> getPropertyType0() {
|
||||
return (this.propertyTypeRef != null)
|
||||
? this.propertyTypeRef.get()
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the method that should be used to read the property value.
|
||||
*
|
||||
* @return The method that should be used to read the property value.
|
||||
* May return null if the property can't be read.
|
||||
*/
|
||||
public synchronized Method getReadMethod() {
|
||||
Method readMethod = this.readMethodRef.get();
|
||||
if (readMethod == null) {
|
||||
Class<?> cls = getClass0();
|
||||
if (cls == null || (readMethodName == null && !this.readMethodRef.isSet())) {
|
||||
// The read method was explicitly set to null.
|
||||
return null;
|
||||
}
|
||||
String nextMethodName = Introspector.GET_PREFIX + getBaseName();
|
||||
if (readMethodName == null) {
|
||||
Class<?> type = getPropertyType0();
|
||||
if (type == boolean.class || type == null) {
|
||||
readMethodName = Introspector.IS_PREFIX + getBaseName();
|
||||
} else {
|
||||
readMethodName = nextMethodName;
|
||||
}
|
||||
}
|
||||
|
||||
// Since there can be multiple write methods but only one getter
|
||||
// method, find the getter method first so that you know what the
|
||||
// property type is. For booleans, there can be "is" and "get"
|
||||
// methods. If an "is" method exists, this is the official
|
||||
// reader method so look for this one first.
|
||||
readMethod = Introspector.findMethod(cls, readMethodName, 0);
|
||||
if ((readMethod == null) && !readMethodName.equals(nextMethodName)) {
|
||||
readMethodName = nextMethodName;
|
||||
readMethod = Introspector.findMethod(cls, readMethodName, 0);
|
||||
}
|
||||
try {
|
||||
setReadMethod(readMethod);
|
||||
} catch (IntrospectionException ex) {
|
||||
// fall
|
||||
}
|
||||
}
|
||||
return readMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the method that should be used to read the property value.
|
||||
*
|
||||
* @param readMethod The new read method.
|
||||
* @throws IntrospectionException if the read method is invalid
|
||||
*/
|
||||
public synchronized void setReadMethod(Method readMethod)
|
||||
throws IntrospectionException {
|
||||
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();
|
||||
setTransient(readMethod.getAnnotation(Transient.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the method that should be used to write the property value.
|
||||
*
|
||||
* @return The method that should be used to write the property value.
|
||||
* May return null if the property can't be written.
|
||||
*/
|
||||
public synchronized Method getWriteMethod() {
|
||||
Method writeMethod = this.writeMethodRef.get();
|
||||
if (writeMethod == null) {
|
||||
Class<?> cls = getClass0();
|
||||
if (cls == null || (writeMethodName == null && !this.writeMethodRef.isSet())) {
|
||||
// The write method was explicitly set to null.
|
||||
return null;
|
||||
}
|
||||
|
||||
// We need the type to fetch the correct method.
|
||||
Class<?> type = getPropertyType0();
|
||||
if (type == null) {
|
||||
try {
|
||||
// Can't use getPropertyType since it will lead to recursive loop.
|
||||
type = findPropertyType(getReadMethod(), null);
|
||||
setPropertyType(type);
|
||||
} catch (IntrospectionException ex) {
|
||||
// Without the correct property type we can't be guaranteed
|
||||
// to find the correct method.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (writeMethodName == null) {
|
||||
writeMethodName = Introspector.SET_PREFIX + getBaseName();
|
||||
}
|
||||
|
||||
Class<?>[] args = (type == null) ? null : new Class<?>[] { type };
|
||||
writeMethod = Introspector.findMethod(cls, writeMethodName, 1, args);
|
||||
if (writeMethod != null) {
|
||||
if (!writeMethod.getReturnType().equals(void.class)) {
|
||||
writeMethod = null;
|
||||
}
|
||||
}
|
||||
try {
|
||||
setWriteMethod(writeMethod);
|
||||
} catch (IntrospectionException ex) {
|
||||
// fall through
|
||||
}
|
||||
}
|
||||
return writeMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the method that should be used to write the property value.
|
||||
*
|
||||
* @param writeMethod The new write method.
|
||||
* @throws IntrospectionException if the write method is invalid
|
||||
*/
|
||||
public synchronized void setWriteMethod(Method writeMethod)
|
||||
throws IntrospectionException {
|
||||
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();
|
||||
setTransient(writeMethod.getAnnotation(Transient.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden to ensure that a super class doesn't take precedent
|
||||
*/
|
||||
void setClass0(Class<?> clz) {
|
||||
if (getClass0() != null && clz.isAssignableFrom(getClass0())) {
|
||||
// don't replace a subclass with a superclass
|
||||
return;
|
||||
}
|
||||
super.setClass0(clz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates to "bound" properties will cause a "PropertyChange" event to
|
||||
* get fired when the property is changed.
|
||||
*
|
||||
* @return True if this is a bound property.
|
||||
*/
|
||||
public boolean isBound() {
|
||||
return bound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates to "bound" properties will cause a "PropertyChange" event to
|
||||
* get fired when the property is changed.
|
||||
*
|
||||
* @param bound True if this is a bound property.
|
||||
*/
|
||||
public void setBound(boolean bound) {
|
||||
this.bound = bound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempted updates to "Constrained" properties will cause a "VetoableChange"
|
||||
* event to get fired when the property is changed.
|
||||
*
|
||||
* @return True if this is a constrained property.
|
||||
*/
|
||||
public boolean isConstrained() {
|
||||
return constrained;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempted updates to "Constrained" properties will cause a "VetoableChange"
|
||||
* event to get fired when the property is changed.
|
||||
*
|
||||
* @param constrained True if this is a constrained property.
|
||||
*/
|
||||
public void setConstrained(boolean constrained) {
|
||||
this.constrained = constrained;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Normally PropertyEditors will be found using the PropertyEditorManager.
|
||||
* However if for some reason you want to associate a particular
|
||||
* PropertyEditor with a given property, then you can do it with
|
||||
* this method.
|
||||
*
|
||||
* @param propertyEditorClass The Class for the desired PropertyEditor.
|
||||
*/
|
||||
public void setPropertyEditorClass(Class<?> propertyEditorClass) {
|
||||
this.propertyEditorClassRef = getWeakReference(propertyEditorClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets any explicit PropertyEditor Class that has been registered
|
||||
* for this property.
|
||||
*
|
||||
* @return Any explicit PropertyEditor Class that has been registered
|
||||
* for this property. Normally this will return "null",
|
||||
* indicating that no special editor has been registered,
|
||||
* so the PropertyEditorManager should be used to locate
|
||||
* a suitable PropertyEditor.
|
||||
*/
|
||||
public Class<?> getPropertyEditorClass() {
|
||||
return (this.propertyEditorClassRef != null)
|
||||
? this.propertyEditorClassRef.get()
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of a property editor using the current
|
||||
* property editor class.
|
||||
* <p>
|
||||
* If the property editor class has a public constructor that takes an
|
||||
* Object argument then it will be invoked using the bean parameter
|
||||
* as the argument. Otherwise, the default constructor will be invoked.
|
||||
*
|
||||
* @param bean the source object
|
||||
* @return a property editor instance or null if a property editor has
|
||||
* not been defined or cannot be created
|
||||
* @since 1.5
|
||||
*/
|
||||
public PropertyEditor createPropertyEditor(Object bean) {
|
||||
Object editor = null;
|
||||
|
||||
final Class<?> cls = getPropertyEditorClass();
|
||||
if (cls != null && PropertyEditor.class.isAssignableFrom(cls)
|
||||
&& ReflectUtil.isPackageAccessible(cls)) {
|
||||
Constructor<?> ctor = null;
|
||||
if (bean != null) {
|
||||
try {
|
||||
ctor = cls.getConstructor(new Class<?>[] { Object.class });
|
||||
} catch (Exception ex) {
|
||||
// Fall through
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (ctor == null) {
|
||||
editor = cls.newInstance();
|
||||
} else {
|
||||
editor = ctor.newInstance(new Object[] { bean });
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// Fall through
|
||||
}
|
||||
}
|
||||
return (PropertyEditor)editor;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares this <code>PropertyDescriptor</code> against the specified object.
|
||||
* Returns true if the objects are the same. Two <code>PropertyDescriptor</code>s
|
||||
* are the same if the read, write, property types, property editor and
|
||||
* flags are equivalent.
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj != null && obj instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor other = (PropertyDescriptor)obj;
|
||||
Method otherReadMethod = other.getReadMethod();
|
||||
Method otherWriteMethod = other.getWriteMethod();
|
||||
|
||||
if (!compareMethods(getReadMethod(), otherReadMethod)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!compareMethods(getWriteMethod(), otherWriteMethod)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getPropertyType() == other.getPropertyType() &&
|
||||
getPropertyEditorClass() == other.getPropertyEditorClass() &&
|
||||
bound == other.isBound() && constrained == other.isConstrained() &&
|
||||
writeMethodName == other.writeMethodName &&
|
||||
readMethodName == other.readMethodName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Package private helper method for Descriptor .equals methods.
|
||||
*
|
||||
* @param a first method to compare
|
||||
* @param b second method to compare
|
||||
* @return boolean to indicate that the methods are equivalent
|
||||
*/
|
||||
boolean compareMethods(Method a, Method b) {
|
||||
// Note: perhaps this should be a protected method in FeatureDescriptor
|
||||
if ((a == null) != (b == null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a != null && b != null) {
|
||||
if (!a.equals(b)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Package-private constructor.
|
||||
* Merge two property descriptors. Where they conflict, give the
|
||||
* second argument (y) priority over the first argument (x).
|
||||
*
|
||||
* @param x The first (lower priority) PropertyDescriptor
|
||||
* @param y The second (higher priority) PropertyDescriptor
|
||||
*/
|
||||
PropertyDescriptor(PropertyDescriptor x, PropertyDescriptor y) {
|
||||
super(x,y);
|
||||
|
||||
if (y.baseName != null) {
|
||||
baseName = y.baseName;
|
||||
} else {
|
||||
baseName = x.baseName;
|
||||
}
|
||||
|
||||
if (y.readMethodName != null) {
|
||||
readMethodName = y.readMethodName;
|
||||
} else {
|
||||
readMethodName = x.readMethodName;
|
||||
}
|
||||
|
||||
if (y.writeMethodName != null) {
|
||||
writeMethodName = y.writeMethodName;
|
||||
} else {
|
||||
writeMethodName = x.writeMethodName;
|
||||
}
|
||||
|
||||
if (y.propertyTypeRef != null) {
|
||||
propertyTypeRef = y.propertyTypeRef;
|
||||
} else {
|
||||
propertyTypeRef = x.propertyTypeRef;
|
||||
}
|
||||
|
||||
// Figure out the merged read method.
|
||||
Method xr = x.getReadMethod();
|
||||
Method yr = y.getReadMethod();
|
||||
|
||||
// Normally give priority to y's readMethod.
|
||||
try {
|
||||
if (isAssignable(xr, yr)) {
|
||||
setReadMethod(yr);
|
||||
} else {
|
||||
setReadMethod(xr);
|
||||
}
|
||||
} catch (IntrospectionException ex) {
|
||||
// fall through
|
||||
}
|
||||
|
||||
// However, if both x and y reference read methods in the same class,
|
||||
// give priority to a boolean "is" method over a boolean "get" method.
|
||||
if (xr != null && yr != null &&
|
||||
xr.getDeclaringClass() == yr.getDeclaringClass() &&
|
||||
getReturnType(getClass0(), xr) == boolean.class &&
|
||||
getReturnType(getClass0(), yr) == boolean.class &&
|
||||
xr.getName().indexOf(Introspector.IS_PREFIX) == 0 &&
|
||||
yr.getName().indexOf(Introspector.GET_PREFIX) == 0) {
|
||||
try {
|
||||
setReadMethod(xr);
|
||||
} catch (IntrospectionException ex) {
|
||||
// fall through
|
||||
}
|
||||
}
|
||||
|
||||
Method xw = x.getWriteMethod();
|
||||
Method yw = y.getWriteMethod();
|
||||
|
||||
try {
|
||||
if (yw != null) {
|
||||
setWriteMethod(yw);
|
||||
} else {
|
||||
setWriteMethod(xw);
|
||||
}
|
||||
} catch (IntrospectionException ex) {
|
||||
// Fall through
|
||||
}
|
||||
|
||||
if (y.getPropertyEditorClass() != null) {
|
||||
setPropertyEditorClass(y.getPropertyEditorClass());
|
||||
} else {
|
||||
setPropertyEditorClass(x.getPropertyEditorClass());
|
||||
}
|
||||
|
||||
|
||||
bound = x.bound | y.bound;
|
||||
constrained = x.constrained | y.constrained;
|
||||
}
|
||||
|
||||
/*
|
||||
* Package-private dup constructor.
|
||||
* This must isolate the new object from any changes to the old object.
|
||||
*/
|
||||
PropertyDescriptor(PropertyDescriptor old) {
|
||||
super(old);
|
||||
propertyTypeRef = old.propertyTypeRef;
|
||||
this.readMethodRef.set(old.readMethodRef.get());
|
||||
this.writeMethodRef.set(old.writeMethodRef.get());
|
||||
propertyEditorClassRef = old.propertyEditorClassRef;
|
||||
|
||||
writeMethodName = old.writeMethodName;
|
||||
readMethodName = old.readMethodName;
|
||||
baseName = old.baseName;
|
||||
|
||||
bound = old.bound;
|
||||
constrained = old.constrained;
|
||||
}
|
||||
|
||||
void updateGenericsFor(Class<?> type) {
|
||||
setClass0(type);
|
||||
try {
|
||||
setPropertyType(findPropertyType(this.readMethodRef.get(), this.writeMethodRef.get()));
|
||||
}
|
||||
catch (IntrospectionException exception) {
|
||||
setPropertyType(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property type that corresponds to the read and write method.
|
||||
* The type precedence is given to the readMethod.
|
||||
*
|
||||
* @return the type of the property descriptor or null if both
|
||||
* read and write methods are null.
|
||||
* @throws IntrospectionException if the read or write method is invalid
|
||||
*/
|
||||
private Class<?> findPropertyType(Method readMethod, Method writeMethod)
|
||||
throws IntrospectionException {
|
||||
Class<?> propertyType = null;
|
||||
try {
|
||||
if (readMethod != null) {
|
||||
Class<?>[] params = getParameterTypes(getClass0(), readMethod);
|
||||
if (params.length != 0) {
|
||||
throw new IntrospectionException("bad read method arg count: "
|
||||
+ readMethod);
|
||||
}
|
||||
propertyType = getReturnType(getClass0(), readMethod);
|
||||
if (propertyType == Void.TYPE) {
|
||||
throw new IntrospectionException("read method " +
|
||||
readMethod.getName() + " returns void");
|
||||
}
|
||||
}
|
||||
if (writeMethod != null) {
|
||||
Class<?>[] params = getParameterTypes(getClass0(), writeMethod);
|
||||
if (params.length != 1) {
|
||||
throw new IntrospectionException("bad write method arg count: "
|
||||
+ writeMethod);
|
||||
}
|
||||
if (propertyType != null && !params[0].isAssignableFrom(propertyType)) {
|
||||
throw new IntrospectionException("type mismatch between read and write methods");
|
||||
}
|
||||
propertyType = params[0];
|
||||
}
|
||||
} catch (IntrospectionException ex) {
|
||||
throw ex;
|
||||
}
|
||||
return propertyType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a hash code value for the object.
|
||||
* See {@link java.lang.Object#hashCode} for a complete description.
|
||||
*
|
||||
* @return a hash code value for this object.
|
||||
* @since 1.5
|
||||
*/
|
||||
public int hashCode() {
|
||||
int result = 7;
|
||||
|
||||
result = 37 * result + ((getPropertyType() == null) ? 0 :
|
||||
getPropertyType().hashCode());
|
||||
result = 37 * result + ((getReadMethod() == null) ? 0 :
|
||||
getReadMethod().hashCode());
|
||||
result = 37 * result + ((getWriteMethod() == null) ? 0 :
|
||||
getWriteMethod().hashCode());
|
||||
result = 37 * result + ((getPropertyEditorClass() == null) ? 0 :
|
||||
getPropertyEditorClass().hashCode());
|
||||
result = 37 * result + ((writeMethodName == null) ? 0 :
|
||||
writeMethodName.hashCode());
|
||||
result = 37 * result + ((readMethodName == null) ? 0 :
|
||||
readMethodName.hashCode());
|
||||
result = 37 * result + getName().hashCode();
|
||||
result = 37 * result + ((bound == false) ? 0 : 1);
|
||||
result = 37 * result + ((constrained == false) ? 0 : 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculate once since capitalize() is expensive.
|
||||
String getBaseName() {
|
||||
if (baseName == null) {
|
||||
baseName = NameGenerator.capitalize(getName());
|
||||
}
|
||||
return baseName;
|
||||
}
|
||||
|
||||
void appendTo(StringBuilder sb) {
|
||||
appendTo(sb, "bound", this.bound);
|
||||
appendTo(sb, "constrained", this.constrained);
|
||||
appendTo(sb, "propertyEditorClass", this.propertyEditorClassRef);
|
||||
appendTo(sb, "propertyType", this.propertyTypeRef);
|
||||
appendTo(sb, "readMethod", this.readMethodRef.get());
|
||||
appendTo(sb, "writeMethod", this.writeMethodRef.get());
|
||||
}
|
||||
|
||||
boolean isAssignable(Method m1, Method m2) {
|
||||
if (m1 == null) {
|
||||
return true; // choose second method
|
||||
}
|
||||
if (m2 == null) {
|
||||
return false; // choose first method
|
||||
}
|
||||
if (!m1.getName().equals(m2.getName())) {
|
||||
return true; // choose second method by default
|
||||
}
|
||||
Class<?> type1 = m1.getDeclaringClass();
|
||||
Class<?> type2 = m2.getDeclaringClass();
|
||||
if (!type1.isAssignableFrom(type2)) {
|
||||
return false; // choose first method: it declared later
|
||||
}
|
||||
type1 = getReturnType(getClass0(), m1);
|
||||
type2 = getReturnType(getClass0(), m2);
|
||||
if (!type1.isAssignableFrom(type2)) {
|
||||
return false; // choose first method: it overrides return type
|
||||
}
|
||||
Class<?>[] args1 = getParameterTypes(getClass0(), m1);
|
||||
Class<?>[] args2 = getParameterTypes(getClass0(), m2);
|
||||
if (args1.length != args2.length) {
|
||||
return true; // choose second method by default
|
||||
}
|
||||
for (int i = 0; i < args1.length; i++) {
|
||||
if (!args1[i].isAssignableFrom(args2[i])) {
|
||||
return false; // choose first method: it overrides parameter
|
||||
}
|
||||
}
|
||||
return true; // choose second method
|
||||
}
|
||||
}
|
||||
225
jdkSrc/jdk8/java/beans/PropertyEditor.java
Normal file
225
jdkSrc/jdk8/java/beans/PropertyEditor.java
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2003, 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;
|
||||
|
||||
/**
|
||||
* A PropertyEditor class provides support for GUIs that want to
|
||||
* allow users to edit a property value of a given type.
|
||||
* <p>
|
||||
* PropertyEditor supports a variety of different kinds of ways of
|
||||
* displaying and updating property values. Most PropertyEditors will
|
||||
* only need to support a subset of the different options available in
|
||||
* this API.
|
||||
* <P>
|
||||
* Simple PropertyEditors may only support the getAsText and setAsText
|
||||
* methods and need not support (say) paintValue or getCustomEditor. More
|
||||
* complex types may be unable to support getAsText and setAsText but will
|
||||
* instead support paintValue and getCustomEditor.
|
||||
* <p>
|
||||
* Every propertyEditor must support one or more of the three simple
|
||||
* display styles. Thus it can either (1) support isPaintable or (2)
|
||||
* both return a non-null String[] from getTags() and return a non-null
|
||||
* value from getAsText or (3) simply return a non-null String from
|
||||
* getAsText().
|
||||
* <p>
|
||||
* Every property editor must support a call on setValue when the argument
|
||||
* object is of the type for which this is the corresponding propertyEditor.
|
||||
* In addition, each property editor must either support a custom editor,
|
||||
* or support setAsText.
|
||||
* <p>
|
||||
* Each PropertyEditor should have a null constructor.
|
||||
*/
|
||||
|
||||
public interface PropertyEditor {
|
||||
|
||||
/**
|
||||
* Set (or change) the object that is to be edited. Primitive types such
|
||||
* as "int" must be wrapped as the corresponding object type such as
|
||||
* "java.lang.Integer".
|
||||
*
|
||||
* @param value The new target object to be edited. Note that this
|
||||
* object should not be modified by the PropertyEditor, rather
|
||||
* the PropertyEditor should create a new object to hold any
|
||||
* modified value.
|
||||
*/
|
||||
void setValue(Object value);
|
||||
|
||||
/**
|
||||
* Gets the property value.
|
||||
*
|
||||
* @return The value of the property. Primitive types such as "int" will
|
||||
* be wrapped as the corresponding object type such as "java.lang.Integer".
|
||||
*/
|
||||
|
||||
Object getValue();
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Determines whether this property editor is paintable.
|
||||
*
|
||||
* @return True if the class will honor the paintValue method.
|
||||
*/
|
||||
|
||||
boolean isPaintable();
|
||||
|
||||
/**
|
||||
* Paint a representation of the value into a given area of screen
|
||||
* real estate. Note that the propertyEditor is responsible for doing
|
||||
* its own clipping so that it fits into the given rectangle.
|
||||
* <p>
|
||||
* If the PropertyEditor doesn't honor paint requests (see isPaintable)
|
||||
* this method should be a silent noop.
|
||||
* <p>
|
||||
* The given Graphics object will have the default font, color, etc of
|
||||
* the parent container. The PropertyEditor may change graphics attributes
|
||||
* such as font and color and doesn't need to restore the old values.
|
||||
*
|
||||
* @param gfx Graphics object to paint into.
|
||||
* @param box Rectangle within graphics object into which we should paint.
|
||||
*/
|
||||
void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns a fragment of Java code that can be used to set a property
|
||||
* to match the editors current state. This method is intended
|
||||
* for use when generating Java code to reflect changes made through the
|
||||
* property editor.
|
||||
* <p>
|
||||
* The code fragment should be context free and must be a legal Java
|
||||
* expression as specified by the JLS.
|
||||
* <p>
|
||||
* Specifically, if the expression represents a computation then all
|
||||
* classes and static members should be fully qualified. This rule
|
||||
* applies to constructors, static methods and non primitive arguments.
|
||||
* <p>
|
||||
* Caution should be used when evaluating the expression as it may throw
|
||||
* exceptions. In particular, code generators must ensure that generated
|
||||
* code will compile in the presence of an expression that can throw
|
||||
* checked exceptions.
|
||||
* <p>
|
||||
* Example results are:
|
||||
* <ul>
|
||||
* <li>Primitive expresssion: <code>2</code>
|
||||
* <li>Class constructor: <code>new java.awt.Color(127,127,34)</code>
|
||||
* <li>Static field: <code>java.awt.Color.orange</code>
|
||||
* <li>Static method: <code>javax.swing.Box.createRigidArea(new
|
||||
* java.awt.Dimension(0, 5))</code>
|
||||
* </ul>
|
||||
*
|
||||
* @return a fragment of Java code representing an initializer for the
|
||||
* current value. It should not contain a semi-colon
|
||||
* ('<code>;</code>') to end the expression.
|
||||
*/
|
||||
String getJavaInitializationString();
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Gets the property value as text.
|
||||
*
|
||||
* @return The property value as a human editable string.
|
||||
* <p> Returns null if the value can't be expressed as an editable string.
|
||||
* <p> If a non-null value is returned, then the PropertyEditor should
|
||||
* be prepared to parse that string back in setAsText().
|
||||
*/
|
||||
String getAsText();
|
||||
|
||||
/**
|
||||
* Set the property value by parsing a given String. May raise
|
||||
* java.lang.IllegalArgumentException if either the String is
|
||||
* badly formatted or if this kind of property can't be expressed
|
||||
* as text.
|
||||
* @param text The string to be parsed.
|
||||
*/
|
||||
void setAsText(String text) throws java.lang.IllegalArgumentException;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* If the property value must be one of a set of known tagged values,
|
||||
* then this method should return an array of the tags. This can
|
||||
* be used to represent (for example) enum values. If a PropertyEditor
|
||||
* supports tags, then it should support the use of setAsText with
|
||||
* a tag value as a way of setting the value and the use of getAsText
|
||||
* to identify the current value.
|
||||
*
|
||||
* @return The tag values for this property. May be null if this
|
||||
* property cannot be represented as a tagged value.
|
||||
*
|
||||
*/
|
||||
String[] getTags();
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A PropertyEditor may choose to make available a full custom Component
|
||||
* that edits its property value. It is the responsibility of the
|
||||
* PropertyEditor to hook itself up to its editor Component itself and
|
||||
* to report property value changes by firing a PropertyChange event.
|
||||
* <P>
|
||||
* The higher-level code that calls getCustomEditor may either embed
|
||||
* the Component in some larger property sheet, or it may put it in
|
||||
* its own individual dialog, or ...
|
||||
*
|
||||
* @return A java.awt.Component that will allow a human to directly
|
||||
* edit the current property value. May be null if this is
|
||||
* not supported.
|
||||
*/
|
||||
|
||||
java.awt.Component getCustomEditor();
|
||||
|
||||
/**
|
||||
* Determines whether this property editor supports a custom editor.
|
||||
*
|
||||
* @return True if the propertyEditor can provide a custom editor.
|
||||
*/
|
||||
boolean supportsCustomEditor();
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Adds a listener for the value change.
|
||||
* When the property editor changes its value
|
||||
* it should fire a {@link PropertyChangeEvent}
|
||||
* on all registered {@link PropertyChangeListener}s,
|
||||
* specifying the {@code null} value for the property name
|
||||
* and itself as the source.
|
||||
*
|
||||
* @param listener the {@link PropertyChangeListener} to add
|
||||
*/
|
||||
void addPropertyChangeListener(PropertyChangeListener listener);
|
||||
|
||||
/**
|
||||
* Removes a listener for the value change.
|
||||
*
|
||||
* @param listener the {@link PropertyChangeListener} to remove
|
||||
*/
|
||||
void removePropertyChangeListener(PropertyChangeListener listener);
|
||||
|
||||
}
|
||||
125
jdkSrc/jdk8/java/beans/PropertyEditorManager.java
Normal file
125
jdkSrc/jdk8/java/beans/PropertyEditorManager.java
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2011, 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;
|
||||
|
||||
/**
|
||||
* The PropertyEditorManager can be used to locate a property editor for
|
||||
* any given type name. This property editor must support the
|
||||
* java.beans.PropertyEditor interface for editing a given object.
|
||||
* <P>
|
||||
* The PropertyEditorManager uses three techniques for locating an editor
|
||||
* for a given type. First, it provides a registerEditor method to allow
|
||||
* an editor to be specifically registered for a given type. Second it
|
||||
* tries to locate a suitable class by adding "Editor" to the full
|
||||
* qualified classname of the given type (e.g. "foo.bah.FozEditor").
|
||||
* Finally it takes the simple classname (without the package name) adds
|
||||
* "Editor" to it and looks in a search-path of packages for a matching
|
||||
* class.
|
||||
* <P>
|
||||
* So for an input class foo.bah.Fred, the PropertyEditorManager would
|
||||
* first look in its tables to see if an editor had been registered for
|
||||
* foo.bah.Fred and if so use that. Then it will look for a
|
||||
* foo.bah.FredEditor class. Then it will look for (say)
|
||||
* standardEditorsPackage.FredEditor class.
|
||||
* <p>
|
||||
* Default PropertyEditors will be provided for the Java primitive types
|
||||
* "boolean", "byte", "short", "int", "long", "float", and "double"; and
|
||||
* for the classes java.lang.String. java.awt.Color, and java.awt.Font.
|
||||
*/
|
||||
|
||||
public class PropertyEditorManager {
|
||||
|
||||
/**
|
||||
* Registers an editor class to edit values of the given target class.
|
||||
* If the editor class is {@code null},
|
||||
* then any existing definition will be removed.
|
||||
* Thus this method can be used to cancel the registration.
|
||||
* The registration is canceled automatically
|
||||
* if either the target or editor class is unloaded.
|
||||
* <p>
|
||||
* If there is a security manager, its {@code checkPropertiesAccess}
|
||||
* method is called. This could result in a {@linkplain SecurityException}.
|
||||
*
|
||||
* @param targetType the class object of the type to be edited
|
||||
* @param editorClass the class object of the editor class
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* its {@code checkPropertiesAccess} method
|
||||
* doesn't allow setting of system properties
|
||||
*
|
||||
* @see SecurityManager#checkPropertiesAccess
|
||||
*/
|
||||
public static void registerEditor(Class<?> targetType, Class<?> editorClass) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPropertiesAccess();
|
||||
}
|
||||
ThreadGroupContext.getContext().getPropertyEditorFinder().register(targetType, editorClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate a value editor for a given target type.
|
||||
*
|
||||
* @param targetType The Class object for the type to be edited
|
||||
* @return An editor object for the given target class.
|
||||
* The result is null if no suitable editor can be found.
|
||||
*/
|
||||
public static PropertyEditor findEditor(Class<?> targetType) {
|
||||
return ThreadGroupContext.getContext().getPropertyEditorFinder().find(targetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the package names that will be searched for property editors.
|
||||
*
|
||||
* @return The array of package names that will be searched in
|
||||
* order to find property editors.
|
||||
* <p> The default value for this array is implementation-dependent,
|
||||
* e.g. Sun implementation initially sets to {"sun.beans.editors"}.
|
||||
*/
|
||||
public static String[] getEditorSearchPath() {
|
||||
return ThreadGroupContext.getContext().getPropertyEditorFinder().getPackages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the list of package names that will be used for
|
||||
* finding property editors.
|
||||
*
|
||||
* <p>First, if there is a security manager, its <code>checkPropertiesAccess</code>
|
||||
* method is called. This could result in a SecurityException.
|
||||
*
|
||||
* @param path Array of package names.
|
||||
* @exception SecurityException if a security manager exists and its
|
||||
* <code>checkPropertiesAccess</code> method doesn't allow setting
|
||||
* of system properties.
|
||||
* @see SecurityManager#checkPropertiesAccess
|
||||
*/
|
||||
public static void setEditorSearchPath(String[] path) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPropertiesAccess();
|
||||
}
|
||||
ThreadGroupContext.getContext().getPropertyEditorFinder().setPackages(path);
|
||||
}
|
||||
}
|
||||
307
jdkSrc/jdk8/java/beans/PropertyEditorSupport.java
Normal file
307
jdkSrc/jdk8/java/beans/PropertyEditorSupport.java
Normal file
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2013, 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.beans.*;
|
||||
|
||||
/**
|
||||
* This is a support class to help build property editors.
|
||||
* <p>
|
||||
* It can be used either as a base class or as a delegate.
|
||||
*/
|
||||
|
||||
public class PropertyEditorSupport implements PropertyEditor {
|
||||
|
||||
/**
|
||||
* Constructs a <code>PropertyEditorSupport</code> object.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public PropertyEditorSupport() {
|
||||
setSource(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a <code>PropertyEditorSupport</code> object.
|
||||
*
|
||||
* @param source the source used for event firing
|
||||
* @since 1.5
|
||||
*/
|
||||
public PropertyEditorSupport(Object source) {
|
||||
if (source == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
setSource(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bean that is used as the
|
||||
* source of events. If the source has not
|
||||
* been explicitly set then this instance of
|
||||
* <code>PropertyEditorSupport</code> is returned.
|
||||
*
|
||||
* @return the source object or this instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public Object getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the source bean.
|
||||
* <p>
|
||||
* The source bean is used as the source of events
|
||||
* for the property changes. This source should be used for information
|
||||
* purposes only and should not be modified by the PropertyEditor.
|
||||
*
|
||||
* @param source source object to be used for events
|
||||
* @since 1.5
|
||||
*/
|
||||
public void setSource(Object source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set (or change) the object that is to be edited.
|
||||
*
|
||||
* @param value The new target object to be edited. Note that this
|
||||
* object should not be modified by the PropertyEditor, rather
|
||||
* the PropertyEditor should create a new object to hold any
|
||||
* modified value.
|
||||
*/
|
||||
public void setValue(Object value) {
|
||||
this.value = value;
|
||||
firePropertyChange();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the property.
|
||||
*
|
||||
* @return The value of the property.
|
||||
*/
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Determines whether the class will honor the paintValue method.
|
||||
*
|
||||
* @return True if the class will honor the paintValue method.
|
||||
*/
|
||||
|
||||
public boolean isPaintable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Paint a representation of the value into a given area of screen
|
||||
* real estate. Note that the propertyEditor is responsible for doing
|
||||
* its own clipping so that it fits into the given rectangle.
|
||||
* <p>
|
||||
* If the PropertyEditor doesn't honor paint requests (see isPaintable)
|
||||
* this method should be a silent noop.
|
||||
*
|
||||
* @param gfx Graphics object to paint into.
|
||||
* @param box Rectangle within graphics object into which we should paint.
|
||||
*/
|
||||
public void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box) {
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* This method is intended for use when generating Java code to set
|
||||
* the value of the property. It should return a fragment of Java code
|
||||
* that can be used to initialize a variable with the current property
|
||||
* value.
|
||||
* <p>
|
||||
* Example results are "2", "new Color(127,127,34)", "Color.orange", etc.
|
||||
*
|
||||
* @return A fragment of Java code representing an initializer for the
|
||||
* current value.
|
||||
*/
|
||||
public String getJavaInitializationString() {
|
||||
return "???";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Gets the property value as a string suitable for presentation
|
||||
* to a human to edit.
|
||||
*
|
||||
* @return The property value as a string suitable for presentation
|
||||
* to a human to edit.
|
||||
* <p> Returns null if the value can't be expressed as a string.
|
||||
* <p> If a non-null value is returned, then the PropertyEditor should
|
||||
* be prepared to parse that string back in setAsText().
|
||||
*/
|
||||
public String getAsText() {
|
||||
return (this.value != null)
|
||||
? this.value.toString()
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the property value by parsing a given String. May raise
|
||||
* java.lang.IllegalArgumentException if either the String is
|
||||
* badly formatted or if this kind of property can't be expressed
|
||||
* as text.
|
||||
*
|
||||
* @param text The string to be parsed.
|
||||
*/
|
||||
public void setAsText(String text) throws java.lang.IllegalArgumentException {
|
||||
if (value instanceof String) {
|
||||
setValue(text);
|
||||
return;
|
||||
}
|
||||
throw new java.lang.IllegalArgumentException(text);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* If the property value must be one of a set of known tagged values,
|
||||
* then this method should return an array of the tag values. This can
|
||||
* be used to represent (for example) enum values. If a PropertyEditor
|
||||
* supports tags, then it should support the use of setAsText with
|
||||
* a tag value as a way of setting the value.
|
||||
*
|
||||
* @return The tag values for this property. May be null if this
|
||||
* property cannot be represented as a tagged value.
|
||||
*
|
||||
*/
|
||||
public String[] getTags() {
|
||||
return null;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A PropertyEditor may chose to make available a full custom Component
|
||||
* that edits its property value. It is the responsibility of the
|
||||
* PropertyEditor to hook itself up to its editor Component itself and
|
||||
* to report property value changes by firing a PropertyChange event.
|
||||
* <P>
|
||||
* The higher-level code that calls getCustomEditor may either embed
|
||||
* the Component in some larger property sheet, or it may put it in
|
||||
* its own individual dialog, or ...
|
||||
*
|
||||
* @return A java.awt.Component that will allow a human to directly
|
||||
* edit the current property value. May be null if this is
|
||||
* not supported.
|
||||
*/
|
||||
|
||||
public java.awt.Component getCustomEditor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the propertyEditor can provide a custom editor.
|
||||
*
|
||||
* @return True if the propertyEditor can provide a custom editor.
|
||||
*/
|
||||
public boolean supportsCustomEditor() {
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Adds a listener for the value change.
|
||||
* When the property editor changes its value
|
||||
* it should fire a {@link PropertyChangeEvent}
|
||||
* on all registered {@link PropertyChangeListener}s,
|
||||
* specifying the {@code null} value for the property name.
|
||||
* If the source property is set,
|
||||
* it should be used as the source of the event.
|
||||
* <p>
|
||||
* The same listener object may be added more than once,
|
||||
* and will be called as many times as it is added.
|
||||
* If {@code listener} is {@code null},
|
||||
* no exception is thrown and no action is taken.
|
||||
*
|
||||
* @param listener the {@link PropertyChangeListener} to add
|
||||
*/
|
||||
public synchronized void addPropertyChangeListener(
|
||||
PropertyChangeListener listener) {
|
||||
if (listeners == null) {
|
||||
listeners = new java.util.Vector<>();
|
||||
}
|
||||
listeners.addElement(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener for the value change.
|
||||
* <p>
|
||||
* If the same listener was added more than once,
|
||||
* it will be notified one less time after being removed.
|
||||
* If {@code listener} is {@code null}, or was never added,
|
||||
* no exception is thrown and no action is taken.
|
||||
*
|
||||
* @param listener the {@link PropertyChangeListener} to remove
|
||||
*/
|
||||
public synchronized void removePropertyChangeListener(
|
||||
PropertyChangeListener listener) {
|
||||
if (listeners == null) {
|
||||
return;
|
||||
}
|
||||
listeners.removeElement(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report that we have been modified to any interested listeners.
|
||||
*/
|
||||
public void firePropertyChange() {
|
||||
java.util.Vector<PropertyChangeListener> targets;
|
||||
synchronized (this) {
|
||||
if (listeners == null) {
|
||||
return;
|
||||
}
|
||||
targets = unsafeClone(listeners);
|
||||
}
|
||||
// Tell our listeners that "everything" has changed.
|
||||
PropertyChangeEvent evt = new PropertyChangeEvent(source, null, null, null);
|
||||
|
||||
for (int i = 0; i < targets.size(); i++) {
|
||||
PropertyChangeListener target = targets.elementAt(i);
|
||||
target.propertyChange(evt);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> java.util.Vector<T> unsafeClone(java.util.Vector<T> v) {
|
||||
return (java.util.Vector<T>)v.clone();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
private Object value;
|
||||
private Object source;
|
||||
private java.util.Vector<PropertyChangeListener> listeners;
|
||||
}
|
||||
64
jdkSrc/jdk8/java/beans/PropertyVetoException.java
Normal file
64
jdkSrc/jdk8/java/beans/PropertyVetoException.java
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2009, 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;
|
||||
|
||||
|
||||
/**
|
||||
* A PropertyVetoException is thrown when a proposed change to a
|
||||
* property represents an unacceptable value.
|
||||
*/
|
||||
|
||||
public
|
||||
class PropertyVetoException extends Exception {
|
||||
private static final long serialVersionUID = 129596057694162164L;
|
||||
|
||||
/**
|
||||
* Constructs a <code>PropertyVetoException</code> with a
|
||||
* detailed message.
|
||||
*
|
||||
* @param mess Descriptive message
|
||||
* @param evt A PropertyChangeEvent describing the vetoed change.
|
||||
*/
|
||||
public PropertyVetoException(String mess, PropertyChangeEvent evt) {
|
||||
super(mess);
|
||||
this.evt = evt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the vetoed <code>PropertyChangeEvent</code>.
|
||||
*
|
||||
* @return A PropertyChangeEvent describing the vetoed change.
|
||||
*/
|
||||
public PropertyChangeEvent getPropertyChangeEvent() {
|
||||
return evt;
|
||||
}
|
||||
|
||||
/**
|
||||
* A PropertyChangeEvent describing the vetoed change.
|
||||
* @serial
|
||||
*/
|
||||
private PropertyChangeEvent evt;
|
||||
}
|
||||
135
jdkSrc/jdk8/java/beans/SimpleBeanInfo.java
Normal file
135
jdkSrc/jdk8/java/beans/SimpleBeanInfo.java
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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.awt.Image;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.image.ImageProducer;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* This is a support class to make it easier for people to provide
|
||||
* BeanInfo classes.
|
||||
* <p>
|
||||
* It defaults to providing "noop" information, and can be selectively
|
||||
* overriden to provide more explicit information on chosen topics.
|
||||
* When the introspector sees the "noop" values, it will apply low
|
||||
* level introspection and design patterns to automatically analyze
|
||||
* the target bean.
|
||||
*/
|
||||
|
||||
public class SimpleBeanInfo implements BeanInfo {
|
||||
|
||||
/**
|
||||
* Deny knowledge about the class and customizer of the bean.
|
||||
* You can override this if you wish to provide explicit info.
|
||||
*/
|
||||
public BeanDescriptor getBeanDescriptor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deny knowledge of properties. You can override this
|
||||
* if you wish to provide explicit property info.
|
||||
*/
|
||||
public PropertyDescriptor[] getPropertyDescriptors() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deny knowledge of a default property. You can override this
|
||||
* if you wish to define a default property for the bean.
|
||||
*/
|
||||
public int getDefaultPropertyIndex() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deny knowledge of event sets. You can override this
|
||||
* if you wish to provide explicit event set info.
|
||||
*/
|
||||
public EventSetDescriptor[] getEventSetDescriptors() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deny knowledge of a default event. You can override this
|
||||
* if you wish to define a default event for the bean.
|
||||
*/
|
||||
public int getDefaultEventIndex() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deny knowledge of methods. You can override this
|
||||
* if you wish to provide explicit method info.
|
||||
*/
|
||||
public MethodDescriptor[] getMethodDescriptors() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Claim there are no other relevant BeanInfo objects. You
|
||||
* may override this if you want to (for example) return a
|
||||
* BeanInfo for a base class.
|
||||
*/
|
||||
public BeanInfo[] getAdditionalBeanInfo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Claim there are no icons available. You can override
|
||||
* this if you want to provide icons for your bean.
|
||||
*/
|
||||
public Image getIcon(int iconKind) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a utility method to help in loading icon images.
|
||||
* It takes the name of a resource file associated with the
|
||||
* current object's class file and loads an image object
|
||||
* from that file. Typically images will be GIFs.
|
||||
* <p>
|
||||
* @param resourceName A pathname relative to the directory
|
||||
* holding the class file of the current class. For example,
|
||||
* "wombat.gif".
|
||||
* @return an image object. May be null if the load failed.
|
||||
*/
|
||||
public Image loadImage(final String resourceName) {
|
||||
try {
|
||||
final URL url = getClass().getResource(resourceName);
|
||||
if (url != null) {
|
||||
final ImageProducer ip = (ImageProducer) url.getContent();
|
||||
if (ip != null) {
|
||||
return Toolkit.getDefaultToolkit().createImage(ip);
|
||||
}
|
||||
}
|
||||
} catch (final Exception ignored) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
363
jdkSrc/jdk8/java/beans/Statement.java
Normal file
363
jdkSrc/jdk8/java/beans/Statement.java
Normal file
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, 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.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
|
||||
import com.sun.beans.finder.ClassFinder;
|
||||
import com.sun.beans.finder.ConstructorFinder;
|
||||
import com.sun.beans.finder.MethodFinder;
|
||||
import sun.reflect.misc.MethodUtil;
|
||||
|
||||
/**
|
||||
* A <code>Statement</code> object represents a primitive statement
|
||||
* in which a single method is applied to a target and
|
||||
* a set of arguments - as in <code>"a.setFoo(b)"</code>.
|
||||
* Note that where this example uses names
|
||||
* to denote the target and its argument, a statement
|
||||
* object does not require a name space and is constructed with
|
||||
* the values themselves.
|
||||
* The statement object associates the named method
|
||||
* with its environment as a simple set of values:
|
||||
* the target and an array of argument values.
|
||||
*
|
||||
* @since 1.4
|
||||
*
|
||||
* @author Philip Milne
|
||||
*/
|
||||
public class Statement {
|
||||
|
||||
private static Object[] emptyArray = new Object[]{};
|
||||
|
||||
static ExceptionListener defaultExceptionListener = new ExceptionListener() {
|
||||
public void exceptionThrown(Exception e) {
|
||||
System.err.println(e);
|
||||
// e.printStackTrace();
|
||||
System.err.println("Continuing ...");
|
||||
}
|
||||
};
|
||||
|
||||
private final AccessControlContext acc = AccessController.getContext();
|
||||
private final Object target;
|
||||
private final String methodName;
|
||||
private final Object[] arguments;
|
||||
ClassLoader loader;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Statement} object
|
||||
* for the specified target object to invoke the method
|
||||
* specified by the name and by the array of arguments.
|
||||
* <p>
|
||||
* The {@code target} and the {@code methodName} values should not be {@code null}.
|
||||
* Otherwise an attempt to execute this {@code Expression}
|
||||
* will result in a {@code NullPointerException}.
|
||||
* If the {@code arguments} value is {@code null},
|
||||
* an empty array is used as the value of the {@code arguments} property.
|
||||
*
|
||||
* @param target the target object of this statement
|
||||
* @param methodName the name of the method to invoke on the specified target
|
||||
* @param arguments the array of arguments to invoke the specified method
|
||||
*/
|
||||
@ConstructorProperties({"target", "methodName", "arguments"})
|
||||
public Statement(Object target, String methodName, Object[] arguments) {
|
||||
this.target = target;
|
||||
this.methodName = methodName;
|
||||
this.arguments = (arguments == null) ? emptyArray : arguments.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target object of this statement.
|
||||
* If this method returns {@code null},
|
||||
* the {@link #execute} method
|
||||
* throws a {@code NullPointerException}.
|
||||
*
|
||||
* @return the target object of this statement
|
||||
*/
|
||||
public Object getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the method to invoke.
|
||||
* If this method returns {@code null},
|
||||
* the {@link #execute} method
|
||||
* throws a {@code NullPointerException}.
|
||||
*
|
||||
* @return the name of the method
|
||||
*/
|
||||
public String getMethodName() {
|
||||
return methodName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the arguments for the method to invoke.
|
||||
* The number of arguments and their types
|
||||
* must match the method being called.
|
||||
* {@code null} can be used as a synonym of an empty array.
|
||||
*
|
||||
* @return the array of arguments
|
||||
*/
|
||||
public Object[] getArguments() {
|
||||
return this.arguments.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@code execute} method finds a method whose name is the same
|
||||
* as the {@code methodName} property, and invokes the method on
|
||||
* the target.
|
||||
*
|
||||
* When the target's class defines many methods with the given name
|
||||
* the implementation should choose the most specific method using
|
||||
* the algorithm specified in the Java Language Specification
|
||||
* (15.11). The dynamic class of the target and arguments are used
|
||||
* in place of the compile-time type information and, like the
|
||||
* {@link java.lang.reflect.Method} class itself, conversion between
|
||||
* primitive values and their associated wrapper classes is handled
|
||||
* internally.
|
||||
* <p>
|
||||
* The following method types are handled as special cases:
|
||||
* <ul>
|
||||
* <li>
|
||||
* Static methods may be called by using a class object as the target.
|
||||
* <li>
|
||||
* The reserved method name "new" may be used to call a class's constructor
|
||||
* as if all classes defined static "new" methods. Constructor invocations
|
||||
* are typically considered {@code Expression}s rather than {@code Statement}s
|
||||
* as they return a value.
|
||||
* <li>
|
||||
* The method names "get" and "set" defined in the {@link java.util.List}
|
||||
* interface may also be applied to array instances, mapping to
|
||||
* the static methods of the same name in the {@code Array} class.
|
||||
* </ul>
|
||||
*
|
||||
* @throws NullPointerException if the value of the {@code target} or
|
||||
* {@code methodName} property is {@code null}
|
||||
* @throws NoSuchMethodException if a matching method is not found
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* it denies the method invocation
|
||||
* @throws Exception that is thrown by the invoked method
|
||||
*
|
||||
* @see java.lang.reflect.Method
|
||||
*/
|
||||
public void execute() throws Exception {
|
||||
invoke();
|
||||
}
|
||||
|
||||
Object invoke() throws Exception {
|
||||
AccessControlContext acc = this.acc;
|
||||
if ((acc == null) && (System.getSecurityManager() != null)) {
|
||||
throw new SecurityException("AccessControlContext is not set");
|
||||
}
|
||||
try {
|
||||
return AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<Object>() {
|
||||
public Object run() throws Exception {
|
||||
return invokeInternal();
|
||||
}
|
||||
},
|
||||
acc
|
||||
);
|
||||
}
|
||||
catch (PrivilegedActionException exception) {
|
||||
throw exception.getException();
|
||||
}
|
||||
}
|
||||
|
||||
private Object invokeInternal() throws Exception {
|
||||
Object target = getTarget();
|
||||
String methodName = getMethodName();
|
||||
|
||||
if (target == null || methodName == null) {
|
||||
throw new NullPointerException((target == null ? "target" :
|
||||
"methodName") + " should not be null");
|
||||
}
|
||||
|
||||
Object[] arguments = getArguments();
|
||||
if (arguments == null) {
|
||||
arguments = emptyArray;
|
||||
}
|
||||
// Class.forName() won't load classes outside
|
||||
// of core from a class inside core. Special
|
||||
// case this method.
|
||||
if (target == Class.class && methodName.equals("forName")) {
|
||||
return ClassFinder.resolveClass((String)arguments[0], this.loader);
|
||||
}
|
||||
Class<?>[] argClasses = new Class<?>[arguments.length];
|
||||
for(int i = 0; i < arguments.length; i++) {
|
||||
argClasses[i] = (arguments[i] == null) ? null : arguments[i].getClass();
|
||||
}
|
||||
|
||||
AccessibleObject m = null;
|
||||
if (target instanceof Class) {
|
||||
/*
|
||||
For class methods, simluate the effect of a meta class
|
||||
by taking the union of the static methods of the
|
||||
actual class, with the instance methods of "Class.class"
|
||||
and the overloaded "newInstance" methods defined by the
|
||||
constructors.
|
||||
This way "System.class", for example, will perform both
|
||||
the static method getProperties() and the instance method
|
||||
getSuperclass() defined in "Class.class".
|
||||
*/
|
||||
if (methodName.equals("new")) {
|
||||
methodName = "newInstance";
|
||||
}
|
||||
// Provide a short form for array instantiation by faking an nary-constructor.
|
||||
if (methodName.equals("newInstance") && ((Class)target).isArray()) {
|
||||
Object result = Array.newInstance(((Class)target).getComponentType(), arguments.length);
|
||||
for(int i = 0; i < arguments.length; i++) {
|
||||
Array.set(result, i, arguments[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (methodName.equals("newInstance") && arguments.length != 0) {
|
||||
// The Character class, as of 1.4, does not have a constructor
|
||||
// which takes a String. All of the other "wrapper" classes
|
||||
// for Java's primitive types have a String constructor so we
|
||||
// fake such a constructor here so that this special case can be
|
||||
// ignored elsewhere.
|
||||
if (target == Character.class && arguments.length == 1 &&
|
||||
argClasses[0] == String.class) {
|
||||
return new Character(((String)arguments[0]).charAt(0));
|
||||
}
|
||||
try {
|
||||
m = ConstructorFinder.findConstructor((Class)target, argClasses);
|
||||
}
|
||||
catch (NoSuchMethodException exception) {
|
||||
m = null;
|
||||
}
|
||||
}
|
||||
if (m == null && target != Class.class) {
|
||||
m = getMethod((Class)target, methodName, argClasses);
|
||||
}
|
||||
if (m == null) {
|
||||
m = getMethod(Class.class, methodName, argClasses);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
This special casing of arrays is not necessary, but makes files
|
||||
involving arrays much shorter and simplifies the archiving infrastrcure.
|
||||
The Array.set() method introduces an unusual idea - that of a static method
|
||||
changing the state of an instance. Normally statements with side
|
||||
effects on objects are instance methods of the objects themselves
|
||||
and we reinstate this rule (perhaps temporarily) by special-casing arrays.
|
||||
*/
|
||||
if (target.getClass().isArray() &&
|
||||
(methodName.equals("set") || methodName.equals("get"))) {
|
||||
int index = ((Integer)arguments[0]).intValue();
|
||||
if (methodName.equals("get")) {
|
||||
return Array.get(target, index);
|
||||
}
|
||||
else {
|
||||
Array.set(target, index, arguments[1]);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
m = getMethod(target.getClass(), methodName, argClasses);
|
||||
}
|
||||
if (m != null) {
|
||||
try {
|
||||
if (m instanceof Method) {
|
||||
return MethodUtil.invoke((Method)m, target, arguments);
|
||||
}
|
||||
else {
|
||||
return ((Constructor)m).newInstance(arguments);
|
||||
}
|
||||
}
|
||||
catch (IllegalAccessException iae) {
|
||||
throw new Exception("Statement cannot invoke: " +
|
||||
methodName + " on " + target.getClass(),
|
||||
iae);
|
||||
}
|
||||
catch (InvocationTargetException ite) {
|
||||
Throwable te = ite.getTargetException();
|
||||
if (te instanceof Exception) {
|
||||
throw (Exception)te;
|
||||
}
|
||||
else {
|
||||
throw ite;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new NoSuchMethodException(toString());
|
||||
}
|
||||
|
||||
String instanceName(Object instance) {
|
||||
if (instance == null) {
|
||||
return "null";
|
||||
} else if (instance.getClass() == String.class) {
|
||||
return "\""+(String)instance + "\"";
|
||||
} else {
|
||||
// Note: there is a minor problem with using the non-caching
|
||||
// NameGenerator method. The return value will not have
|
||||
// specific information about the inner class name. For example,
|
||||
// In 1.4.2 an inner class would be represented as JList$1 now
|
||||
// would be named Class.
|
||||
|
||||
return NameGenerator.unqualifiedClassName(instance.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the value of this statement using a Java-style syntax.
|
||||
*/
|
||||
public String toString() {
|
||||
// Respect a subclass's implementation here.
|
||||
Object target = getTarget();
|
||||
String methodName = getMethodName();
|
||||
Object[] arguments = getArguments();
|
||||
if (arguments == null) {
|
||||
arguments = emptyArray;
|
||||
}
|
||||
StringBuffer result = new StringBuffer(instanceName(target) + "." + methodName + "(");
|
||||
int n = arguments.length;
|
||||
for(int i = 0; i < n; i++) {
|
||||
result.append(instanceName(arguments[i]));
|
||||
if (i != n -1) {
|
||||
result.append(", ");
|
||||
}
|
||||
}
|
||||
result.append(");");
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
static Method getMethod(Class<?> type, String name, Class<?>... args) {
|
||||
try {
|
||||
return MethodFinder.findMethod(type, name, args);
|
||||
}
|
||||
catch (NoSuchMethodException exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
130
jdkSrc/jdk8/java/beans/ThreadGroupContext.java
Normal file
130
jdkSrc/jdk8/java/beans/ThreadGroupContext.java
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2013, 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 com.sun.beans.finder.BeanInfoFinder;
|
||||
import com.sun.beans.finder.PropertyEditorFinder;
|
||||
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
/**
|
||||
* The {@code ThreadGroupContext} is an application-dependent
|
||||
* context referenced by the specific {@link ThreadGroup}.
|
||||
* This is a replacement for the {@link sun.awt.AppContext}.
|
||||
*
|
||||
* @author Sergey Malenkov
|
||||
*/
|
||||
final class ThreadGroupContext {
|
||||
|
||||
private static final WeakIdentityMap<ThreadGroupContext> contexts = new WeakIdentityMap<ThreadGroupContext>() {
|
||||
protected ThreadGroupContext create(Object key) {
|
||||
return new ThreadGroupContext();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the appropriate {@code ThreadGroupContext} for the caller,
|
||||
* as determined by its {@code ThreadGroup}.
|
||||
*
|
||||
* @return the application-dependent context
|
||||
*/
|
||||
static ThreadGroupContext getContext() {
|
||||
return contexts.get(Thread.currentThread().getThreadGroup());
|
||||
}
|
||||
|
||||
private volatile boolean isDesignTime;
|
||||
private volatile Boolean isGuiAvailable;
|
||||
|
||||
private Map<Class<?>, BeanInfo> beanInfoCache;
|
||||
private BeanInfoFinder beanInfoFinder;
|
||||
private PropertyEditorFinder propertyEditorFinder;
|
||||
|
||||
private ThreadGroupContext() {
|
||||
}
|
||||
|
||||
boolean isDesignTime() {
|
||||
return this.isDesignTime;
|
||||
}
|
||||
|
||||
void setDesignTime(boolean isDesignTime) {
|
||||
this.isDesignTime = isDesignTime;
|
||||
}
|
||||
|
||||
|
||||
boolean isGuiAvailable() {
|
||||
Boolean isGuiAvailable = this.isGuiAvailable;
|
||||
return (isGuiAvailable != null)
|
||||
? isGuiAvailable.booleanValue()
|
||||
: !GraphicsEnvironment.isHeadless();
|
||||
}
|
||||
|
||||
void setGuiAvailable(boolean isGuiAvailable) {
|
||||
this.isGuiAvailable = Boolean.valueOf(isGuiAvailable);
|
||||
}
|
||||
|
||||
|
||||
BeanInfo getBeanInfo(Class<?> type) {
|
||||
return (this.beanInfoCache != null)
|
||||
? this.beanInfoCache.get(type)
|
||||
: null;
|
||||
}
|
||||
|
||||
BeanInfo putBeanInfo(Class<?> type, BeanInfo info) {
|
||||
if (this.beanInfoCache == null) {
|
||||
this.beanInfoCache = new WeakHashMap<>();
|
||||
}
|
||||
return this.beanInfoCache.put(type, info);
|
||||
}
|
||||
|
||||
void removeBeanInfo(Class<?> type) {
|
||||
if (this.beanInfoCache != null) {
|
||||
this.beanInfoCache.remove(type);
|
||||
}
|
||||
}
|
||||
|
||||
void clearBeanInfoCache() {
|
||||
if (this.beanInfoCache != null) {
|
||||
this.beanInfoCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
synchronized BeanInfoFinder getBeanInfoFinder() {
|
||||
if (this.beanInfoFinder == null) {
|
||||
this.beanInfoFinder = new BeanInfoFinder();
|
||||
}
|
||||
return this.beanInfoFinder;
|
||||
}
|
||||
|
||||
synchronized PropertyEditorFinder getPropertyEditorFinder() {
|
||||
if (this.propertyEditorFinder == null) {
|
||||
this.propertyEditorFinder = new PropertyEditorFinder();
|
||||
}
|
||||
return this.propertyEditorFinder;
|
||||
}
|
||||
}
|
||||
74
jdkSrc/jdk8/java/beans/Transient.java
Normal file
74
jdkSrc/jdk8/java/beans/Transient.java
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2013, 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.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* Indicates that an attribute called "transient"
|
||||
* should be declared with the given {@code value}
|
||||
* when the {@link Introspector} constructs
|
||||
* a {@link PropertyDescriptor} or {@link EventSetDescriptor}
|
||||
* classes associated with the annotated code element.
|
||||
* A {@code true} value for the "transient" attribute
|
||||
* indicates to encoders derived from {@link Encoder}
|
||||
* that this feature should be ignored.
|
||||
* <p>
|
||||
* The {@code Transient} annotation may be be used
|
||||
* in any of the methods that are involved
|
||||
* in a {@link FeatureDescriptor} subclass
|
||||
* to identify the transient feature in the annotated class and its subclasses.
|
||||
* Normally, the method that starts with "get" is the best place
|
||||
* to put the annotation and it is this declaration
|
||||
* that takes precedence in the case of multiple annotations
|
||||
* being defined for the same feature.
|
||||
* <p>
|
||||
* To declare a feature non-transient in a class
|
||||
* whose superclass declares it transient,
|
||||
* use {@code @Transient(false)}.
|
||||
* In all cases, the {@link Introspector} decides
|
||||
* if a feature is transient by referring to the annotation
|
||||
* on the most specific superclass.
|
||||
* If no {@code Transient} annotation is present
|
||||
* in any superclass the feature is not transient.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
@Target({METHOD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Transient {
|
||||
/**
|
||||
* Returns whether or not the {@code Introspector} should
|
||||
* construct artifacts for the annotated method.
|
||||
* @return whether or not the {@code Introspector} should
|
||||
* construct artifacts for the annotated method
|
||||
*/
|
||||
boolean value() default true;
|
||||
}
|
||||
44
jdkSrc/jdk8/java/beans/VetoableChangeListener.java
Normal file
44
jdkSrc/jdk8/java/beans/VetoableChangeListener.java
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 1997, 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;
|
||||
|
||||
/**
|
||||
* A VetoableChange event gets fired whenever a bean changes a "constrained"
|
||||
* property. You can register a VetoableChangeListener with a source bean
|
||||
* so as to be notified of any constrained property updates.
|
||||
*/
|
||||
public interface VetoableChangeListener extends java.util.EventListener {
|
||||
/**
|
||||
* This method gets called when a constrained property is changed.
|
||||
*
|
||||
* @param evt a <code>PropertyChangeEvent</code> object describing the
|
||||
* event source and the property that has changed.
|
||||
* @exception PropertyVetoException if the recipient wishes the property
|
||||
* change to be rolled back.
|
||||
*/
|
||||
void vetoableChange(PropertyChangeEvent evt)
|
||||
throws PropertyVetoException;
|
||||
}
|
||||
84
jdkSrc/jdk8/java/beans/VetoableChangeListenerProxy.java
Normal file
84
jdkSrc/jdk8/java/beans/VetoableChangeListenerProxy.java
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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.util.EventListenerProxy;
|
||||
|
||||
/**
|
||||
* A class which extends the {@code EventListenerProxy}
|
||||
* specifically for adding a {@code VetoableChangeListener}
|
||||
* with a "constrained" property.
|
||||
* Instances of this class can be added
|
||||
* as {@code VetoableChangeListener}s to a bean
|
||||
* which supports firing vetoable change events.
|
||||
* <p>
|
||||
* If the object has a {@code getVetoableChangeListeners} method
|
||||
* then the array returned could be a mixture of {@code VetoableChangeListener}
|
||||
* and {@code VetoableChangeListenerProxy} objects.
|
||||
*
|
||||
* @see java.util.EventListenerProxy
|
||||
* @see VetoableChangeSupport#getVetoableChangeListeners
|
||||
* @since 1.4
|
||||
*/
|
||||
public class VetoableChangeListenerProxy
|
||||
extends EventListenerProxy<VetoableChangeListener>
|
||||
implements VetoableChangeListener {
|
||||
|
||||
private final String propertyName;
|
||||
|
||||
/**
|
||||
* Constructor which binds the {@code VetoableChangeListener}
|
||||
* to a specific property.
|
||||
*
|
||||
* @param propertyName the name of the property to listen on
|
||||
* @param listener the listener object
|
||||
*/
|
||||
public VetoableChangeListenerProxy(String propertyName, VetoableChangeListener listener) {
|
||||
super(listener);
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards the property change event to the listener delegate.
|
||||
*
|
||||
* @param event the property change event
|
||||
*
|
||||
* @exception PropertyVetoException if the recipient wishes the property
|
||||
* change to be rolled back
|
||||
*/
|
||||
public void vetoableChange(PropertyChangeEvent event) throws PropertyVetoException{
|
||||
getListener().vetoableChange(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the named property associated with the listener.
|
||||
*
|
||||
* @return the name of the named property associated with the listener
|
||||
*/
|
||||
public String getPropertyName() {
|
||||
return this.propertyName;
|
||||
}
|
||||
}
|
||||
536
jdkSrc/jdk8/java/beans/VetoableChangeSupport.java
Normal file
536
jdkSrc/jdk8/java/beans/VetoableChangeSupport.java
Normal file
@@ -0,0 +1,536 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2013, 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.io.Serializable;
|
||||
import java.io.ObjectStreamField;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* This is a utility class that can be used by beans that support constrained
|
||||
* properties. It manages a list of listeners and dispatches
|
||||
* {@link PropertyChangeEvent}s to them. You can use an instance of this class
|
||||
* as a member field of your bean and delegate these types of work to it.
|
||||
* The {@link VetoableChangeListener} can be registered for all properties
|
||||
* or for a property specified by name.
|
||||
* <p>
|
||||
* Here is an example of {@code VetoableChangeSupport} usage that follows
|
||||
* the rules and recommendations laid out in the JavaBeans™ specification:
|
||||
* <pre>{@code
|
||||
* public class MyBean {
|
||||
* private final VetoableChangeSupport vcs = new VetoableChangeSupport(this);
|
||||
*
|
||||
* public void addVetoableChangeListener(VetoableChangeListener listener) {
|
||||
* this.vcs.addVetoableChangeListener(listener);
|
||||
* }
|
||||
*
|
||||
* public void removeVetoableChangeListener(VetoableChangeListener listener) {
|
||||
* this.vcs.removeVetoableChangeListener(listener);
|
||||
* }
|
||||
*
|
||||
* private String value;
|
||||
*
|
||||
* public String getValue() {
|
||||
* return this.value;
|
||||
* }
|
||||
*
|
||||
* public void setValue(String newValue) throws PropertyVetoException {
|
||||
* String oldValue = this.value;
|
||||
* this.vcs.fireVetoableChange("value", oldValue, newValue);
|
||||
* this.value = newValue;
|
||||
* }
|
||||
*
|
||||
* [...]
|
||||
* }
|
||||
* }</pre>
|
||||
* <p>
|
||||
* A {@code VetoableChangeSupport} instance is thread-safe.
|
||||
* <p>
|
||||
* This class is serializable. When it is serialized it will save
|
||||
* (and restore) any listeners that are themselves serializable. Any
|
||||
* non-serializable listeners will be skipped during serialization.
|
||||
*
|
||||
* @see PropertyChangeSupport
|
||||
*/
|
||||
public class VetoableChangeSupport implements Serializable {
|
||||
private VetoableChangeListenerMap map = new VetoableChangeListenerMap();
|
||||
|
||||
/**
|
||||
* Constructs a <code>VetoableChangeSupport</code> object.
|
||||
*
|
||||
* @param sourceBean The bean to be given as the source for any events.
|
||||
*/
|
||||
public VetoableChangeSupport(Object sourceBean) {
|
||||
if (sourceBean == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
source = sourceBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a VetoableChangeListener to the listener list.
|
||||
* The listener is registered for all properties.
|
||||
* The same listener object may be added more than once, and will be called
|
||||
* as many times as it is added.
|
||||
* If <code>listener</code> is null, no exception is thrown and no action
|
||||
* is taken.
|
||||
*
|
||||
* @param listener The VetoableChangeListener to be added
|
||||
*/
|
||||
public void addVetoableChangeListener(VetoableChangeListener listener) {
|
||||
if (listener == null) {
|
||||
return;
|
||||
}
|
||||
if (listener instanceof VetoableChangeListenerProxy) {
|
||||
VetoableChangeListenerProxy proxy =
|
||||
(VetoableChangeListenerProxy)listener;
|
||||
// Call two argument add method.
|
||||
addVetoableChangeListener(proxy.getPropertyName(),
|
||||
proxy.getListener());
|
||||
} else {
|
||||
this.map.add(null, listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a VetoableChangeListener from the listener list.
|
||||
* This removes a VetoableChangeListener that was registered
|
||||
* for all properties.
|
||||
* If <code>listener</code> was added more than once to the same event
|
||||
* source, it will be notified one less time after being removed.
|
||||
* If <code>listener</code> is null, or was never added, no exception is
|
||||
* thrown and no action is taken.
|
||||
*
|
||||
* @param listener The VetoableChangeListener to be removed
|
||||
*/
|
||||
public void removeVetoableChangeListener(VetoableChangeListener listener) {
|
||||
if (listener == null) {
|
||||
return;
|
||||
}
|
||||
if (listener instanceof VetoableChangeListenerProxy) {
|
||||
VetoableChangeListenerProxy proxy =
|
||||
(VetoableChangeListenerProxy)listener;
|
||||
// Call two argument remove method.
|
||||
removeVetoableChangeListener(proxy.getPropertyName(),
|
||||
proxy.getListener());
|
||||
} else {
|
||||
this.map.remove(null, listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all the listeners that were added to the
|
||||
* VetoableChangeSupport object with addVetoableChangeListener().
|
||||
* <p>
|
||||
* If some listeners have been added with a named property, then
|
||||
* the returned array will be a mixture of VetoableChangeListeners
|
||||
* and <code>VetoableChangeListenerProxy</code>s. If the calling
|
||||
* method is interested in distinguishing the listeners then it must
|
||||
* test each element to see if it's a
|
||||
* <code>VetoableChangeListenerProxy</code>, perform the cast, and examine
|
||||
* the parameter.
|
||||
*
|
||||
* <pre>{@code
|
||||
* VetoableChangeListener[] listeners = bean.getVetoableChangeListeners();
|
||||
* for (int i = 0; i < listeners.length; i++) {
|
||||
* if (listeners[i] instanceof VetoableChangeListenerProxy) {
|
||||
* VetoableChangeListenerProxy proxy =
|
||||
* (VetoableChangeListenerProxy)listeners[i];
|
||||
* if (proxy.getPropertyName().equals("foo")) {
|
||||
* // proxy is a VetoableChangeListener which was associated
|
||||
* // with the property named "foo"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @see VetoableChangeListenerProxy
|
||||
* @return all of the <code>VetoableChangeListeners</code> added or an
|
||||
* empty array if no listeners have been added
|
||||
* @since 1.4
|
||||
*/
|
||||
public VetoableChangeListener[] getVetoableChangeListeners(){
|
||||
return this.map.getListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a VetoableChangeListener for a specific property. The listener
|
||||
* will be invoked only when a call on fireVetoableChange names that
|
||||
* specific property.
|
||||
* The same listener object may be added more than once. For each
|
||||
* property, the listener will be invoked the number of times it was added
|
||||
* for that property.
|
||||
* If <code>propertyName</code> or <code>listener</code> is null, no
|
||||
* exception is thrown and no action is taken.
|
||||
*
|
||||
* @param propertyName The name of the property to listen on.
|
||||
* @param listener The VetoableChangeListener to be added
|
||||
*/
|
||||
public void addVetoableChangeListener(
|
||||
String propertyName,
|
||||
VetoableChangeListener listener) {
|
||||
if (listener == null || propertyName == null) {
|
||||
return;
|
||||
}
|
||||
listener = this.map.extract(listener);
|
||||
if (listener != null) {
|
||||
this.map.add(propertyName, listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a VetoableChangeListener for a specific property.
|
||||
* If <code>listener</code> was added more than once to the same event
|
||||
* source for the specified property, it will be notified one less time
|
||||
* after being removed.
|
||||
* If <code>propertyName</code> is null, no exception is thrown and no
|
||||
* action is taken.
|
||||
* If <code>listener</code> is null, or was never added for the specified
|
||||
* property, no exception is thrown and no action is taken.
|
||||
*
|
||||
* @param propertyName The name of the property that was listened on.
|
||||
* @param listener The VetoableChangeListener to be removed
|
||||
*/
|
||||
public void removeVetoableChangeListener(
|
||||
String propertyName,
|
||||
VetoableChangeListener listener) {
|
||||
if (listener == null || propertyName == null) {
|
||||
return;
|
||||
}
|
||||
listener = this.map.extract(listener);
|
||||
if (listener != null) {
|
||||
this.map.remove(propertyName, listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all the listeners which have been associated
|
||||
* with the named property.
|
||||
*
|
||||
* @param propertyName The name of the property being listened to
|
||||
* @return all the <code>VetoableChangeListeners</code> associated with
|
||||
* the named property. If no such listeners have been added,
|
||||
* or if <code>propertyName</code> is null, an empty array is
|
||||
* returned.
|
||||
* @since 1.4
|
||||
*/
|
||||
public VetoableChangeListener[] getVetoableChangeListeners(String propertyName) {
|
||||
return this.map.getListeners(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports a constrained property update to listeners
|
||||
* that have been registered to track updates of
|
||||
* all properties or a property with the specified name.
|
||||
* <p>
|
||||
* Any listener can throw a {@code PropertyVetoException} to veto the update.
|
||||
* If one of the listeners vetoes the update, this method passes
|
||||
* a new "undo" {@code PropertyChangeEvent} that reverts to the old value
|
||||
* to all listeners that already confirmed this update
|
||||
* and throws the {@code PropertyVetoException} again.
|
||||
* <p>
|
||||
* No event is fired if old and new values are equal and non-null.
|
||||
* <p>
|
||||
* This is merely a convenience wrapper around the more general
|
||||
* {@link #fireVetoableChange(PropertyChangeEvent)} method.
|
||||
*
|
||||
* @param propertyName the programmatic name of the property that is about to change
|
||||
* @param oldValue the old value of the property
|
||||
* @param newValue the new value of the property
|
||||
* @throws PropertyVetoException if one of listeners vetoes the property update
|
||||
*/
|
||||
public void fireVetoableChange(String propertyName, Object oldValue, Object newValue)
|
||||
throws PropertyVetoException {
|
||||
if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
|
||||
fireVetoableChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports an integer constrained property update to listeners
|
||||
* that have been registered to track updates of
|
||||
* all properties or a property with the specified name.
|
||||
* <p>
|
||||
* Any listener can throw a {@code PropertyVetoException} to veto the update.
|
||||
* If one of the listeners vetoes the update, this method passes
|
||||
* a new "undo" {@code PropertyChangeEvent} that reverts to the old value
|
||||
* to all listeners that already confirmed this update
|
||||
* and throws the {@code PropertyVetoException} again.
|
||||
* <p>
|
||||
* No event is fired if old and new values are equal.
|
||||
* <p>
|
||||
* This is merely a convenience wrapper around the more general
|
||||
* {@link #fireVetoableChange(String, Object, Object)} method.
|
||||
*
|
||||
* @param propertyName the programmatic name of the property that is about to change
|
||||
* @param oldValue the old value of the property
|
||||
* @param newValue the new value of the property
|
||||
* @throws PropertyVetoException if one of listeners vetoes the property update
|
||||
*/
|
||||
public void fireVetoableChange(String propertyName, int oldValue, int newValue)
|
||||
throws PropertyVetoException {
|
||||
if (oldValue != newValue) {
|
||||
fireVetoableChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports a boolean constrained property update to listeners
|
||||
* that have been registered to track updates of
|
||||
* all properties or a property with the specified name.
|
||||
* <p>
|
||||
* Any listener can throw a {@code PropertyVetoException} to veto the update.
|
||||
* If one of the listeners vetoes the update, this method passes
|
||||
* a new "undo" {@code PropertyChangeEvent} that reverts to the old value
|
||||
* to all listeners that already confirmed this update
|
||||
* and throws the {@code PropertyVetoException} again.
|
||||
* <p>
|
||||
* No event is fired if old and new values are equal.
|
||||
* <p>
|
||||
* This is merely a convenience wrapper around the more general
|
||||
* {@link #fireVetoableChange(String, Object, Object)} method.
|
||||
*
|
||||
* @param propertyName the programmatic name of the property that is about to change
|
||||
* @param oldValue the old value of the property
|
||||
* @param newValue the new value of the property
|
||||
* @throws PropertyVetoException if one of listeners vetoes the property update
|
||||
*/
|
||||
public void fireVetoableChange(String propertyName, boolean oldValue, boolean newValue)
|
||||
throws PropertyVetoException {
|
||||
if (oldValue != newValue) {
|
||||
fireVetoableChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires a property change event to listeners
|
||||
* that have been registered to track updates of
|
||||
* all properties or a property with the specified name.
|
||||
* <p>
|
||||
* Any listener can throw a {@code PropertyVetoException} to veto the update.
|
||||
* If one of the listeners vetoes the update, this method passes
|
||||
* a new "undo" {@code PropertyChangeEvent} that reverts to the old value
|
||||
* to all listeners that already confirmed this update
|
||||
* and throws the {@code PropertyVetoException} again.
|
||||
* <p>
|
||||
* No event is fired if the given event's old and new values are equal and non-null.
|
||||
*
|
||||
* @param event the {@code PropertyChangeEvent} to be fired
|
||||
* @throws PropertyVetoException if one of listeners vetoes the property update
|
||||
*/
|
||||
public void fireVetoableChange(PropertyChangeEvent event)
|
||||
throws PropertyVetoException {
|
||||
Object oldValue = event.getOldValue();
|
||||
Object newValue = event.getNewValue();
|
||||
if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
|
||||
String name = event.getPropertyName();
|
||||
|
||||
VetoableChangeListener[] common = this.map.get(null);
|
||||
VetoableChangeListener[] named = (name != null)
|
||||
? this.map.get(name)
|
||||
: null;
|
||||
|
||||
VetoableChangeListener[] listeners;
|
||||
if (common == null) {
|
||||
listeners = named;
|
||||
}
|
||||
else if (named == null) {
|
||||
listeners = common;
|
||||
}
|
||||
else {
|
||||
listeners = new VetoableChangeListener[common.length + named.length];
|
||||
System.arraycopy(common, 0, listeners, 0, common.length);
|
||||
System.arraycopy(named, 0, listeners, common.length, named.length);
|
||||
}
|
||||
if (listeners != null) {
|
||||
int current = 0;
|
||||
try {
|
||||
while (current < listeners.length) {
|
||||
listeners[current].vetoableChange(event);
|
||||
current++;
|
||||
}
|
||||
}
|
||||
catch (PropertyVetoException veto) {
|
||||
event = new PropertyChangeEvent(this.source, name, newValue, oldValue);
|
||||
for (int i = 0; i < current; i++) {
|
||||
try {
|
||||
listeners[i].vetoableChange(event);
|
||||
}
|
||||
catch (PropertyVetoException exception) {
|
||||
// ignore exceptions that occur during rolling back
|
||||
}
|
||||
}
|
||||
throw veto; // rethrow the veto exception
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there are any listeners for a specific property, including
|
||||
* those registered on all properties. If <code>propertyName</code>
|
||||
* is null, only check for listeners registered on all properties.
|
||||
*
|
||||
* @param propertyName the property name.
|
||||
* @return true if there are one or more listeners for the given property
|
||||
*/
|
||||
public boolean hasListeners(String propertyName) {
|
||||
return this.map.hasListeners(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @serialData Null terminated list of <code>VetoableChangeListeners</code>.
|
||||
* <p>
|
||||
* At serialization time we skip non-serializable listeners and
|
||||
* only serialize the serializable listeners.
|
||||
*/
|
||||
private void writeObject(ObjectOutputStream s) throws IOException {
|
||||
Hashtable<String, VetoableChangeSupport> children = null;
|
||||
VetoableChangeListener[] listeners = null;
|
||||
synchronized (this.map) {
|
||||
for (Entry<String, VetoableChangeListener[]> entry : this.map.getEntries()) {
|
||||
String property = entry.getKey();
|
||||
if (property == null) {
|
||||
listeners = entry.getValue();
|
||||
} else {
|
||||
if (children == null) {
|
||||
children = new Hashtable<>();
|
||||
}
|
||||
VetoableChangeSupport vcs = new VetoableChangeSupport(this.source);
|
||||
vcs.map.set(null, entry.getValue());
|
||||
children.put(property, vcs);
|
||||
}
|
||||
}
|
||||
}
|
||||
ObjectOutputStream.PutField fields = s.putFields();
|
||||
fields.put("children", children);
|
||||
fields.put("source", this.source);
|
||||
fields.put("vetoableChangeSupportSerializedDataVersion", 2);
|
||||
s.writeFields();
|
||||
|
||||
if (listeners != null) {
|
||||
for (VetoableChangeListener l : listeners) {
|
||||
if (l instanceof Serializable) {
|
||||
s.writeObject(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
s.writeObject(null);
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
|
||||
this.map = new VetoableChangeListenerMap();
|
||||
|
||||
ObjectInputStream.GetField fields = s.readFields();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Hashtable<String, VetoableChangeSupport> children = (Hashtable<String, VetoableChangeSupport>)fields.get("children", null);
|
||||
this.source = fields.get("source", null);
|
||||
fields.get("vetoableChangeSupportSerializedDataVersion", 2);
|
||||
|
||||
Object listenerOrNull;
|
||||
while (null != (listenerOrNull = s.readObject())) {
|
||||
this.map.add(null, (VetoableChangeListener)listenerOrNull);
|
||||
}
|
||||
if (children != null) {
|
||||
for (Entry<String, VetoableChangeSupport> entry : children.entrySet()) {
|
||||
for (VetoableChangeListener listener : entry.getValue().getVetoableChangeListeners()) {
|
||||
this.map.add(entry.getKey(), listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The object to be provided as the "source" for any generated events.
|
||||
*/
|
||||
private Object source;
|
||||
|
||||
/**
|
||||
* @serialField children Hashtable
|
||||
* @serialField source Object
|
||||
* @serialField vetoableChangeSupportSerializedDataVersion int
|
||||
*/
|
||||
private static final ObjectStreamField[] serialPersistentFields = {
|
||||
new ObjectStreamField("children", Hashtable.class),
|
||||
new ObjectStreamField("source", Object.class),
|
||||
new ObjectStreamField("vetoableChangeSupportSerializedDataVersion", Integer.TYPE)
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialization version ID, so we're compatible with JDK 1.1
|
||||
*/
|
||||
static final long serialVersionUID = -5090210921595982017L;
|
||||
|
||||
/**
|
||||
* This is a {@link ChangeListenerMap ChangeListenerMap} implementation
|
||||
* that works with {@link VetoableChangeListener VetoableChangeListener} objects.
|
||||
*/
|
||||
private static final class VetoableChangeListenerMap extends ChangeListenerMap<VetoableChangeListener> {
|
||||
private static final VetoableChangeListener[] EMPTY = {};
|
||||
|
||||
/**
|
||||
* Creates an array of {@link VetoableChangeListener VetoableChangeListener} objects.
|
||||
* This method uses the same instance of the empty array
|
||||
* when {@code length} equals {@code 0}.
|
||||
*
|
||||
* @param length the array length
|
||||
* @return an array with specified length
|
||||
*/
|
||||
@Override
|
||||
protected VetoableChangeListener[] newArray(int length) {
|
||||
return (0 < length)
|
||||
? new VetoableChangeListener[length]
|
||||
: EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link VetoableChangeListenerProxy VetoableChangeListenerProxy}
|
||||
* object for the specified property.
|
||||
*
|
||||
* @param name the name of the property to listen on
|
||||
* @param listener the listener to process events
|
||||
* @return a {@code VetoableChangeListenerProxy} object
|
||||
*/
|
||||
@Override
|
||||
protected VetoableChangeListener newProxy(String name, VetoableChangeListener listener) {
|
||||
return new VetoableChangeListenerProxy(name, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public final VetoableChangeListener extract(VetoableChangeListener listener) {
|
||||
while (listener instanceof VetoableChangeListenerProxy) {
|
||||
listener = ((VetoableChangeListenerProxy) listener).getListener();
|
||||
}
|
||||
return listener;
|
||||
}
|
||||
}
|
||||
}
|
||||
67
jdkSrc/jdk8/java/beans/Visibility.java
Normal file
67
jdkSrc/jdk8/java/beans/Visibility.java
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 1998, 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;
|
||||
|
||||
/**
|
||||
* Under some circumstances a bean may be run on servers where a GUI
|
||||
* is not available. This interface can be used to query a bean to
|
||||
* determine whether it absolutely needs a gui, and to advise the
|
||||
* bean whether a GUI is available.
|
||||
* <p>
|
||||
* This interface is for expert developers, and is not needed
|
||||
* for normal simple beans. To avoid confusing end-users we
|
||||
* avoid using getXXX setXXX design patterns for these methods.
|
||||
*/
|
||||
|
||||
public interface Visibility {
|
||||
|
||||
/**
|
||||
* Determines whether this bean needs a GUI.
|
||||
*
|
||||
* @return True if the bean absolutely needs a GUI available in
|
||||
* order to get its work done.
|
||||
*/
|
||||
boolean needsGui();
|
||||
|
||||
/**
|
||||
* This method instructs the bean that it should not use the Gui.
|
||||
*/
|
||||
void dontUseGui();
|
||||
|
||||
/**
|
||||
* This method instructs the bean that it is OK to use the Gui.
|
||||
*/
|
||||
void okToUseGui();
|
||||
|
||||
/**
|
||||
* Determines whether this bean is avoiding using a GUI.
|
||||
*
|
||||
* @return true if the bean is currently avoiding use of the Gui.
|
||||
* e.g. due to a call on dontUseGui().
|
||||
*/
|
||||
boolean avoidingGui();
|
||||
|
||||
}
|
||||
190
jdkSrc/jdk8/java/beans/WeakIdentityMap.java
Normal file
190
jdkSrc/jdk8/java/beans/WeakIdentityMap.java
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 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.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* Hash table based mapping, which uses weak references to store keys
|
||||
* and reference-equality in place of object-equality to compare them.
|
||||
* An entry will automatically be removed when its key is no longer
|
||||
* in ordinary use. Both null values and the null key are supported.
|
||||
* This class does not require additional synchronization.
|
||||
* A thread-safety is provided by a fragile combination
|
||||
* of synchronized blocks and volatile fields.
|
||||
* Be very careful during editing!
|
||||
*
|
||||
* @see java.util.IdentityHashMap
|
||||
* @see java.util.WeakHashMap
|
||||
*/
|
||||
abstract class WeakIdentityMap<T> {
|
||||
|
||||
private static final int MAXIMUM_CAPACITY = 1 << 30; // it MUST be a power of two
|
||||
private static final Object NULL = new Object(); // special object for null key
|
||||
|
||||
private final ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
|
||||
|
||||
private volatile Entry<T>[] table = newTable(1<<3); // table's length MUST be a power of two
|
||||
private int threshold = 6; // the next size value at which to resize
|
||||
private int size = 0; // the number of key-value mappings
|
||||
|
||||
public T get(Object key) {
|
||||
removeStaleEntries();
|
||||
if (key == null) {
|
||||
key = NULL;
|
||||
}
|
||||
int hash = key.hashCode();
|
||||
Entry<T>[] table = this.table;
|
||||
// unsynchronized search improves performance
|
||||
// the null value does not mean that there are no needed entry
|
||||
int index = getIndex(table, hash);
|
||||
for (Entry<T> entry = table[index]; entry != null; entry = entry.next) {
|
||||
if (entry.isMatched(key, hash)) {
|
||||
return entry.value;
|
||||
}
|
||||
}
|
||||
synchronized (NULL) {
|
||||
// synchronized search improves stability
|
||||
// we must create and add new value if there are no needed entry
|
||||
index = getIndex(this.table, hash);
|
||||
for (Entry<T> entry = this.table[index]; entry != null; entry = entry.next) {
|
||||
if (entry.isMatched(key, hash)) {
|
||||
return entry.value;
|
||||
}
|
||||
}
|
||||
T value = create(key);
|
||||
this.table[index] = new Entry<T>(key, hash, value, this.queue, this.table[index]);
|
||||
if (++this.size >= this.threshold) {
|
||||
if (this.table.length == MAXIMUM_CAPACITY) {
|
||||
this.threshold = Integer.MAX_VALUE;
|
||||
}
|
||||
else {
|
||||
removeStaleEntries();
|
||||
table = newTable(this.table.length * 2);
|
||||
transfer(this.table, table);
|
||||
// If ignoring null elements and processing ref queue caused massive
|
||||
// shrinkage, then restore old table. This should be rare, but avoids
|
||||
// unbounded expansion of garbage-filled tables.
|
||||
if (this.size >= this.threshold / 2) {
|
||||
this.table = table;
|
||||
this.threshold *= 2;
|
||||
}
|
||||
else {
|
||||
transfer(table, this.table);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract T create(Object key);
|
||||
|
||||
private void removeStaleEntries() {
|
||||
Object ref = this.queue.poll();
|
||||
if (ref != null) {
|
||||
synchronized (NULL) {
|
||||
do {
|
||||
@SuppressWarnings("unchecked")
|
||||
Entry<T> entry = (Entry<T>) ref;
|
||||
int index = getIndex(this.table, entry.hash);
|
||||
|
||||
Entry<T> prev = this.table[index];
|
||||
Entry<T> current = prev;
|
||||
while (current != null) {
|
||||
Entry<T> next = current.next;
|
||||
if (current == entry) {
|
||||
if (prev == entry) {
|
||||
this.table[index] = next;
|
||||
}
|
||||
else {
|
||||
prev.next = next;
|
||||
}
|
||||
entry.value = null; // Help GC
|
||||
entry.next = null; // Help GC
|
||||
this.size--;
|
||||
break;
|
||||
}
|
||||
prev = current;
|
||||
current = next;
|
||||
}
|
||||
ref = this.queue.poll();
|
||||
}
|
||||
while (ref != null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void transfer(Entry<T>[] oldTable, Entry<T>[] newTable) {
|
||||
for (int i = 0; i < oldTable.length; i++) {
|
||||
Entry<T> entry = oldTable[i];
|
||||
oldTable[i] = null;
|
||||
while (entry != null) {
|
||||
Entry<T> next = entry.next;
|
||||
Object key = entry.get();
|
||||
if (key == null) {
|
||||
entry.value = null; // Help GC
|
||||
entry.next = null; // Help GC
|
||||
this.size--;
|
||||
}
|
||||
else {
|
||||
int index = getIndex(newTable, entry.hash);
|
||||
entry.next = newTable[index];
|
||||
newTable[index] = entry;
|
||||
}
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Entry<T>[] newTable(int length) {
|
||||
return (Entry<T>[]) new Entry<?>[length];
|
||||
}
|
||||
|
||||
private static int getIndex(Entry<?>[] table, int hash) {
|
||||
return hash & (table.length - 1);
|
||||
}
|
||||
|
||||
private static class Entry<T> extends WeakReference<Object> {
|
||||
private final int hash;
|
||||
private volatile T value;
|
||||
private volatile Entry<T> next;
|
||||
|
||||
Entry(Object key, int hash, T value, ReferenceQueue<Object> queue, Entry<T> next) {
|
||||
super(key, queue);
|
||||
this.hash = hash;
|
||||
this.value = value;
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
boolean isMatched(Object key, int hash) {
|
||||
return (this.hash == hash) && (key == get());
|
||||
}
|
||||
}
|
||||
}
|
||||
306
jdkSrc/jdk8/java/beans/XMLDecoder.java
Normal file
306
jdkSrc/jdk8/java/beans/XMLDecoder.java
Normal file
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, 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 com.sun.beans.decoder.DocumentHandler;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
/**
|
||||
* The <code>XMLDecoder</code> class is used to read XML documents
|
||||
* created using the <code>XMLEncoder</code> and is used just like
|
||||
* the <code>ObjectInputStream</code>. For example, one can use
|
||||
* the following fragment to read the first object defined
|
||||
* in an XML document written by the <code>XMLEncoder</code>
|
||||
* class:
|
||||
* <pre>
|
||||
* XMLDecoder d = new XMLDecoder(
|
||||
* new BufferedInputStream(
|
||||
* new FileInputStream("Test.xml")));
|
||||
* Object result = d.readObject();
|
||||
* d.close();
|
||||
* </pre>
|
||||
*
|
||||
*<p>
|
||||
* For more information you might also want to check out
|
||||
* <a
|
||||
href="http://java.sun.com/products/jfc/tsc/articles/persistence3">Long Term Persistence of JavaBeans Components: XML Schema</a>,
|
||||
* an article in <em>The Swing Connection.</em>
|
||||
* @see XMLEncoder
|
||||
* @see java.io.ObjectInputStream
|
||||
*
|
||||
* @since 1.4
|
||||
*
|
||||
* @author Philip Milne
|
||||
*/
|
||||
public class XMLDecoder implements AutoCloseable {
|
||||
private final AccessControlContext acc = AccessController.getContext();
|
||||
private final DocumentHandler handler = new DocumentHandler();
|
||||
private final InputSource input;
|
||||
private Object owner;
|
||||
private Object[] array;
|
||||
private int index;
|
||||
|
||||
/**
|
||||
* Creates a new input stream for reading archives
|
||||
* created by the <code>XMLEncoder</code> class.
|
||||
*
|
||||
* @param in The underlying stream.
|
||||
*
|
||||
* @see XMLEncoder#XMLEncoder(java.io.OutputStream)
|
||||
*/
|
||||
public XMLDecoder(InputStream in) {
|
||||
this(in, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new input stream for reading archives
|
||||
* created by the <code>XMLEncoder</code> class.
|
||||
*
|
||||
* @param in The underlying stream.
|
||||
* @param owner The owner of this stream.
|
||||
*
|
||||
*/
|
||||
public XMLDecoder(InputStream in, Object owner) {
|
||||
this(in, owner, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new input stream for reading archives
|
||||
* created by the <code>XMLEncoder</code> class.
|
||||
*
|
||||
* @param in the underlying stream.
|
||||
* @param owner the owner of this stream.
|
||||
* @param exceptionListener the exception handler for the stream;
|
||||
* if <code>null</code> the default exception listener will be used.
|
||||
*/
|
||||
public XMLDecoder(InputStream in, Object owner, ExceptionListener exceptionListener) {
|
||||
this(in, owner, exceptionListener, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new input stream for reading archives
|
||||
* created by the <code>XMLEncoder</code> class.
|
||||
*
|
||||
* @param in the underlying stream. <code>null</code> may be passed without
|
||||
* error, though the resulting XMLDecoder will be useless
|
||||
* @param owner the owner of this stream. <code>null</code> is a legal
|
||||
* value
|
||||
* @param exceptionListener the exception handler for the stream, or
|
||||
* <code>null</code> to use the default
|
||||
* @param cl the class loader used for instantiating objects.
|
||||
* <code>null</code> indicates that the default class loader should
|
||||
* be used
|
||||
* @since 1.5
|
||||
*/
|
||||
public XMLDecoder(InputStream in, Object owner,
|
||||
ExceptionListener exceptionListener, ClassLoader cl) {
|
||||
this(new InputSource(in), owner, exceptionListener, cl);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new decoder to parse XML archives
|
||||
* created by the {@code XMLEncoder} class.
|
||||
* If the input source {@code is} is {@code null},
|
||||
* no exception is thrown and no parsing is performed.
|
||||
* This behavior is similar to behavior of other constructors
|
||||
* that use {@code InputStream} as a parameter.
|
||||
*
|
||||
* @param is the input source to parse
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public XMLDecoder(InputSource is) {
|
||||
this(is, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new decoder to parse XML archives
|
||||
* created by the {@code XMLEncoder} class.
|
||||
*
|
||||
* @param is the input source to parse
|
||||
* @param owner the owner of this decoder
|
||||
* @param el the exception handler for the parser,
|
||||
* or {@code null} to use the default exception handler
|
||||
* @param cl the class loader used for instantiating objects,
|
||||
* or {@code null} to use the default class loader
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
private XMLDecoder(InputSource is, Object owner, ExceptionListener el, ClassLoader cl) {
|
||||
this.input = is;
|
||||
this.owner = owner;
|
||||
setExceptionListener(el);
|
||||
this.handler.setClassLoader(cl);
|
||||
this.handler.setOwner(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method closes the input stream associated
|
||||
* with this stream.
|
||||
*/
|
||||
public void close() {
|
||||
if (parsingComplete()) {
|
||||
close(this.input.getCharacterStream());
|
||||
close(this.input.getByteStream());
|
||||
}
|
||||
}
|
||||
|
||||
private void close(Closeable in) {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
getExceptionListener().exceptionThrown(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean parsingComplete() {
|
||||
if (this.input == null) {
|
||||
return false;
|
||||
}
|
||||
if (this.array == null) {
|
||||
if ((this.acc == null) && (null != System.getSecurityManager())) {
|
||||
throw new SecurityException("AccessControlContext is not set");
|
||||
}
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
XMLDecoder.this.handler.parse(XMLDecoder.this.input);
|
||||
return null;
|
||||
}
|
||||
}, this.acc);
|
||||
this.array = this.handler.getObjects();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the exception handler for this stream to <code>exceptionListener</code>.
|
||||
* The exception handler is notified when this stream catches recoverable
|
||||
* exceptions.
|
||||
*
|
||||
* @param exceptionListener The exception handler for this stream;
|
||||
* if <code>null</code> the default exception listener will be used.
|
||||
*
|
||||
* @see #getExceptionListener
|
||||
*/
|
||||
public void setExceptionListener(ExceptionListener exceptionListener) {
|
||||
if (exceptionListener == null) {
|
||||
exceptionListener = Statement.defaultExceptionListener;
|
||||
}
|
||||
this.handler.setExceptionListener(exceptionListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exception handler for this stream.
|
||||
*
|
||||
* @return The exception handler for this stream.
|
||||
* Will return the default exception listener if this has not explicitly been set.
|
||||
*
|
||||
* @see #setExceptionListener
|
||||
*/
|
||||
public ExceptionListener getExceptionListener() {
|
||||
return this.handler.getExceptionListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the next object from the underlying input stream.
|
||||
*
|
||||
* @return the next object read
|
||||
*
|
||||
* @throws ArrayIndexOutOfBoundsException if the stream contains no objects
|
||||
* (or no more objects)
|
||||
*
|
||||
* @see XMLEncoder#writeObject
|
||||
*/
|
||||
public Object readObject() {
|
||||
return (parsingComplete())
|
||||
? this.array[this.index++]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the owner of this decoder to <code>owner</code>.
|
||||
*
|
||||
* @param owner The owner of this decoder.
|
||||
*
|
||||
* @see #getOwner
|
||||
*/
|
||||
public void setOwner(Object owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the owner of this decoder.
|
||||
*
|
||||
* @return The owner of this decoder.
|
||||
*
|
||||
* @see #setOwner
|
||||
*/
|
||||
public Object getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new handler for SAX parser
|
||||
* that can be used to parse embedded XML archives
|
||||
* created by the {@code XMLEncoder} class.
|
||||
*
|
||||
* The {@code owner} should be used if parsed XML document contains
|
||||
* the method call within context of the <java> element.
|
||||
* The {@code null} value may cause illegal parsing in such case.
|
||||
* The same problem may occur, if the {@code owner} class
|
||||
* does not contain expected method to call. See details <a
|
||||
* href="http://java.sun.com/products/jfc/tsc/articles/persistence3/">here</a>.
|
||||
*
|
||||
* @param owner the owner of the default handler
|
||||
* that can be used as a value of <java> element
|
||||
* @param el the exception handler for the parser,
|
||||
* or {@code null} to use the default exception handler
|
||||
* @param cl the class loader used for instantiating objects,
|
||||
* or {@code null} to use the default class loader
|
||||
* @return an instance of {@code DefaultHandler} for SAX parser
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public static DefaultHandler createHandler(Object owner, ExceptionListener el, ClassLoader cl) {
|
||||
DocumentHandler handler = new DocumentHandler();
|
||||
handler.setOwner(owner);
|
||||
handler.setExceptionListener(el);
|
||||
handler.setClassLoader(cl);
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
814
jdkSrc/jdk8/java/beans/XMLEncoder.java
Normal file
814
jdkSrc/jdk8/java/beans/XMLEncoder.java
Normal file
@@ -0,0 +1,814 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.beans;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.nio.charset.IllegalCharsetNameException;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
|
||||
/**
|
||||
* The <code>XMLEncoder</code> class is a complementary alternative to
|
||||
* the <code>ObjectOutputStream</code> and can used to generate
|
||||
* a textual representation of a <em>JavaBean</em> in the same
|
||||
* way that the <code>ObjectOutputStream</code> can
|
||||
* be used to create binary representation of <code>Serializable</code>
|
||||
* objects. For example, the following fragment can be used to create
|
||||
* a textual representation the supplied <em>JavaBean</em>
|
||||
* and all its properties:
|
||||
* <pre>
|
||||
* XMLEncoder e = new XMLEncoder(
|
||||
* new BufferedOutputStream(
|
||||
* new FileOutputStream("Test.xml")));
|
||||
* e.writeObject(new JButton("Hello, world"));
|
||||
* e.close();
|
||||
* </pre>
|
||||
* Despite the similarity of their APIs, the <code>XMLEncoder</code>
|
||||
* class is exclusively designed for the purpose of archiving graphs
|
||||
* of <em>JavaBean</em>s as textual representations of their public
|
||||
* properties. Like Java source files, documents written this way
|
||||
* have a natural immunity to changes in the implementations of the classes
|
||||
* involved. The <code>ObjectOutputStream</code> continues to be recommended
|
||||
* for interprocess communication and general purpose serialization.
|
||||
* <p>
|
||||
* The <code>XMLEncoder</code> class provides a default denotation for
|
||||
* <em>JavaBean</em>s in which they are represented as XML documents
|
||||
* complying with version 1.0 of the XML specification and the
|
||||
* UTF-8 character encoding of the Unicode/ISO 10646 character set.
|
||||
* The XML documents produced by the <code>XMLEncoder</code> class are:
|
||||
* <ul>
|
||||
* <li>
|
||||
* <em>Portable and version resilient</em>: they have no dependencies
|
||||
* on the private implementation of any class and so, like Java source
|
||||
* files, they may be exchanged between environments which may have
|
||||
* different versions of some of the classes and between VMs from
|
||||
* different vendors.
|
||||
* <li>
|
||||
* <em>Structurally compact</em>: The <code>XMLEncoder</code> class
|
||||
* uses a <em>redundancy elimination</em> algorithm internally so that the
|
||||
* default values of a Bean's properties are not written to the stream.
|
||||
* <li>
|
||||
* <em>Fault tolerant</em>: Non-structural errors in the file,
|
||||
* caused either by damage to the file or by API changes
|
||||
* made to classes in an archive remain localized
|
||||
* so that a reader can report the error and continue to load the parts
|
||||
* of the document which were not affected by the error.
|
||||
* </ul>
|
||||
* <p>
|
||||
* Below is an example of an XML archive containing
|
||||
* some user interface components from the <em>swing</em> toolkit:
|
||||
* <pre>
|
||||
* <?xml version="1.0" encoding="UTF-8"?>
|
||||
* <java version="1.0" class="java.beans.XMLDecoder">
|
||||
* <object class="javax.swing.JFrame">
|
||||
* <void property="name">
|
||||
* <string>frame1</string>
|
||||
* </void>
|
||||
* <void property="bounds">
|
||||
* <object class="java.awt.Rectangle">
|
||||
* <int>0</int>
|
||||
* <int>0</int>
|
||||
* <int>200</int>
|
||||
* <int>200</int>
|
||||
* </object>
|
||||
* </void>
|
||||
* <void property="contentPane">
|
||||
* <void method="add">
|
||||
* <object class="javax.swing.JButton">
|
||||
* <void property="label">
|
||||
* <string>Hello</string>
|
||||
* </void>
|
||||
* </object>
|
||||
* </void>
|
||||
* </void>
|
||||
* <void property="visible">
|
||||
* <boolean>true</boolean>
|
||||
* </void>
|
||||
* </object>
|
||||
* </java>
|
||||
* </pre>
|
||||
* The XML syntax uses the following conventions:
|
||||
* <ul>
|
||||
* <li>
|
||||
* Each element represents a method call.
|
||||
* <li>
|
||||
* The "object" tag denotes an <em>expression</em> whose value is
|
||||
* to be used as the argument to the enclosing element.
|
||||
* <li>
|
||||
* The "void" tag denotes a <em>statement</em> which will
|
||||
* be executed, but whose result will not be used as an
|
||||
* argument to the enclosing method.
|
||||
* <li>
|
||||
* Elements which contain elements use those elements as arguments,
|
||||
* unless they have the tag: "void".
|
||||
* <li>
|
||||
* The name of the method is denoted by the "method" attribute.
|
||||
* <li>
|
||||
* XML's standard "id" and "idref" attributes are used to make
|
||||
* references to previous expressions - so as to deal with
|
||||
* circularities in the object graph.
|
||||
* <li>
|
||||
* The "class" attribute is used to specify the target of a static
|
||||
* method or constructor explicitly; its value being the fully
|
||||
* qualified name of the class.
|
||||
* <li>
|
||||
* Elements with the "void" tag are executed using
|
||||
* the outer context as the target if no target is defined
|
||||
* by a "class" attribute.
|
||||
* <li>
|
||||
* Java's String class is treated specially and is
|
||||
* written <string>Hello, world</string> where
|
||||
* the characters of the string are converted to bytes
|
||||
* using the UTF-8 character encoding.
|
||||
* </ul>
|
||||
* <p>
|
||||
* Although all object graphs may be written using just these three
|
||||
* tags, the following definitions are included so that common
|
||||
* data structures can be expressed more concisely:
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>
|
||||
* The default method name is "new".
|
||||
* <li>
|
||||
* A reference to a java class is written in the form
|
||||
* <class>javax.swing.JButton</class>.
|
||||
* <li>
|
||||
* Instances of the wrapper classes for Java's primitive types are written
|
||||
* using the name of the primitive type as the tag. For example, an
|
||||
* instance of the <code>Integer</code> class could be written:
|
||||
* <int>123</int>. Note that the <code>XMLEncoder</code> class
|
||||
* uses Java's reflection package in which the conversion between
|
||||
* Java's primitive types and their associated "wrapper classes"
|
||||
* is handled internally. The API for the <code>XMLEncoder</code> class
|
||||
* itself deals only with <code>Object</code>s.
|
||||
* <li>
|
||||
* In an element representing a nullary method whose name
|
||||
* starts with "get", the "method" attribute is replaced
|
||||
* with a "property" attribute whose value is given by removing
|
||||
* the "get" prefix and decapitalizing the result.
|
||||
* <li>
|
||||
* In an element representing a monadic method whose name
|
||||
* starts with "set", the "method" attribute is replaced
|
||||
* with a "property" attribute whose value is given by removing
|
||||
* the "set" prefix and decapitalizing the result.
|
||||
* <li>
|
||||
* In an element representing a method named "get" taking one
|
||||
* integer argument, the "method" attribute is replaced
|
||||
* with an "index" attribute whose value the value of the
|
||||
* first argument.
|
||||
* <li>
|
||||
* In an element representing a method named "set" taking two arguments,
|
||||
* the first of which is an integer, the "method" attribute is replaced
|
||||
* with an "index" attribute whose value the value of the
|
||||
* first argument.
|
||||
* <li>
|
||||
* A reference to an array is written using the "array"
|
||||
* tag. The "class" and "length" attributes specify the
|
||||
* sub-type of the array and its length respectively.
|
||||
* </ul>
|
||||
*
|
||||
*<p>
|
||||
* For more information you might also want to check out
|
||||
* <a
|
||||
href="http://java.sun.com/products/jfc/tsc/articles/persistence4">Using XMLEncoder</a>,
|
||||
* an article in <em>The Swing Connection.</em>
|
||||
* @see XMLDecoder
|
||||
* @see java.io.ObjectOutputStream
|
||||
*
|
||||
* @since 1.4
|
||||
*
|
||||
* @author Philip Milne
|
||||
*/
|
||||
public class XMLEncoder extends Encoder implements AutoCloseable {
|
||||
|
||||
private final CharsetEncoder encoder;
|
||||
private final String charset;
|
||||
private final boolean declaration;
|
||||
|
||||
private OutputStreamWriter out;
|
||||
private Object owner;
|
||||
private int indentation = 0;
|
||||
private boolean internal = false;
|
||||
private Map<Object, ValueData> valueToExpression;
|
||||
private Map<Object, List<Statement>> targetToStatementList;
|
||||
private boolean preambleWritten = false;
|
||||
private NameGenerator nameGenerator;
|
||||
|
||||
private class ValueData {
|
||||
public int refs = 0;
|
||||
public boolean marked = false; // Marked -> refs > 0 unless ref was a target.
|
||||
public String name = null;
|
||||
public Expression exp = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new XML encoder to write out <em>JavaBeans</em>
|
||||
* to the stream <code>out</code> using an XML encoding.
|
||||
*
|
||||
* @param out the stream to which the XML representation of
|
||||
* the objects will be written
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if <code>out</code> is <code>null</code>
|
||||
*
|
||||
* @see XMLDecoder#XMLDecoder(InputStream)
|
||||
*/
|
||||
public XMLEncoder(OutputStream out) {
|
||||
this(out, "UTF-8", true, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new XML encoder to write out <em>JavaBeans</em>
|
||||
* to the stream <code>out</code> using the given <code>charset</code>
|
||||
* starting from the given <code>indentation</code>.
|
||||
*
|
||||
* @param out the stream to which the XML representation of
|
||||
* the objects will be written
|
||||
* @param charset the name of the requested charset;
|
||||
* may be either a canonical name or an alias
|
||||
* @param declaration whether the XML declaration should be generated;
|
||||
* set this to <code>false</code>
|
||||
* when embedding the contents in another XML document
|
||||
* @param indentation the number of space characters to indent the entire XML document by
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if <code>out</code> or <code>charset</code> is <code>null</code>,
|
||||
* or if <code>indentation</code> is less than 0
|
||||
*
|
||||
* @throws IllegalCharsetNameException
|
||||
* if <code>charset</code> name is illegal
|
||||
*
|
||||
* @throws UnsupportedCharsetException
|
||||
* if no support for the named charset is available
|
||||
* in this instance of the Java virtual machine
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* if loaded charset does not support encoding
|
||||
*
|
||||
* @see Charset#forName(String)
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public XMLEncoder(OutputStream out, String charset, boolean declaration, int indentation) {
|
||||
if (out == null) {
|
||||
throw new IllegalArgumentException("the output stream cannot be null");
|
||||
}
|
||||
if (indentation < 0) {
|
||||
throw new IllegalArgumentException("the indentation must be >= 0");
|
||||
}
|
||||
Charset cs = Charset.forName(charset);
|
||||
this.encoder = cs.newEncoder();
|
||||
this.charset = charset;
|
||||
this.declaration = declaration;
|
||||
this.indentation = indentation;
|
||||
this.out = new OutputStreamWriter(out, cs.newEncoder());
|
||||
valueToExpression = new IdentityHashMap<>();
|
||||
targetToStatementList = new IdentityHashMap<>();
|
||||
nameGenerator = new NameGenerator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the owner of this encoder to <code>owner</code>.
|
||||
*
|
||||
* @param owner The owner of this encoder.
|
||||
*
|
||||
* @see #getOwner
|
||||
*/
|
||||
public void setOwner(Object owner) {
|
||||
this.owner = owner;
|
||||
writeExpression(new Expression(this, "getOwner", new Object[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the owner of this encoder.
|
||||
*
|
||||
* @return The owner of this encoder.
|
||||
*
|
||||
* @see #setOwner
|
||||
*/
|
||||
public Object getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an XML representation of the specified object to the output.
|
||||
*
|
||||
* @param o The object to be written to the stream.
|
||||
*
|
||||
* @see XMLDecoder#readObject
|
||||
*/
|
||||
public void writeObject(Object o) {
|
||||
if (internal) {
|
||||
super.writeObject(o);
|
||||
}
|
||||
else {
|
||||
writeStatement(new Statement(this, "writeObject", new Object[]{o}));
|
||||
}
|
||||
}
|
||||
|
||||
private List<Statement> statementList(Object target) {
|
||||
List<Statement> list = targetToStatementList.get(target);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
targetToStatementList.put(target, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
private void mark(Object o, boolean isArgument) {
|
||||
if (o == null || o == this) {
|
||||
return;
|
||||
}
|
||||
ValueData d = getValueData(o);
|
||||
Expression exp = d.exp;
|
||||
// Do not mark liternal strings. Other strings, which might,
|
||||
// for example, come from resource bundles should still be marked.
|
||||
if (o.getClass() == String.class && exp == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Bump the reference counts of all arguments
|
||||
if (isArgument) {
|
||||
d.refs++;
|
||||
}
|
||||
if (d.marked) {
|
||||
return;
|
||||
}
|
||||
d.marked = true;
|
||||
Object target = exp.getTarget();
|
||||
mark(exp);
|
||||
if (!(target instanceof Class)) {
|
||||
statementList(target).add(exp);
|
||||
// Pending: Why does the reference count need to
|
||||
// be incremented here?
|
||||
d.refs++;
|
||||
}
|
||||
}
|
||||
|
||||
private void mark(Statement stm) {
|
||||
Object[] args = stm.getArguments();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
Object arg = args[i];
|
||||
mark(arg, true);
|
||||
}
|
||||
mark(stm.getTarget(), stm instanceof Expression);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Records the Statement so that the Encoder will
|
||||
* produce the actual output when the stream is flushed.
|
||||
* <P>
|
||||
* This method should only be invoked within the context
|
||||
* of initializing a persistence delegate.
|
||||
*
|
||||
* @param oldStm The statement that will be written
|
||||
* to the stream.
|
||||
* @see java.beans.PersistenceDelegate#initialize
|
||||
*/
|
||||
public void writeStatement(Statement oldStm) {
|
||||
// System.out.println("XMLEncoder::writeStatement: " + oldStm);
|
||||
boolean internal = this.internal;
|
||||
this.internal = true;
|
||||
try {
|
||||
super.writeStatement(oldStm);
|
||||
/*
|
||||
Note we must do the mark first as we may
|
||||
require the results of previous values in
|
||||
this context for this statement.
|
||||
Test case is:
|
||||
os.setOwner(this);
|
||||
os.writeObject(this);
|
||||
*/
|
||||
mark(oldStm);
|
||||
Object target = oldStm.getTarget();
|
||||
if (target instanceof Field) {
|
||||
String method = oldStm.getMethodName();
|
||||
Object[] args = oldStm.getArguments();
|
||||
if ((method == null) || (args == null)) {
|
||||
}
|
||||
else if (method.equals("get") && (args.length == 1)) {
|
||||
target = args[0];
|
||||
}
|
||||
else if (method.equals("set") && (args.length == 2)) {
|
||||
target = args[0];
|
||||
}
|
||||
}
|
||||
statementList(target).add(oldStm);
|
||||
}
|
||||
catch (Exception e) {
|
||||
getExceptionListener().exceptionThrown(new Exception("XMLEncoder: discarding statement " + oldStm, e));
|
||||
}
|
||||
this.internal = internal;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Records the Expression so that the Encoder will
|
||||
* produce the actual output when the stream is flushed.
|
||||
* <P>
|
||||
* This method should only be invoked within the context of
|
||||
* initializing a persistence delegate or setting up an encoder to
|
||||
* read from a resource bundle.
|
||||
* <P>
|
||||
* For more information about using resource bundles with the
|
||||
* XMLEncoder, see
|
||||
* http://java.sun.com/products/jfc/tsc/articles/persistence4/#i18n
|
||||
*
|
||||
* @param oldExp The expression that will be written
|
||||
* to the stream.
|
||||
* @see java.beans.PersistenceDelegate#initialize
|
||||
*/
|
||||
public void writeExpression(Expression oldExp) {
|
||||
boolean internal = this.internal;
|
||||
this.internal = true;
|
||||
Object oldValue = getValue(oldExp);
|
||||
if (get(oldValue) == null || (oldValue instanceof String && !internal)) {
|
||||
getValueData(oldValue).exp = oldExp;
|
||||
super.writeExpression(oldExp);
|
||||
}
|
||||
this.internal = internal;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method writes out the preamble associated with the
|
||||
* XML encoding if it has not been written already and
|
||||
* then writes out all of the values that been
|
||||
* written to the stream since the last time <code>flush</code>
|
||||
* was called. After flushing, all internal references to the
|
||||
* values that were written to this stream are cleared.
|
||||
*/
|
||||
public void flush() {
|
||||
if (!preambleWritten) { // Don't do this in constructor - it throws ... pending.
|
||||
if (this.declaration) {
|
||||
writeln("<?xml version=" + quote("1.0") +
|
||||
" encoding=" + quote(this.charset) + "?>");
|
||||
}
|
||||
writeln("<java version=" + quote(System.getProperty("java.version")) +
|
||||
" class=" + quote(XMLDecoder.class.getName()) + ">");
|
||||
preambleWritten = true;
|
||||
}
|
||||
indentation++;
|
||||
List<Statement> statements = statementList(this);
|
||||
while (!statements.isEmpty()) {
|
||||
Statement s = statements.remove(0);
|
||||
if ("writeObject".equals(s.getMethodName())) {
|
||||
outputValue(s.getArguments()[0], this, true);
|
||||
}
|
||||
else {
|
||||
outputStatement(s, this, false);
|
||||
}
|
||||
}
|
||||
indentation--;
|
||||
|
||||
Statement statement = getMissedStatement();
|
||||
while (statement != null) {
|
||||
outputStatement(statement, this, false);
|
||||
statement = getMissedStatement();
|
||||
}
|
||||
|
||||
try {
|
||||
out.flush();
|
||||
}
|
||||
catch (IOException e) {
|
||||
getExceptionListener().exceptionThrown(e);
|
||||
}
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
super.clear();
|
||||
nameGenerator.clear();
|
||||
valueToExpression.clear();
|
||||
targetToStatementList.clear();
|
||||
}
|
||||
|
||||
Statement getMissedStatement() {
|
||||
for (List<Statement> statements : this.targetToStatementList.values()) {
|
||||
for (int i = 0; i < statements.size(); i++) {
|
||||
if (Statement.class == statements.get(i).getClass()) {
|
||||
return statements.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method calls <code>flush</code>, writes the closing
|
||||
* postamble and then closes the output stream associated
|
||||
* with this stream.
|
||||
*/
|
||||
public void close() {
|
||||
flush();
|
||||
writeln("</java>");
|
||||
try {
|
||||
out.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
getExceptionListener().exceptionThrown(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String quote(String s) {
|
||||
return "\"" + s + "\"";
|
||||
}
|
||||
|
||||
private ValueData getValueData(Object o) {
|
||||
ValueData d = valueToExpression.get(o);
|
||||
if (d == null) {
|
||||
d = new ValueData();
|
||||
valueToExpression.put(o, d);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the argument,
|
||||
* a Unicode code point, is valid in XML documents.
|
||||
* Unicode characters fit into the low sixteen bits of a Unicode code point,
|
||||
* and pairs of Unicode <em>surrogate characters</em> can be combined
|
||||
* to encode Unicode code point in documents containing only Unicode.
|
||||
* (The <code>char</code> datatype in the Java Programming Language
|
||||
* represents Unicode characters, including unpaired surrogates.)
|
||||
* <par>
|
||||
* [2] Char ::= #x0009 | #x000A | #x000D
|
||||
* | [#x0020-#xD7FF]
|
||||
* | [#xE000-#xFFFD]
|
||||
* | [#x10000-#x10ffff]
|
||||
* </par>
|
||||
*
|
||||
* @param code the 32-bit Unicode code point being tested
|
||||
* @return <code>true</code> if the Unicode code point is valid,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
private static boolean isValidCharCode(int code) {
|
||||
return (0x0020 <= code && code <= 0xD7FF)
|
||||
|| (0x000A == code)
|
||||
|| (0x0009 == code)
|
||||
|| (0x000D == code)
|
||||
|| (0xE000 <= code && code <= 0xFFFD)
|
||||
|| (0x10000 <= code && code <= 0x10ffff);
|
||||
}
|
||||
|
||||
private void writeln(String exp) {
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(int i = 0; i < indentation; i++) {
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append(exp);
|
||||
sb.append('\n');
|
||||
this.out.write(sb.toString());
|
||||
}
|
||||
catch (IOException e) {
|
||||
getExceptionListener().exceptionThrown(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void outputValue(Object value, Object outer, boolean isArgument) {
|
||||
if (value == null) {
|
||||
writeln("<null/>");
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof Class) {
|
||||
writeln("<class>" + ((Class)value).getName() + "</class>");
|
||||
return;
|
||||
}
|
||||
|
||||
ValueData d = getValueData(value);
|
||||
if (d.exp != null) {
|
||||
Object target = d.exp.getTarget();
|
||||
String methodName = d.exp.getMethodName();
|
||||
|
||||
if (target == null || methodName == null) {
|
||||
throw new NullPointerException((target == null ? "target" :
|
||||
"methodName") + " should not be null");
|
||||
}
|
||||
|
||||
if (isArgument && target instanceof Field && methodName.equals("get")) {
|
||||
Field f = (Field) target;
|
||||
if (Modifier.isStatic(f.getModifiers())) {
|
||||
writeln("<object class=" + quote(f.getDeclaringClass().getName()) +
|
||||
" field=" + quote(f.getName()) + "/>");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> primitiveType = primitiveTypeFor(value.getClass());
|
||||
if (primitiveType != null && target == value.getClass() &&
|
||||
methodName.equals("new")) {
|
||||
String primitiveTypeName = primitiveType.getName();
|
||||
// Make sure that character types are quoted correctly.
|
||||
if (primitiveType == Character.TYPE) {
|
||||
char code = ((Character) value).charValue();
|
||||
if (!isValidCharCode(code)) {
|
||||
writeln(createString(code));
|
||||
return;
|
||||
}
|
||||
value = quoteCharCode(code);
|
||||
if (value == null) {
|
||||
value = Character.valueOf(code);
|
||||
}
|
||||
}
|
||||
writeln("<" + primitiveTypeName + ">" + value + "</" +
|
||||
primitiveTypeName + ">");
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (value instanceof String) {
|
||||
writeln(createString((String) value));
|
||||
return;
|
||||
}
|
||||
|
||||
if (d.name != null) {
|
||||
if (isArgument) {
|
||||
writeln("<object idref=" + quote(d.name) + "/>");
|
||||
}
|
||||
else {
|
||||
outputXML("void", " idref=" + quote(d.name), value);
|
||||
}
|
||||
}
|
||||
else if (d.exp != null) {
|
||||
outputStatement(d.exp, outer, isArgument);
|
||||
}
|
||||
}
|
||||
|
||||
private static String quoteCharCode(int code) {
|
||||
switch(code) {
|
||||
case '&': return "&";
|
||||
case '<': return "<";
|
||||
case '>': return ">";
|
||||
case '"': return """;
|
||||
case '\'': return "'";
|
||||
case '\r': return " ";
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String createString(int code) {
|
||||
return "<char code=\"#" + Integer.toString(code, 16) + "\"/>";
|
||||
}
|
||||
|
||||
private String createString(String string) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("<string>");
|
||||
int index = 0;
|
||||
while (index < string.length()) {
|
||||
int point = string.codePointAt(index);
|
||||
int count = Character.charCount(point);
|
||||
|
||||
if (isValidCharCode(point) && this.encoder.canEncode(string.substring(index, index + count))) {
|
||||
String value = quoteCharCode(point);
|
||||
if (value != null) {
|
||||
sb.append(value);
|
||||
} else {
|
||||
sb.appendCodePoint(point);
|
||||
}
|
||||
index += count;
|
||||
} else {
|
||||
sb.append(createString(string.charAt(index)));
|
||||
index++;
|
||||
}
|
||||
}
|
||||
sb.append("</string>");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void outputStatement(Statement exp, Object outer, boolean isArgument) {
|
||||
Object target = exp.getTarget();
|
||||
String methodName = exp.getMethodName();
|
||||
|
||||
if (target == null || methodName == null) {
|
||||
throw new NullPointerException((target == null ? "target" :
|
||||
"methodName") + " should not be null");
|
||||
}
|
||||
|
||||
Object[] args = exp.getArguments();
|
||||
boolean expression = exp.getClass() == Expression.class;
|
||||
Object value = (expression) ? getValue((Expression)exp) : null;
|
||||
|
||||
String tag = (expression && isArgument) ? "object" : "void";
|
||||
String attributes = "";
|
||||
ValueData d = getValueData(value);
|
||||
|
||||
// Special cases for targets.
|
||||
if (target == outer) {
|
||||
}
|
||||
else if (target == Array.class && methodName.equals("newInstance")) {
|
||||
tag = "array";
|
||||
attributes = attributes + " class=" + quote(((Class)args[0]).getName());
|
||||
attributes = attributes + " length=" + quote(args[1].toString());
|
||||
args = new Object[]{};
|
||||
}
|
||||
else if (target.getClass() == Class.class) {
|
||||
attributes = attributes + " class=" + quote(((Class)target).getName());
|
||||
}
|
||||
else {
|
||||
d.refs = 2;
|
||||
if (d.name == null) {
|
||||
getValueData(target).refs++;
|
||||
List<Statement> statements = statementList(target);
|
||||
if (!statements.contains(exp)) {
|
||||
statements.add(exp);
|
||||
}
|
||||
outputValue(target, outer, false);
|
||||
}
|
||||
if (expression) {
|
||||
outputValue(value, outer, isArgument);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (expression && (d.refs > 1)) {
|
||||
String instanceName = nameGenerator.instanceName(value);
|
||||
d.name = instanceName;
|
||||
attributes = attributes + " id=" + quote(instanceName);
|
||||
}
|
||||
|
||||
// Special cases for methods.
|
||||
if ((!expression && methodName.equals("set") && args.length == 2 &&
|
||||
args[0] instanceof Integer) ||
|
||||
(expression && methodName.equals("get") && args.length == 1 &&
|
||||
args[0] instanceof Integer)) {
|
||||
attributes = attributes + " index=" + quote(args[0].toString());
|
||||
args = (args.length == 1) ? new Object[]{} : new Object[]{args[1]};
|
||||
}
|
||||
else if ((!expression && methodName.startsWith("set") && args.length == 1) ||
|
||||
(expression && methodName.startsWith("get") && args.length == 0)) {
|
||||
if (3 < methodName.length()) {
|
||||
attributes = attributes + " property=" +
|
||||
quote(Introspector.decapitalize(methodName.substring(3)));
|
||||
}
|
||||
}
|
||||
else if (!methodName.equals("new") && !methodName.equals("newInstance")) {
|
||||
attributes = attributes + " method=" + quote(methodName);
|
||||
}
|
||||
outputXML(tag, attributes, value, args);
|
||||
}
|
||||
|
||||
private void outputXML(String tag, String attributes, Object value, Object... args) {
|
||||
List<Statement> statements = statementList(value);
|
||||
// Use XML's short form when there is no body.
|
||||
if (args.length == 0 && statements.size() == 0) {
|
||||
writeln("<" + tag + attributes + "/>");
|
||||
return;
|
||||
}
|
||||
|
||||
writeln("<" + tag + attributes + ">");
|
||||
indentation++;
|
||||
|
||||
for(int i = 0; i < args.length; i++) {
|
||||
outputValue(args[i], null, true);
|
||||
}
|
||||
|
||||
while (!statements.isEmpty()) {
|
||||
Statement s = statements.remove(0);
|
||||
outputStatement(s, value, false);
|
||||
}
|
||||
|
||||
indentation--;
|
||||
writeln("</" + tag + ">");
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
static Class primitiveTypeFor(Class wrapper) {
|
||||
if (wrapper == Boolean.class) return Boolean.TYPE;
|
||||
if (wrapper == Byte.class) return Byte.TYPE;
|
||||
if (wrapper == Character.class) return Character.TYPE;
|
||||
if (wrapper == Short.class) return Short.TYPE;
|
||||
if (wrapper == Integer.class) return Integer.TYPE;
|
||||
if (wrapper == Long.class) return Long.TYPE;
|
||||
if (wrapper == Float.class) return Float.TYPE;
|
||||
if (wrapper == Double.class) return Double.TYPE;
|
||||
if (wrapper == Void.class) return Void.TYPE;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
135
jdkSrc/jdk8/java/beans/beancontext/BeanContext.java
Normal file
135
jdkSrc/jdk8/java/beans/beancontext/BeanContext.java
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, 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.beancontext;
|
||||
|
||||
import java.beans.DesignMode;
|
||||
import java.beans.Visibility;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* The BeanContext acts a logical hierarchical container for JavaBeans.
|
||||
* </p>
|
||||
*
|
||||
* @author Laurence P. G. Cable
|
||||
* @since 1.2
|
||||
*
|
||||
* @see java.beans.Beans
|
||||
* @see java.beans.beancontext.BeanContextChild
|
||||
* @see java.beans.beancontext.BeanContextMembershipListener
|
||||
* @see java.beans.PropertyChangeEvent
|
||||
* @see java.beans.DesignMode
|
||||
* @see java.beans.Visibility
|
||||
* @see java.util.Collection
|
||||
*/
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public interface BeanContext extends BeanContextChild, Collection, DesignMode, Visibility {
|
||||
|
||||
/**
|
||||
* Instantiate the javaBean named as a
|
||||
* child of this <code>BeanContext</code>.
|
||||
* The implementation of the JavaBean is
|
||||
* derived from the value of the beanName parameter,
|
||||
* and is defined by the
|
||||
* <code>java.beans.Beans.instantiate()</code> method.
|
||||
*
|
||||
* @return a javaBean named as a child of this
|
||||
* <code>BeanContext</code>
|
||||
* @param beanName The name of the JavaBean to instantiate
|
||||
* as a child of this <code>BeanContext</code>
|
||||
* @throws IOException if an IO problem occurs
|
||||
* @throws ClassNotFoundException if the class identified
|
||||
* by the beanName parameter is not found
|
||||
*/
|
||||
Object instantiateChild(String beanName) throws IOException, ClassNotFoundException;
|
||||
|
||||
/**
|
||||
* Analagous to <code>java.lang.ClassLoader.getResourceAsStream()</code>,
|
||||
* this method allows a <code>BeanContext</code> implementation
|
||||
* to interpose behavior between the child <code>Component</code>
|
||||
* and underlying <code>ClassLoader</code>.
|
||||
*
|
||||
* @param name the resource name
|
||||
* @param bcc the specified child
|
||||
* @return an <code>InputStream</code> for reading the resource,
|
||||
* or <code>null</code> if the resource could not
|
||||
* be found.
|
||||
* @throws IllegalArgumentException if
|
||||
* the resource is not valid
|
||||
*/
|
||||
InputStream getResourceAsStream(String name, BeanContextChild bcc) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Analagous to <code>java.lang.ClassLoader.getResource()</code>, this
|
||||
* method allows a <code>BeanContext</code> implementation to interpose
|
||||
* behavior between the child <code>Component</code>
|
||||
* and underlying <code>ClassLoader</code>.
|
||||
*
|
||||
* @param name the resource name
|
||||
* @param bcc the specified child
|
||||
* @return a <code>URL</code> for the named
|
||||
* resource for the specified child
|
||||
* @throws IllegalArgumentException
|
||||
* if the resource is not valid
|
||||
*/
|
||||
URL getResource(String name, BeanContextChild bcc) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Adds the specified <code>BeanContextMembershipListener</code>
|
||||
* to receive <code>BeanContextMembershipEvents</code> from
|
||||
* this <code>BeanContext</code> whenever it adds
|
||||
* or removes a child <code>Component</code>(s).
|
||||
*
|
||||
* @param bcml the BeanContextMembershipListener to be added
|
||||
*/
|
||||
void addBeanContextMembershipListener(BeanContextMembershipListener bcml);
|
||||
|
||||
/**
|
||||
* Removes the specified <code>BeanContextMembershipListener</code>
|
||||
* so that it no longer receives <code>BeanContextMembershipEvent</code>s
|
||||
* when the child <code>Component</code>(s) are added or removed.
|
||||
*
|
||||
* @param bcml the <code>BeanContextMembershipListener</code>
|
||||
* to be removed
|
||||
*/
|
||||
void removeBeanContextMembershipListener(BeanContextMembershipListener bcml);
|
||||
|
||||
/**
|
||||
* This global lock is used by both <code>BeanContext</code>
|
||||
* and <code>BeanContextServices</code> implementors
|
||||
* to serialize changes in a <code>BeanContext</code>
|
||||
* hierarchy and any service requests etc.
|
||||
*/
|
||||
public static final Object globalHierarchyLock = new Object();
|
||||
}
|
||||
137
jdkSrc/jdk8/java/beans/beancontext/BeanContextChild.java
Normal file
137
jdkSrc/jdk8/java/beans/beancontext/BeanContextChild.java
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, 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.beancontext;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.VetoableChangeListener;
|
||||
import java.beans.PropertyVetoException;
|
||||
|
||||
import java.beans.beancontext.BeanContext;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* JavaBeans wishing to be nested within, and obtain a reference to their
|
||||
* execution environment, or context, as defined by the BeanContext
|
||||
* sub-interface shall implement this interface.
|
||||
* </p>
|
||||
* <p>
|
||||
* Conformant BeanContexts shall as a side effect of adding a BeanContextChild
|
||||
* object shall pass a reference to itself via the setBeanContext() method of
|
||||
* this interface.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that a BeanContextChild may refuse a change in state by throwing
|
||||
* PropertyVetoedException in response.
|
||||
* </p>
|
||||
* <p>
|
||||
* In order for persistence mechanisms to function properly on BeanContextChild
|
||||
* instances across a broad variety of scenarios, implementing classes of this
|
||||
* interface are required to define as transient, any or all fields, or
|
||||
* instance variables, that may contain, or represent, references to the
|
||||
* nesting BeanContext instance or other resources obtained
|
||||
* from the BeanContext via any unspecified mechanisms.
|
||||
* </p>
|
||||
*
|
||||
* @author Laurence P. G. Cable
|
||||
* @since 1.2
|
||||
*
|
||||
* @see java.beans.beancontext.BeanContext
|
||||
* @see java.beans.PropertyChangeEvent
|
||||
* @see java.beans.PropertyChangeListener
|
||||
* @see java.beans.PropertyVetoException
|
||||
* @see java.beans.VetoableChangeListener
|
||||
*/
|
||||
|
||||
public interface BeanContextChild {
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Objects that implement this interface,
|
||||
* shall fire a java.beans.PropertyChangeEvent, with parameters:
|
||||
*
|
||||
* propertyName "beanContext", oldValue (the previous nesting
|
||||
* <code>BeanContext</code> instance, or <code>null</code>),
|
||||
* newValue (the current nesting
|
||||
* <code>BeanContext</code> instance, or <code>null</code>).
|
||||
* <p>
|
||||
* A change in the value of the nesting BeanContext property of this
|
||||
* BeanContextChild may be vetoed by throwing the appropriate exception.
|
||||
* </p>
|
||||
* @param bc The <code>BeanContext</code> with which
|
||||
* to associate this <code>BeanContextChild</code>.
|
||||
* @throws PropertyVetoException if the
|
||||
* addition of the specified <code>BeanContext</code> is refused.
|
||||
*/
|
||||
void setBeanContext(BeanContext bc) throws PropertyVetoException;
|
||||
|
||||
/**
|
||||
* Gets the <code>BeanContext</code> associated
|
||||
* with this <code>BeanContextChild</code>.
|
||||
* @return the <code>BeanContext</code> associated
|
||||
* with this <code>BeanContextChild</code>.
|
||||
*/
|
||||
BeanContext getBeanContext();
|
||||
|
||||
/**
|
||||
* Adds a <code>PropertyChangeListener</code>
|
||||
* to this <code>BeanContextChild</code>
|
||||
* in order to receive a <code>PropertyChangeEvent</code>
|
||||
* whenever the specified property has changed.
|
||||
* @param name the name of the property to listen on
|
||||
* @param pcl the <code>PropertyChangeListener</code> to add
|
||||
*/
|
||||
void addPropertyChangeListener(String name, PropertyChangeListener pcl);
|
||||
|
||||
/**
|
||||
* Removes a <code>PropertyChangeListener</code> from this
|
||||
* <code>BeanContextChild</code> so that it no longer
|
||||
* receives <code>PropertyChangeEvents</code> when the
|
||||
* specified property is changed.
|
||||
*
|
||||
* @param name the name of the property that was listened on
|
||||
* @param pcl the <code>PropertyChangeListener</code> to remove
|
||||
*/
|
||||
void removePropertyChangeListener(String name, PropertyChangeListener pcl);
|
||||
|
||||
/**
|
||||
* Adds a <code>VetoableChangeListener</code> to
|
||||
* this <code>BeanContextChild</code>
|
||||
* to receive events whenever the specified property changes.
|
||||
* @param name the name of the property to listen on
|
||||
* @param vcl the <code>VetoableChangeListener</code> to add
|
||||
*/
|
||||
void addVetoableChangeListener(String name, VetoableChangeListener vcl);
|
||||
|
||||
/**
|
||||
* Removes a <code>VetoableChangeListener</code> from this
|
||||
* <code>BeanContextChild</code> so that it no longer receives
|
||||
* events when the specified property changes.
|
||||
* @param name the name of the property that was listened on.
|
||||
* @param vcl the <code>VetoableChangeListener</code> to remove.
|
||||
*/
|
||||
void removeVetoableChangeListener(String name, VetoableChangeListener vcl);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2002, 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.beancontext;
|
||||
|
||||
import java.awt.Component;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This interface is implemented by
|
||||
* <code>BeanContextChildren</code> that have an AWT <code>Component</code>
|
||||
* associated with them.
|
||||
* </p>
|
||||
*
|
||||
* @author Laurence P. G. Cable
|
||||
* @since 1.2
|
||||
*
|
||||
* @see java.beans.beancontext.BeanContext
|
||||
* @see java.beans.beancontext.BeanContextSupport
|
||||
*/
|
||||
|
||||
public interface BeanContextChildComponentProxy {
|
||||
|
||||
/**
|
||||
* Gets the <code>java.awt.Component</code> associated with
|
||||
* this <code>BeanContextChild</code>.
|
||||
* @return the AWT <code>Component</code> associated with
|
||||
* this <code>BeanContextChild</code>
|
||||
*/
|
||||
|
||||
Component getComponent();
|
||||
}
|
||||
377
jdkSrc/jdk8/java/beans/beancontext/BeanContextChildSupport.java
Normal file
377
jdkSrc/jdk8/java/beans/beancontext/BeanContextChildSupport.java
Normal file
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2013, 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.beancontext;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
|
||||
import java.beans.VetoableChangeListener;
|
||||
import java.beans.VetoableChangeSupport;
|
||||
|
||||
import java.beans.PropertyVetoException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a general support class to provide support for implementing the
|
||||
* BeanContextChild protocol.
|
||||
*
|
||||
* This class may either be directly subclassed, or encapsulated and delegated
|
||||
* to in order to implement this interface for a given component.
|
||||
* </p>
|
||||
*
|
||||
* @author Laurence P. G. Cable
|
||||
* @since 1.2
|
||||
*
|
||||
* @see java.beans.beancontext.BeanContext
|
||||
* @see java.beans.beancontext.BeanContextServices
|
||||
* @see java.beans.beancontext.BeanContextChild
|
||||
*/
|
||||
|
||||
public class BeanContextChildSupport implements BeanContextChild, BeanContextServicesListener, Serializable {
|
||||
|
||||
static final long serialVersionUID = 6328947014421475877L;
|
||||
|
||||
/**
|
||||
* construct a BeanContextChildSupport where this class has been
|
||||
* subclassed in order to implement the JavaBean component itself.
|
||||
*/
|
||||
|
||||
public BeanContextChildSupport() {
|
||||
super();
|
||||
|
||||
beanContextChildPeer = this;
|
||||
|
||||
pcSupport = new PropertyChangeSupport(beanContextChildPeer);
|
||||
vcSupport = new VetoableChangeSupport(beanContextChildPeer);
|
||||
}
|
||||
|
||||
/**
|
||||
* construct a BeanContextChildSupport where the JavaBean component
|
||||
* itself implements BeanContextChild, and encapsulates this, delegating
|
||||
* that interface to this implementation
|
||||
* @param bcc the underlying bean context child
|
||||
*/
|
||||
|
||||
public BeanContextChildSupport(BeanContextChild bcc) {
|
||||
super();
|
||||
|
||||
beanContextChildPeer = (bcc != null) ? bcc : this;
|
||||
|
||||
pcSupport = new PropertyChangeSupport(beanContextChildPeer);
|
||||
vcSupport = new VetoableChangeSupport(beanContextChildPeer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <code>BeanContext</code> for
|
||||
* this <code>BeanContextChildSupport</code>.
|
||||
* @param bc the new value to be assigned to the <code>BeanContext</code>
|
||||
* property
|
||||
* @throws PropertyVetoException if the change is rejected
|
||||
*/
|
||||
public synchronized void setBeanContext(BeanContext bc) throws PropertyVetoException {
|
||||
if (bc == beanContext) return;
|
||||
|
||||
BeanContext oldValue = beanContext;
|
||||
BeanContext newValue = bc;
|
||||
|
||||
if (!rejectedSetBCOnce) {
|
||||
if (rejectedSetBCOnce = !validatePendingSetBeanContext(bc)) {
|
||||
throw new PropertyVetoException(
|
||||
"setBeanContext() change rejected:",
|
||||
new PropertyChangeEvent(beanContextChildPeer, "beanContext", oldValue, newValue)
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
fireVetoableChange("beanContext",
|
||||
oldValue,
|
||||
newValue
|
||||
);
|
||||
} catch (PropertyVetoException pve) {
|
||||
rejectedSetBCOnce = true;
|
||||
|
||||
throw pve; // re-throw
|
||||
}
|
||||
}
|
||||
|
||||
if (beanContext != null) releaseBeanContextResources();
|
||||
|
||||
beanContext = newValue;
|
||||
rejectedSetBCOnce = false;
|
||||
|
||||
firePropertyChange("beanContext",
|
||||
oldValue,
|
||||
newValue
|
||||
);
|
||||
|
||||
if (beanContext != null) initializeBeanContextResources();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the nesting <code>BeanContext</code>
|
||||
* for this <code>BeanContextChildSupport</code>.
|
||||
* @return the nesting <code>BeanContext</code> for
|
||||
* this <code>BeanContextChildSupport</code>.
|
||||
*/
|
||||
public synchronized BeanContext getBeanContext() { return beanContext; }
|
||||
|
||||
/**
|
||||
* Add a PropertyChangeListener for a specific property.
|
||||
* The same listener object may be added more than once. For each
|
||||
* property, the listener will be invoked the number of times it was added
|
||||
* for that property.
|
||||
* If <code>name</code> or <code>pcl</code> is null, no exception is thrown
|
||||
* and no action is taken.
|
||||
*
|
||||
* @param name The name of the property to listen on
|
||||
* @param pcl The <code>PropertyChangeListener</code> to be added
|
||||
*/
|
||||
public void addPropertyChangeListener(String name, PropertyChangeListener pcl) {
|
||||
pcSupport.addPropertyChangeListener(name, pcl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a PropertyChangeListener for a specific property.
|
||||
* If <code>pcl</code> was added more than once to the same event
|
||||
* source for the specified property, it will be notified one less time
|
||||
* after being removed.
|
||||
* If <code>name</code> is null, no exception is thrown
|
||||
* and no action is taken.
|
||||
* If <code>pcl</code> is null, or was never added for the specified
|
||||
* property, no exception is thrown and no action is taken.
|
||||
*
|
||||
* @param name The name of the property that was listened on
|
||||
* @param pcl The PropertyChangeListener to be removed
|
||||
*/
|
||||
public void removePropertyChangeListener(String name, PropertyChangeListener pcl) {
|
||||
pcSupport.removePropertyChangeListener(name, pcl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a VetoableChangeListener for a specific property.
|
||||
* The same listener object may be added more than once. For each
|
||||
* property, the listener will be invoked the number of times it was added
|
||||
* for that property.
|
||||
* If <code>name</code> or <code>vcl</code> is null, no exception is thrown
|
||||
* and no action is taken.
|
||||
*
|
||||
* @param name The name of the property to listen on
|
||||
* @param vcl The <code>VetoableChangeListener</code> to be added
|
||||
*/
|
||||
public void addVetoableChangeListener(String name, VetoableChangeListener vcl) {
|
||||
vcSupport.addVetoableChangeListener(name, vcl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a <code>VetoableChangeListener</code>.
|
||||
* If <code>pcl</code> was added more than once to the same event
|
||||
* source for the specified property, it will be notified one less time
|
||||
* after being removed.
|
||||
* If <code>name</code> is null, no exception is thrown
|
||||
* and no action is taken.
|
||||
* If <code>vcl</code> is null, or was never added for the specified
|
||||
* property, no exception is thrown and no action is taken.
|
||||
*
|
||||
* @param name The name of the property that was listened on
|
||||
* @param vcl The <code>VetoableChangeListener</code> to be removed
|
||||
*/
|
||||
public void removeVetoableChangeListener(String name, VetoableChangeListener vcl) {
|
||||
vcSupport.removeVetoableChangeListener(name, vcl);
|
||||
}
|
||||
|
||||
/**
|
||||
* A service provided by the nesting BeanContext has been revoked.
|
||||
*
|
||||
* Subclasses may override this method in order to implement their own
|
||||
* behaviors.
|
||||
* @param bcsre The <code>BeanContextServiceRevokedEvent</code> fired as a
|
||||
* result of a service being revoked
|
||||
*/
|
||||
public void serviceRevoked(BeanContextServiceRevokedEvent bcsre) { }
|
||||
|
||||
/**
|
||||
* A new service is available from the nesting BeanContext.
|
||||
*
|
||||
* Subclasses may override this method in order to implement their own
|
||||
* behaviors
|
||||
* @param bcsae The BeanContextServiceAvailableEvent fired as a
|
||||
* result of a service becoming available
|
||||
*
|
||||
*/
|
||||
public void serviceAvailable(BeanContextServiceAvailableEvent bcsae) { }
|
||||
|
||||
/**
|
||||
* Gets the <tt>BeanContextChild</tt> associated with this
|
||||
* <tt>BeanContextChildSupport</tt>.
|
||||
*
|
||||
* @return the <tt>BeanContextChild</tt> peer of this class
|
||||
*/
|
||||
public BeanContextChild getBeanContextChildPeer() { return beanContextChildPeer; }
|
||||
|
||||
/**
|
||||
* Reports whether or not this class is a delegate of another.
|
||||
*
|
||||
* @return true if this class is a delegate of another
|
||||
*/
|
||||
public boolean isDelegated() { return !this.equals(beanContextChildPeer); }
|
||||
|
||||
/**
|
||||
* Report a bound property update to any registered listeners. No event is
|
||||
* fired if old and new are equal and non-null.
|
||||
* @param name The programmatic name of the property that was changed
|
||||
* @param oldValue The old value of the property
|
||||
* @param newValue The new value of the property
|
||||
*/
|
||||
public void firePropertyChange(String name, Object oldValue, Object newValue) {
|
||||
pcSupport.firePropertyChange(name, oldValue, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a vetoable property update to any registered listeners.
|
||||
* If anyone vetos the change, then fire a new event
|
||||
* reverting everyone to the old value and then rethrow
|
||||
* the PropertyVetoException. <P>
|
||||
*
|
||||
* No event is fired if old and new are equal and non-null.
|
||||
* <P>
|
||||
* @param name The programmatic name of the property that is about to
|
||||
* change
|
||||
*
|
||||
* @param oldValue The old value of the property
|
||||
* @param newValue - The new value of the property
|
||||
*
|
||||
* @throws PropertyVetoException if the recipient wishes the property
|
||||
* change to be rolled back.
|
||||
*/
|
||||
public void fireVetoableChange(String name, Object oldValue, Object newValue) throws PropertyVetoException {
|
||||
vcSupport.fireVetoableChange(name, oldValue, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from setBeanContext to validate (or otherwise) the
|
||||
* pending change in the nesting BeanContext property value.
|
||||
* Returning false will cause setBeanContext to throw
|
||||
* PropertyVetoException.
|
||||
* @param newValue the new value that has been requested for
|
||||
* the BeanContext property
|
||||
* @return <code>true</code> if the change operation is to be vetoed
|
||||
*/
|
||||
public boolean validatePendingSetBeanContext(BeanContext newValue) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method may be overridden by subclasses to provide their own
|
||||
* release behaviors. When invoked any resources held by this instance
|
||||
* obtained from its current BeanContext property should be released
|
||||
* since the object is no longer nested within that BeanContext.
|
||||
*/
|
||||
|
||||
protected void releaseBeanContextResources() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* This method may be overridden by subclasses to provide their own
|
||||
* initialization behaviors. When invoked any resources required by the
|
||||
* BeanContextChild should be obtained from the current BeanContext.
|
||||
*/
|
||||
|
||||
protected void initializeBeanContextResources() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the persistence state of the object.
|
||||
*/
|
||||
|
||||
private void writeObject(ObjectOutputStream oos) throws IOException {
|
||||
|
||||
/*
|
||||
* don't serialize if we are delegated and the delegator is not also
|
||||
* serializable.
|
||||
*/
|
||||
|
||||
if (!equals(beanContextChildPeer) && !(beanContextChildPeer instanceof Serializable))
|
||||
throw new IOException("BeanContextChildSupport beanContextChildPeer not Serializable");
|
||||
|
||||
else
|
||||
oos.defaultWriteObject();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Restore a persistent object, must wait for subsequent setBeanContext()
|
||||
* to fully restore any resources obtained from the new nesting
|
||||
* BeanContext
|
||||
*/
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
ois.defaultReadObject();
|
||||
}
|
||||
|
||||
/*
|
||||
* fields
|
||||
*/
|
||||
|
||||
/**
|
||||
* The <code>BeanContext</code> in which
|
||||
* this <code>BeanContextChild</code> is nested.
|
||||
*/
|
||||
public BeanContextChild beanContextChildPeer;
|
||||
|
||||
/**
|
||||
* The <tt>PropertyChangeSupport</tt> associated with this
|
||||
* <tt>BeanContextChildSupport</tt>.
|
||||
*/
|
||||
protected PropertyChangeSupport pcSupport;
|
||||
|
||||
/**
|
||||
* The <tt>VetoableChangeSupport</tt> associated with this
|
||||
* <tt>BeanContextChildSupport</tt>.
|
||||
*/
|
||||
protected VetoableChangeSupport vcSupport;
|
||||
|
||||
/**
|
||||
* The bean context.
|
||||
*/
|
||||
protected transient BeanContext beanContext;
|
||||
|
||||
/**
|
||||
* A flag indicating that there has been
|
||||
* at least one <code>PropertyChangeVetoException</code>
|
||||
* thrown for the attempted setBeanContext operation.
|
||||
*/
|
||||
protected transient boolean rejectedSetBCOnce;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2002, 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.beancontext;
|
||||
|
||||
import java.awt.Container;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This interface is implemented by BeanContexts' that have an AWT Container
|
||||
* associated with them.
|
||||
* </p>
|
||||
*
|
||||
* @author Laurence P. G. Cable
|
||||
* @since 1.2
|
||||
*
|
||||
* @see java.beans.beancontext.BeanContext
|
||||
* @see java.beans.beancontext.BeanContextSupport
|
||||
*/
|
||||
|
||||
public interface BeanContextContainerProxy {
|
||||
|
||||
/**
|
||||
* Gets the <code>java.awt.Container</code> associated
|
||||
* with this <code>BeanContext</code>.
|
||||
* @return the <code>java.awt.Container</code> associated
|
||||
* with this <code>BeanContext</code>.
|
||||
*/
|
||||
Container getContainer();
|
||||
}
|
||||
104
jdkSrc/jdk8/java/beans/beancontext/BeanContextEvent.java
Normal file
104
jdkSrc/jdk8/java/beans/beancontext/BeanContextEvent.java
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2009, 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.beancontext;
|
||||
|
||||
import java.util.EventObject;
|
||||
|
||||
import java.beans.beancontext.BeanContext;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* <code>BeanContextEvent</code> is the abstract root event class
|
||||
* for all events emitted
|
||||
* from, and pertaining to the semantics of, a <code>BeanContext</code>.
|
||||
* This class introduces a mechanism to allow the propagation of
|
||||
* <code>BeanContextEvent</code> subclasses through a hierarchy of
|
||||
* <code>BeanContext</code>s. The <code>setPropagatedFrom()</code>
|
||||
* and <code>getPropagatedFrom()</code> methods allow a
|
||||
* <code>BeanContext</code> to identify itself as the source
|
||||
* of a propagated event.
|
||||
* </p>
|
||||
*
|
||||
* @author Laurence P. G. Cable
|
||||
* @since 1.2
|
||||
* @see java.beans.beancontext.BeanContext
|
||||
*/
|
||||
|
||||
public abstract class BeanContextEvent extends EventObject {
|
||||
private static final long serialVersionUID = 7267998073569045052L;
|
||||
|
||||
/**
|
||||
* Contruct a BeanContextEvent
|
||||
*
|
||||
* @param bc The BeanContext source
|
||||
*/
|
||||
protected BeanContextEvent(BeanContext bc) {
|
||||
super(bc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the <code>BeanContext</code> associated with this event.
|
||||
* @return the <code>BeanContext</code> associated with this event.
|
||||
*/
|
||||
public BeanContext getBeanContext() { return (BeanContext)getSource(); }
|
||||
|
||||
/**
|
||||
* Sets the <code>BeanContext</code> from which this event was propagated.
|
||||
* @param bc the <code>BeanContext</code> from which this event
|
||||
* was propagated
|
||||
*/
|
||||
public synchronized void setPropagatedFrom(BeanContext bc) {
|
||||
propagatedFrom = bc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the <code>BeanContext</code> from which this event was propagated.
|
||||
* @return the <code>BeanContext</code> from which this
|
||||
* event was propagated
|
||||
*/
|
||||
public synchronized BeanContext getPropagatedFrom() {
|
||||
return propagatedFrom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports whether or not this event is
|
||||
* propagated from some other <code>BeanContext</code>.
|
||||
* @return <code>true</code> if propagated, <code>false</code>
|
||||
* if not
|
||||
*/
|
||||
public synchronized boolean isPropagated() {
|
||||
return propagatedFrom != null;
|
||||
}
|
||||
|
||||
/*
|
||||
* fields
|
||||
*/
|
||||
|
||||
/**
|
||||
* The <code>BeanContext</code> from which this event was propagated
|
||||
*/
|
||||
protected BeanContext propagatedFrom;
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, 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.beancontext;
|
||||
|
||||
import java.util.EventObject;
|
||||
|
||||
import java.beans.beancontext.BeanContext;
|
||||
import java.beans.beancontext.BeanContextEvent;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A <code>BeanContextMembershipEvent</code> encapsulates
|
||||
* the list of children added to, or removed from,
|
||||
* the membership of a particular <code>BeanContext</code>.
|
||||
* An instance of this event is fired whenever a successful
|
||||
* add(), remove(), retainAll(), removeAll(), or clear() is
|
||||
* invoked on a given <code>BeanContext</code> instance.
|
||||
* Objects interested in receiving events of this type must
|
||||
* implement the <code>BeanContextMembershipListener</code>
|
||||
* interface, and must register their intent via the
|
||||
* <code>BeanContext</code>'s
|
||||
* <code>addBeanContextMembershipListener(BeanContextMembershipListener bcml)
|
||||
* </code> method.
|
||||
*
|
||||
* @author Laurence P. G. Cable
|
||||
* @since 1.2
|
||||
* @see java.beans.beancontext.BeanContext
|
||||
* @see java.beans.beancontext.BeanContextEvent
|
||||
* @see java.beans.beancontext.BeanContextMembershipListener
|
||||
*/
|
||||
public class BeanContextMembershipEvent extends BeanContextEvent {
|
||||
private static final long serialVersionUID = 3499346510334590959L;
|
||||
|
||||
/**
|
||||
* Contruct a BeanContextMembershipEvent
|
||||
*
|
||||
* @param bc The BeanContext source
|
||||
* @param changes The Children affected
|
||||
* @throws NullPointerException if <CODE>changes</CODE> is <CODE>null</CODE>
|
||||
*/
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public BeanContextMembershipEvent(BeanContext bc, Collection changes) {
|
||||
super(bc);
|
||||
|
||||
if (changes == null) throw new NullPointerException(
|
||||
"BeanContextMembershipEvent constructor: changes is null.");
|
||||
|
||||
children = changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contruct a BeanContextMembershipEvent
|
||||
*
|
||||
* @param bc The BeanContext source
|
||||
* @param changes The Children effected
|
||||
* @exception NullPointerException if changes associated with this
|
||||
* event are null.
|
||||
*/
|
||||
|
||||
public BeanContextMembershipEvent(BeanContext bc, Object[] changes) {
|
||||
super(bc);
|
||||
|
||||
if (changes == null) throw new NullPointerException(
|
||||
"BeanContextMembershipEvent: changes is null.");
|
||||
|
||||
children = Arrays.asList(changes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of children affected by the notification.
|
||||
* @return the number of children affected by the notification
|
||||
*/
|
||||
public int size() { return children.size(); }
|
||||
|
||||
/**
|
||||
* Is the child specified affected by the event?
|
||||
* @return <code>true</code> if affected, <code>false</code>
|
||||
* if not
|
||||
* @param child the object to check for being affected
|
||||
*/
|
||||
public boolean contains(Object child) {
|
||||
return children.contains(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the array of children affected by this event.
|
||||
* @return the array of children affected
|
||||
*/
|
||||
public Object[] toArray() { return children.toArray(); }
|
||||
|
||||
/**
|
||||
* Gets the array of children affected by this event.
|
||||
* @return the array of children effected
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Iterator iterator() { return children.iterator(); }
|
||||
|
||||
/*
|
||||
* fields
|
||||
*/
|
||||
|
||||
/**
|
||||
* The list of children affected by this
|
||||
* event notification.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
protected Collection children;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 1999, 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.beancontext;
|
||||
|
||||
import java.beans.beancontext.BeanContextMembershipEvent;
|
||||
|
||||
import java.util.EventListener;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Compliant BeanContexts fire events on this interface when the state of
|
||||
* the membership of the BeanContext changes.
|
||||
* </p>
|
||||
*
|
||||
* @author Laurence P. G. Cable
|
||||
* @since 1.2
|
||||
* @see java.beans.beancontext.BeanContext
|
||||
*/
|
||||
|
||||
public interface BeanContextMembershipListener extends EventListener {
|
||||
|
||||
/**
|
||||
* Called when a child or list of children is added to a
|
||||
* <code>BeanContext</code> that this listener is registered with.
|
||||
* @param bcme The <code>BeanContextMembershipEvent</code>
|
||||
* describing the change that occurred.
|
||||
*/
|
||||
void childrenAdded(BeanContextMembershipEvent bcme);
|
||||
|
||||
/**
|
||||
* Called when a child or list of children is removed
|
||||
* from a <code>BeanContext</code> that this listener
|
||||
* is registered with.
|
||||
* @param bcme The <code>BeanContextMembershipEvent</code>
|
||||
* describing the change that occurred.
|
||||
*/
|
||||
void childrenRemoved(BeanContextMembershipEvent bcme);
|
||||
}
|
||||
85
jdkSrc/jdk8/java/beans/beancontext/BeanContextProxy.java
Normal file
85
jdkSrc/jdk8/java/beans/beancontext/BeanContextProxy.java
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2002, 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.beancontext;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This interface is implemented by a JavaBean that does
|
||||
* not directly have a BeanContext(Child) associated with
|
||||
* it (via implementing that interface or a subinterface thereof),
|
||||
* but has a public BeanContext(Child) delegated from it.
|
||||
* For example, a subclass of java.awt.Container may have a BeanContext
|
||||
* associated with it that all Component children of that Container shall
|
||||
* be contained within.
|
||||
* </p>
|
||||
* <p>
|
||||
* An Object may not implement this interface and the
|
||||
* BeanContextChild interface
|
||||
* (or any subinterfaces thereof) they are mutually exclusive.
|
||||
* </p>
|
||||
* <p>
|
||||
* Callers of this interface shall examine the return type in order to
|
||||
* obtain a particular subinterface of BeanContextChild as follows:
|
||||
* <code>
|
||||
* BeanContextChild bcc = o.getBeanContextProxy();
|
||||
*
|
||||
* if (bcc instanceof BeanContext) {
|
||||
* // ...
|
||||
* }
|
||||
* </code>
|
||||
* or
|
||||
* <code>
|
||||
* BeanContextChild bcc = o.getBeanContextProxy();
|
||||
* BeanContext bc = null;
|
||||
*
|
||||
* try {
|
||||
* bc = (BeanContext)bcc;
|
||||
* } catch (ClassCastException cce) {
|
||||
* // cast failed, bcc is not an instanceof BeanContext
|
||||
* }
|
||||
* </code>
|
||||
* </p>
|
||||
* <p>
|
||||
* The return value is a constant for the lifetime of the implementing
|
||||
* instance
|
||||
* </p>
|
||||
* @author Laurence P. G. Cable
|
||||
* @since 1.2
|
||||
*
|
||||
* @see java.beans.beancontext.BeanContextChild
|
||||
* @see java.beans.beancontext.BeanContextChildSupport
|
||||
*/
|
||||
|
||||
public interface BeanContextProxy {
|
||||
|
||||
/**
|
||||
* Gets the <code>BeanContextChild</code> (or subinterface)
|
||||
* associated with this object.
|
||||
* @return the <code>BeanContextChild</code> (or subinterface)
|
||||
* associated with this object
|
||||
*/
|
||||
BeanContextChild getBeanContextProxy();
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2009, 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.beancontext;
|
||||
|
||||
import java.beans.beancontext.BeanContextChild;
|
||||
import java.beans.beancontext.BeanContextEvent;
|
||||
|
||||
import java.beans.beancontext.BeanContextServices;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This event type is used by the BeanContextServicesListener in order to
|
||||
* identify the service being registered.
|
||||
* </p>
|
||||
*/
|
||||
|
||||
public class BeanContextServiceAvailableEvent extends BeanContextEvent {
|
||||
private static final long serialVersionUID = -5333985775656400778L;
|
||||
|
||||
/**
|
||||
* Construct a <code>BeanContextAvailableServiceEvent</code>.
|
||||
* @param bcs The context in which the service has become available
|
||||
* @param sc A <code>Class</code> reference to the newly available service
|
||||
*/
|
||||
public BeanContextServiceAvailableEvent(BeanContextServices bcs, Class sc) {
|
||||
super((BeanContext)bcs);
|
||||
|
||||
serviceClass = sc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source as a reference of type <code>BeanContextServices</code>.
|
||||
* @return The context in which the service has become available
|
||||
*/
|
||||
public BeanContextServices getSourceAsBeanContextServices() {
|
||||
return (BeanContextServices)getBeanContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the service class that is the subject of this notification.
|
||||
* @return A <code>Class</code> reference to the newly available service
|
||||
*/
|
||||
public Class getServiceClass() { return serviceClass; }
|
||||
|
||||
/**
|
||||
* Gets the list of service dependent selectors.
|
||||
* @return the current selectors available from the service
|
||||
*/
|
||||
public Iterator getCurrentServiceSelectors() {
|
||||
return ((BeanContextServices)getSource()).getCurrentServiceSelectors(serviceClass);
|
||||
}
|
||||
|
||||
/*
|
||||
* fields
|
||||
*/
|
||||
|
||||
/**
|
||||
* A <code>Class</code> reference to the newly available service
|
||||
*/
|
||||
protected Class serviceClass;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2004, 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.beancontext;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* One of the primary functions of a BeanContext is to act a as rendezvous
|
||||
* between JavaBeans, and BeanContextServiceProviders.
|
||||
* </p>
|
||||
* <p>
|
||||
* A JavaBean nested within a BeanContext, may ask that BeanContext to
|
||||
* provide an instance of a "service", based upon a reference to a Java
|
||||
* Class object that represents that service.
|
||||
* </p>
|
||||
* <p>
|
||||
* If such a service has been registered with the context, or one of its
|
||||
* nesting context's, in the case where a context delegate to its context
|
||||
* to satisfy a service request, then the BeanContextServiceProvider associated with
|
||||
* the service is asked to provide an instance of that service.
|
||||
* </p>
|
||||
* <p>
|
||||
* The ServcieProvider may always return the same instance, or it may
|
||||
* construct a new instance for each request.
|
||||
* </p>
|
||||
*/
|
||||
|
||||
public interface BeanContextServiceProvider {
|
||||
|
||||
/**
|
||||
* Invoked by <code>BeanContextServices</code>, this method
|
||||
* requests an instance of a
|
||||
* service from this <code>BeanContextServiceProvider</code>.
|
||||
*
|
||||
* @param bcs The <code>BeanContextServices</code> associated with this
|
||||
* particular request. This parameter enables the
|
||||
* <code>BeanContextServiceProvider</code> to distinguish service
|
||||
* requests from multiple sources.
|
||||
*
|
||||
* @param requestor The object requesting the service
|
||||
*
|
||||
* @param serviceClass The service requested
|
||||
*
|
||||
* @param serviceSelector the service dependent parameter
|
||||
* for a particular service, or <code>null</code> if not applicable.
|
||||
*
|
||||
* @return a reference to the requested service
|
||||
*/
|
||||
Object getService(BeanContextServices bcs, Object requestor, Class serviceClass, Object serviceSelector);
|
||||
|
||||
/**
|
||||
* Invoked by <code>BeanContextServices</code>,
|
||||
* this method releases a nested <code>BeanContextChild</code>'s
|
||||
* (or any arbitrary object associated with a
|
||||
* <code>BeanContextChild</code>) reference to the specified service.
|
||||
*
|
||||
* @param bcs the <code>BeanContextServices</code> associated with this
|
||||
* particular release request
|
||||
*
|
||||
* @param requestor the object requesting the service to be released
|
||||
*
|
||||
* @param service the service that is to be released
|
||||
*/
|
||||
public void releaseService(BeanContextServices bcs, Object requestor, Object service);
|
||||
|
||||
/**
|
||||
* Invoked by <code>BeanContextServices</code>, this method
|
||||
* gets the current service selectors for the specified service.
|
||||
* A service selector is a service specific parameter,
|
||||
* typical examples of which could include: a
|
||||
* parameter to a constructor for the service implementation class,
|
||||
* a value for a particular service's property, or a key into a
|
||||
* map of existing implementations.
|
||||
*
|
||||
* @param bcs the <code>BeanContextServices</code> for this request
|
||||
* @param serviceClass the specified service
|
||||
* @return the current service selectors for the specified serviceClass
|
||||
*/
|
||||
Iterator getCurrentServiceSelectors(BeanContextServices bcs, Class serviceClass);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 1999, 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.beancontext;
|
||||
|
||||
import java.beans.BeanInfo;
|
||||
|
||||
/**
|
||||
* A BeanContextServiceProvider implementor who wishes to provide explicit
|
||||
* information about the services their bean may provide shall implement a
|
||||
* BeanInfo class that implements this BeanInfo subinterface and provides
|
||||
* explicit information about the methods, properties, events, etc, of their
|
||||
* services.
|
||||
*/
|
||||
|
||||
public interface BeanContextServiceProviderBeanInfo extends BeanInfo {
|
||||
|
||||
/**
|
||||
* Gets a <code>BeanInfo</code> array, one for each
|
||||
* service class or interface statically available
|
||||
* from this ServiceProvider.
|
||||
* @return the <code>BeanInfo</code> array
|
||||
*/
|
||||
BeanInfo[] getServicesBeanInfo();
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2009, 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.beancontext;
|
||||
|
||||
import java.beans.beancontext.BeanContextEvent;
|
||||
|
||||
import java.beans.beancontext.BeanContextServices;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This event type is used by the
|
||||
* <code>BeanContextServiceRevokedListener</code> in order to
|
||||
* identify the service being revoked.
|
||||
* </p>
|
||||
*/
|
||||
public class BeanContextServiceRevokedEvent extends BeanContextEvent {
|
||||
private static final long serialVersionUID = -1295543154724961754L;
|
||||
|
||||
/**
|
||||
* Construct a <code>BeanContextServiceEvent</code>.
|
||||
* @param bcs the <code>BeanContextServices</code>
|
||||
* from which this service is being revoked
|
||||
* @param sc the service that is being revoked
|
||||
* @param invalidate <code>true</code> for immediate revocation
|
||||
*/
|
||||
public BeanContextServiceRevokedEvent(BeanContextServices bcs, Class sc, boolean invalidate) {
|
||||
super((BeanContext)bcs);
|
||||
|
||||
serviceClass = sc;
|
||||
invalidateRefs = invalidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source as a reference of type <code>BeanContextServices</code>
|
||||
* @return the <code>BeanContextServices</code> from which
|
||||
* this service is being revoked
|
||||
*/
|
||||
public BeanContextServices getSourceAsBeanContextServices() {
|
||||
return (BeanContextServices)getBeanContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the service class that is the subject of this notification
|
||||
* @return A <code>Class</code> reference to the
|
||||
* service that is being revoked
|
||||
*/
|
||||
public Class getServiceClass() { return serviceClass; }
|
||||
|
||||
/**
|
||||
* Checks this event to determine whether or not
|
||||
* the service being revoked is of a particular class.
|
||||
* @param service the service of interest (should be non-null)
|
||||
* @return <code>true</code> if the service being revoked is of the
|
||||
* same class as the specified service
|
||||
*/
|
||||
public boolean isServiceClass(Class service) {
|
||||
return serviceClass.equals(service);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports if the current service is being forcibly revoked,
|
||||
* in which case the references are now invalidated and unusable.
|
||||
* @return <code>true</code> if current service is being forcibly revoked
|
||||
*/
|
||||
public boolean isCurrentServiceInvalidNow() { return invalidateRefs; }
|
||||
|
||||
/**
|
||||
* fields
|
||||
*/
|
||||
|
||||
/**
|
||||
* A <code>Class</code> reference to the service that is being revoked.
|
||||
*/
|
||||
protected Class serviceClass;
|
||||
private boolean invalidateRefs;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2013, 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.beancontext;
|
||||
|
||||
import java.beans.beancontext.BeanContextServiceRevokedEvent;
|
||||
|
||||
import java.util.EventListener;
|
||||
|
||||
/**
|
||||
* The listener interface for receiving
|
||||
* <code>BeanContextServiceRevokedEvent</code> objects. A class that is
|
||||
* interested in processing a <code>BeanContextServiceRevokedEvent</code>
|
||||
* implements this interface.
|
||||
*/
|
||||
public interface BeanContextServiceRevokedListener extends EventListener {
|
||||
|
||||
/**
|
||||
* The service named has been revoked. getService requests for
|
||||
* this service will no longer be satisfied.
|
||||
* @param bcsre the <code>BeanContextServiceRevokedEvent</code> received
|
||||
* by this listener.
|
||||
*/
|
||||
void serviceRevoked(BeanContextServiceRevokedEvent bcsre);
|
||||
}
|
||||
160
jdkSrc/jdk8/java/beans/beancontext/BeanContextServices.java
Normal file
160
jdkSrc/jdk8/java/beans/beancontext/BeanContextServices.java
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2013, 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.beancontext;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import java.util.TooManyListenersException;
|
||||
|
||||
import java.beans.beancontext.BeanContext;
|
||||
|
||||
import java.beans.beancontext.BeanContextServiceProvider;
|
||||
|
||||
import java.beans.beancontext.BeanContextServicesListener;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* The BeanContextServices interface provides a mechanism for a BeanContext
|
||||
* to expose generic "services" to the BeanContextChild objects within.
|
||||
* </p>
|
||||
*/
|
||||
public interface BeanContextServices extends BeanContext, BeanContextServicesListener {
|
||||
|
||||
/**
|
||||
* Adds a service to this BeanContext.
|
||||
* <code>BeanContextServiceProvider</code>s call this method
|
||||
* to register a particular service with this context.
|
||||
* If the service has not previously been added, the
|
||||
* <code>BeanContextServices</code> associates
|
||||
* the service with the <code>BeanContextServiceProvider</code> and
|
||||
* fires a <code>BeanContextServiceAvailableEvent</code> to all
|
||||
* currently registered <code>BeanContextServicesListeners</code>.
|
||||
* The method then returns <code>true</code>, indicating that
|
||||
* the addition of the service was successful.
|
||||
* If the given service has already been added, this method
|
||||
* simply returns <code>false</code>.
|
||||
* @param serviceClass the service to add
|
||||
* @param serviceProvider the <code>BeanContextServiceProvider</code>
|
||||
* associated with the service
|
||||
* @return true if the service was successful added, false otherwise
|
||||
*/
|
||||
boolean addService(Class serviceClass, BeanContextServiceProvider serviceProvider);
|
||||
|
||||
/**
|
||||
* BeanContextServiceProviders wishing to remove
|
||||
* a currently registered service from this context
|
||||
* may do so via invocation of this method. Upon revocation of
|
||||
* the service, the <code>BeanContextServices</code> fires a
|
||||
* <code>BeanContextServiceRevokedEvent</code> to its
|
||||
* list of currently registered
|
||||
* <code>BeanContextServiceRevokedListeners</code> and
|
||||
* <code>BeanContextServicesListeners</code>.
|
||||
* @param serviceClass the service to revoke from this BeanContextServices
|
||||
* @param serviceProvider the BeanContextServiceProvider associated with
|
||||
* this particular service that is being revoked
|
||||
* @param revokeCurrentServicesNow a value of <code>true</code>
|
||||
* indicates an exceptional circumstance where the
|
||||
* <code>BeanContextServiceProvider</code> or
|
||||
* <code>BeanContextServices</code> wishes to immediately
|
||||
* terminate service to all currently outstanding references
|
||||
* to the specified service.
|
||||
*/
|
||||
void revokeService(Class serviceClass, BeanContextServiceProvider serviceProvider, boolean revokeCurrentServicesNow);
|
||||
|
||||
/**
|
||||
* Reports whether or not a given service is
|
||||
* currently available from this context.
|
||||
* @param serviceClass the service in question
|
||||
* @return true if the service is available
|
||||
*/
|
||||
boolean hasService(Class serviceClass);
|
||||
|
||||
/**
|
||||
* A <code>BeanContextChild</code>, or any arbitrary object
|
||||
* associated with a <code>BeanContextChild</code>, may obtain
|
||||
* a reference to a currently registered service from its
|
||||
* nesting <code>BeanContextServices</code>
|
||||
* via invocation of this method. When invoked, this method
|
||||
* gets the service by calling the getService() method on the
|
||||
* underlying <code>BeanContextServiceProvider</code>.
|
||||
* @param child the <code>BeanContextChild</code>
|
||||
* associated with this request
|
||||
* @param requestor the object requesting the service
|
||||
* @param serviceClass class of the requested service
|
||||
* @param serviceSelector the service dependent parameter
|
||||
* @param bcsrl the
|
||||
* <code>BeanContextServiceRevokedListener</code> to notify
|
||||
* if the service should later become revoked
|
||||
* @throws TooManyListenersException if there are too many listeners
|
||||
* @return a reference to this context's named
|
||||
* Service as requested or <code>null</code>
|
||||
*/
|
||||
Object getService(BeanContextChild child, Object requestor, Class serviceClass, Object serviceSelector, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException;
|
||||
|
||||
/**
|
||||
* Releases a <code>BeanContextChild</code>'s
|
||||
* (or any arbitrary object associated with a BeanContextChild)
|
||||
* reference to the specified service by calling releaseService()
|
||||
* on the underlying <code>BeanContextServiceProvider</code>.
|
||||
* @param child the <code>BeanContextChild</code>
|
||||
* @param requestor the requestor
|
||||
* @param service the service
|
||||
*/
|
||||
void releaseService(BeanContextChild child, Object requestor, Object service);
|
||||
|
||||
/**
|
||||
* Gets the currently available services for this context.
|
||||
* @return an <code>Iterator</code> consisting of the
|
||||
* currently available services
|
||||
*/
|
||||
Iterator getCurrentServiceClasses();
|
||||
|
||||
/**
|
||||
* Gets the list of service dependent service parameters
|
||||
* (Service Selectors) for the specified service, by
|
||||
* calling getCurrentServiceSelectors() on the
|
||||
* underlying BeanContextServiceProvider.
|
||||
* @param serviceClass the specified service
|
||||
* @return the currently available service selectors
|
||||
* for the named serviceClass
|
||||
*/
|
||||
Iterator getCurrentServiceSelectors(Class serviceClass);
|
||||
|
||||
/**
|
||||
* Adds a <code>BeanContextServicesListener</code> to this BeanContext
|
||||
* @param bcsl the <code>BeanContextServicesListener</code> to add
|
||||
*/
|
||||
void addBeanContextServicesListener(BeanContextServicesListener bcsl);
|
||||
|
||||
/**
|
||||
* Removes a <code>BeanContextServicesListener</code>
|
||||
* from this <code>BeanContext</code>
|
||||
* @param bcsl the <code>BeanContextServicesListener</code>
|
||||
* to remove from this context
|
||||
*/
|
||||
void removeBeanContextServicesListener(BeanContextServicesListener bcsl);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 1999, 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.beancontext;
|
||||
|
||||
import java.beans.beancontext.BeanContextServiceAvailableEvent;
|
||||
import java.beans.beancontext.BeanContextServiceRevokedEvent;
|
||||
import java.beans.beancontext.BeanContextServiceRevokedListener;
|
||||
|
||||
/**
|
||||
* The listener interface for receiving
|
||||
* <code>BeanContextServiceAvailableEvent</code> objects.
|
||||
* A class that is interested in processing a
|
||||
* <code>BeanContextServiceAvailableEvent</code> implements this interface.
|
||||
*/
|
||||
public interface BeanContextServicesListener extends BeanContextServiceRevokedListener {
|
||||
|
||||
/**
|
||||
* The service named has been registered. getService requests for
|
||||
* this service may now be made.
|
||||
* @param bcsae the <code>BeanContextServiceAvailableEvent</code>
|
||||
*/
|
||||
void serviceAvailable(BeanContextServiceAvailableEvent bcsae);
|
||||
}
|
||||
1257
jdkSrc/jdk8/java/beans/beancontext/BeanContextServicesSupport.java
Normal file
1257
jdkSrc/jdk8/java/beans/beancontext/BeanContextServicesSupport.java
Normal file
File diff suppressed because it is too large
Load Diff
1404
jdkSrc/jdk8/java/beans/beancontext/BeanContextSupport.java
Normal file
1404
jdkSrc/jdk8/java/beans/beancontext/BeanContextSupport.java
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user