PatchSet 5738 
Date: 2005/04/22 23:30:35
Author: robilad
Branch: HEAD
Tag: (none) 
Log:
Resynced with GNU Classpath: beans fix

2005-04-22  Dalibor Topic  <[EMAIL PROTECTED]>

        Resynced with GNU Classpath:

        2005-04-18  Jeroen Frijters  <[EMAIL PROTECTED]>

        * gnu/java/beans/IntrospectionIncubator.java
        (addToPropertyHash, addToListenerHash): Don't confuse get(),
        set(), is(), add() and remove() with properties or events.

Members: 
        ChangeLog:1.3906->1.3907 
        
libraries/javalib/gnu/java/beans/IntrospectionIncubator.java:INITIAL->1.8 

Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.3906 kaffe/ChangeLog:1.3907
--- kaffe/ChangeLog:1.3906      Fri Apr 22 23:28:18 2005
+++ kaffe/ChangeLog     Fri Apr 22 23:30:35 2005
@@ -2,6 +2,16 @@
 
        Resynced with GNU Classpath:
 
+       2005-04-18  Jeroen Frijters  <[EMAIL PROTECTED]>
+
+        * gnu/java/beans/IntrospectionIncubator.java
+        (addToPropertyHash, addToListenerHash): Don't confuse get(),
+        set(), is(), add() and remove() with properties or events.
+
+2005-04-22  Dalibor Topic  <[EMAIL PROTECTED]>
+
+       Resynced with GNU Classpath:
+
        2005-04-17  Roman Kennke  <[EMAIL PROTECTED]>
 
         * javax/swing/text/SimpleAttributeSet.java
===================================================================
Checking out kaffe/libraries/javalib/gnu/java/beans/IntrospectionIncubator.java
RCS:  
/home/cvs/kaffe/kaffe/libraries/javalib/gnu/java/beans/IntrospectionIncubator.java,v
VERS: 1.8
***************
--- /dev/null   Sun Aug  4 19:57:58 2002
+++ kaffe/libraries/javalib/gnu/java/beans/IntrospectionIncubator.java  Fri Apr 
22 23:42:15 2005
@@ -0,0 +1,441 @@
+/* gnu.java.beans.IntrospectionIncubator
+   Copyright (C) 1998, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+ 
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.beans;
+
+import gnu.java.lang.ArrayHelper;
+import gnu.java.lang.ClassHelper;
+
+import java.beans.BeanInfo;
+import java.beans.EventSetDescriptor;
+import java.beans.IndexedPropertyDescriptor;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.MethodDescriptor;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ ** IntrospectionIncubator takes in a bunch of Methods, and
+ ** Introspects only those Methods you give it.<br/>
+ **
+ ** See [EMAIL PROTECTED] addMethod(Method)} for details which rules apply to
+ ** the methods.
+ **
+ ** @author John Keiser
+ ** @author Robert Schuster
+ ** @see gnu.java.beans.ExplicitBeanInfo
+ ** @see java.beans.BeanInfo
+ **/
+
+public class IntrospectionIncubator {
+       Hashtable propertyMethods = new Hashtable();
+       Hashtable listenerMethods = new Hashtable();
+       Vector otherMethods = new Vector();
+
+       Class propertyStopClass;
+       Class eventStopClass;
+       Class methodStopClass;
+
+       public IntrospectionIncubator() {
+       }
+
+       /** Examines the given method and files it in a suitable collection.
+        * It files the method as a property method if it finds:
+        * <ul>
+        * <li>boolean "is" getter</li>
+        * <li>"get" style getter</li>
+        * <li>single argument setter</li>
+        * <li>indiced setter and getter</li> 
+        * </ul>
+        * It files the method as a listener method if all of these rules apply:
+        * <ul>
+        * <li>the method name starts with "add" or "remove"</li>
+        * <li>there is only a single argument</li>
+        * <li>the argument type is a subclass of 
<code>java.util.EventListener</code></li>
+        * </ul>
+        * All public methods are filed as such. 
+        *   
+        * @param method The method instance to examine.
+        */
+       public void addMethod(Method method) {
+               if(Modifier.isPublic(method.getModifiers())) {
+                       String name = 
ClassHelper.getTruncatedName(method.getName());
+                       Class retType = method.getReturnType();
+                       Class[] params = method.getParameterTypes();
+                       boolean isVoid = retType.equals(java.lang.Void.TYPE);
+                       Class methodClass = method.getDeclaringClass();
+                       
+                       /* Accepts the method for examination if no stop class 
is given or the method is declared in a subclass of the stop class.
+                        * The rules for this are described in [EMAIL 
PROTECTED] java.beans.Introspector.getBeanInfo(Class, Class)}.
+                        * This block finds out whether the method is a 
suitable getter or setter method (or read/write method).  
+                        */
+                       if(isReachable(propertyStopClass, methodClass)) {
+                               /* At this point a method may regarded as a 
property's read or write method if its name
+                                * starts with "is", "get" or "set". However, 
if a method is static it cannot be part
+                                * of a property.
+                                */
+                               if(Modifier.isStatic(method.getModifiers())) {
+                                       // files method as other because it is 
static
+                                       otherMethods.addElement(method);
+                               } else if(name.startsWith("is")
+                                  && retType.equals(java.lang.Boolean.TYPE)
+                                  && params.length == 0) {
+                                       // files method as boolean "is" style 
getter
+                                       addToPropertyHash(name,method,IS);
+                               } else if(name.startsWith("get") && !isVoid) {
+                                       if(params.length == 0) {
+                                               // files as legal non-argument 
getter
+                                               
addToPropertyHash(name,method,GET);
+                                       } else if(params.length == 1 && 
params[0].equals(java.lang.Integer.TYPE)) {
+                                               // files as legal indiced getter
+                                               
addToPropertyHash(name,method,GET_I);
+                                       } else {
+                                               // files as other because the 
method's signature is not Bean-like
+                                               otherMethods.addElement(method);
+                                       }
+                               } else if(name.startsWith("set") && isVoid) {
+                                       if(params.length == 1) {
+                                               // files as legal 
single-argument setter method
+                                               
addToPropertyHash(name,method,SET);
+                                       } else if(params.length == 2 && 
params[0].equals(java.lang.Integer.TYPE)) {
+                                               // files as legal indiced 
setter method
+                                               
addToPropertyHash(name,method,SET_I);
+                                       } else {
+                                               // files as other because the 
method's signature is not Bean-like
+                                               otherMethods.addElement(method);
+                                       }
+                               }
+                       }
+                       
+                       if(isReachable(eventStopClass, methodClass)) {
+                               if(name.startsWith("add")
+                                         && isVoid
+                                         && params.length == 1
+                                         && 
java.util.EventListener.class.isAssignableFrom(params[0])) {
+                                       addToListenerHash(name,method,ADD);
+                               } else if(name.startsWith("remove")
+                                         && isVoid
+                                         && params.length == 1
+                                         && 
java.util.EventListener.class.isAssignableFrom(params[0])) {
+                                       addToListenerHash(name,method,REMOVE);
+                               }
+                       }
+                        
+                       if(isReachable(methodStopClass, methodClass)) {
+                               // files as reachable public method
+                               otherMethods.addElement(method);
+                       }
+                       
+               }
+       }
+
+       public void addMethods(Method[] m) {
+               for(int i=0;i<m.length;i++) {
+                       addMethod(m[i]);
+               }
+       }
+
+       public void setPropertyStopClass(Class c) {
+               propertyStopClass = c;
+       }
+
+       public void setEventStopClass(Class c) {
+               eventStopClass = c;
+       }
+
+       public void setMethodStopClass(Class c) {
+               methodStopClass = c;
+       }
+
+
+       public BeanInfoEmbryo getBeanInfoEmbryo() throws IntrospectionException 
{
+               BeanInfoEmbryo b = new BeanInfoEmbryo();
+               findXXX(b,IS);
+               findXXXInt(b,GET_I);
+               findXXXInt(b,SET_I);
+               findXXX(b,GET);
+               findXXX(b,SET);
+               findAddRemovePairs(b);
+               for(int i=0;i<otherMethods.size();i++) {
+                       MethodDescriptor newMethod = new 
MethodDescriptor((Method)otherMethods.elementAt(i));
+                       if(!b.hasMethod(newMethod)) {
+                               b.addMethod(new 
MethodDescriptor((Method)otherMethods.elementAt(i)));
+                       }
+               }
+               return b;
+       }
+
+       public BeanInfo getBeanInfo() throws IntrospectionException {
+               return getBeanInfoEmbryo().getBeanInfo();
+       }
+
+
+       void findAddRemovePairs(BeanInfoEmbryo b) throws IntrospectionException 
{
+               Enumeration listenerEnum = listenerMethods.keys();
+               while(listenerEnum.hasMoreElements()) {
+                       DoubleKey k = (DoubleKey)listenerEnum.nextElement();
+                       Method[] m = (Method[])listenerMethods.get(k);
+                       if(m[ADD] != null && m[REMOVE] != null) {
+                               EventSetDescriptor e = new 
EventSetDescriptor(Introspector.decapitalize(k.getName()),
+                                                                             
k.getType(), k.getType().getMethods(),
+                                                                             
m[ADD],m[REMOVE]);
+                               
e.setUnicast(ArrayHelper.contains(m[ADD].getExceptionTypes(),java.util.TooManyListenersException.class));
+                               if(!b.hasEvent(e)) {
+                                       b.addEvent(e);
+                               }
+                       }
+               }
+       }
+
+       void findXXX(BeanInfoEmbryo b, int funcType) throws 
IntrospectionException {
+               Enumeration keys = propertyMethods.keys();
+               while(keys.hasMoreElements()) {
+                       DoubleKey k = (DoubleKey)keys.nextElement();
+                       Method[] m = (Method[])propertyMethods.get(k);
+                       if(m[funcType] != null) {
+                               PropertyDescriptor p = new 
PropertyDescriptor(Introspector.decapitalize(k.getName()),
+                                                                    m[IS] != 
null ? m[IS] : m[GET],
+                                                                    m[SET]);
+                               if(m[SET] != null) {
+                                       
p.setConstrained(ArrayHelper.contains(m[SET].getExceptionTypes(),java.beans.PropertyVetoException.class));
+                               }
+                               if(!b.hasProperty(p)) {
+                                       b.addProperty(p);
+                               }
+                       }
+               }
+       }
+
+       void findXXXInt(BeanInfoEmbryo b, int funcType) throws 
IntrospectionException {
+               Enumeration keys = propertyMethods.keys();
+               while(keys.hasMoreElements()) {
+                       DoubleKey k = (DoubleKey)keys.nextElement();
+                       Method[] m = (Method[])propertyMethods.get(k);
+                       if(m[funcType] != null) {
+                               boolean constrained;
+                               if(m[SET_I] != null) {
+                                       constrained = 
ArrayHelper.contains(m[SET_I].getExceptionTypes(),java.beans.PropertyVetoException.class);
+                               } else {
+                                       constrained = false;
+                               }
+
+                               /** Find out if there is an array type get or 
set **/
+                               Class arrayType = 
Array.newInstance(k.getType(),0).getClass();
+                               DoubleKey findSetArray = new 
DoubleKey(arrayType,k.getName());
+                               Method[] m2 = 
(Method[])propertyMethods.get(findSetArray);
+                               IndexedPropertyDescriptor p;
+                               if(m2 == null) {
+                                       p = new 
IndexedPropertyDescriptor(Introspector.decapitalize(k.getName()),
+                                                                         
null,null,
+                                                                         
m[GET_I],m[SET_I]);
+                               } else {
+                                       if(constrained && m2[SET] != null) {
+                                               constrained = 
ArrayHelper.contains(m2[SET].getExceptionTypes(),java.beans.PropertyVetoException.class);
+                                       }
+                                       p = new 
IndexedPropertyDescriptor(Introspector.decapitalize(k.getName()),
+                                                                         
m2[GET],m2[SET],
+                                                                         
m[GET_I],m[SET_I]);
+                               }
+                               p.setConstrained(constrained);
+                               if(!b.hasProperty(p)) {
+                                       b.addProperty(p);
+                               }
+                       }
+               }
+       }
+
+       static final int IS=0;
+       static final int GET_I=1;
+       static final int SET_I=2;
+       static final int GET=3;
+       static final int SET=4;
+
+       static final int ADD=0;
+       static final int REMOVE=1;
+
+       void addToPropertyHash(String name, Method method, int funcType) {
+               String newName;
+               Class type;
+
+               switch(funcType) {
+                       case IS:
+                               type = java.lang.Boolean.TYPE;
+                               newName = name.substring(2);
+                               break;
+                       case GET_I:
+                               type = method.getReturnType();
+                               newName = name.substring(3);
+                               break;
+                       case SET_I:
+                               type = method.getParameterTypes()[1];
+                               newName = name.substring(3);
+                               break;
+                       case GET:
+                               type = method.getReturnType();
+                               newName = name.substring(3);
+                               break;
+                       case SET:
+                               type = method.getParameterTypes()[0];
+                               newName = name.substring(3);
+                               break;
+                       default:
+                               return;
+               }
+               newName = capitalize(newName);
+               if (newName.length() == 0)
+                       return;
+
+               DoubleKey k = new DoubleKey(type,newName);
+               Method[] methods = (Method[])propertyMethods.get(k);
+               if(methods == null) {
+                       methods = new Method[5];
+                       propertyMethods.put(k,methods);
+               }
+               methods[funcType] = method;
+       }
+
+       void addToListenerHash(String name, Method method, int funcType) {
+               String newName;
+               Class type;
+
+               switch(funcType) {
+                       case ADD:
+                               type = method.getParameterTypes()[0];
+                               newName = name.substring(3,name.length()-8);
+                               break;
+                       case REMOVE:
+                               type = method.getParameterTypes()[0];
+                               newName = name.substring(6,name.length()-8);
+                               break;
+                       default:
+                               return;
+               }
+               newName = capitalize(newName);
+               if (newName.length() == 0)
+                       return;
+
+               DoubleKey k = new DoubleKey(type,newName);
+               Method[] methods = (Method[])listenerMethods.get(k);
+               if(methods == null) {
+                       methods = new Method[2];
+                       listenerMethods.put(k,methods);
+               }
+               methods[funcType] = method;
+       }
+
+       /* Determines whether <code>stopClass</code> is <code>null</code>
+        * or <code>declaringClass<code> is a true subclass of 
<code>stopClass</code>.
+        * This expression is useful to detect whether a method should be 
introspected or not.
+        * The rules for this are described in [EMAIL PROTECTED] 
java.beans.Introspector.getBeanInfo(Class, Class)}.
+        */
+       static boolean isReachable(Class stopClass, Class declaringClass) {
+               return stopClass == null || 
(stopClass.isAssignableFrom(declaringClass) && 
!stopClass.equals(declaringClass));
+       }
+
+       /** Transforms a property name into a part of a method name.
+        * E.g. "value" becomes "Value" which can then concatenated with
+        * "set", "get" or "is" to form a valid method name.
+        * 
+        * Implementation notes:
+        * If "" is the argument, it is returned without changes.
+        * If <code>null</code> is the argument, <code>null</code> is returned.
+        * 
+        * @param name Name of a property.
+        * @return Part of a method name of a property.
+        */
+       static String capitalize(String name) {
+               try {
+                       if(Character.isUpperCase(name.charAt(0))) {
+                               return name;
+                       } else {
+                               char[] c = name.toCharArray();
+                               c[0] = Character.toLowerCase(c[0]);
+                               return new String(c);
+                       }
+               } catch(StringIndexOutOfBoundsException E) {
+                       return name;
+               } catch(NullPointerException E) {
+                       return null;
+               }
+       }
+}
+
+/** This class is a hashmap key that consists of a <code>Class</code> and a
+ * <code>String</code> element.
+ * 
+ * It is used for XXX: find out what this is used for
+ * 
+ * @author John Keiser
+ * @author Robert Schuster
+ */ 
+class DoubleKey {
+       Class type;
+       String name;
+
+       DoubleKey(Class type, String name) {
+               this.type = type;
+               this.name = name;
+       }
+
+       Class getType() {
+               return type;
+       }
+
+       String getName() {
+               return name;
+       }
+
+       public boolean equals(Object o) {
+               if(o instanceof DoubleKey) {
+                       DoubleKey d = (DoubleKey)o;
+                       return d.type.equals(type) && d.name.equals(name);
+               } else {
+                       return false;
+               }
+       }
+
+       public int hashCode() {
+               return type.hashCode() ^ name.hashCode();
+       }
+}

_______________________________________________
kaffe mailing list
[email protected]
http://kaffe.org/cgi-bin/mailman/listinfo/kaffe

Reply via email to