mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			297 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			297 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* java.beans.IndexedPropertyDescriptor
 | |
|    Copyright (C) 1998 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.
 | |
| 
 | |
| As a special exception, if you link this library with other files to
 | |
| produce an executable, this library does not by itself cause the
 | |
| resulting executable to be covered by the GNU General Public License.
 | |
| This exception does not however invalidate any other reasons why the
 | |
| executable file might be covered by the GNU General Public License. */
 | |
| 
 | |
| 
 | |
| package java.beans;
 | |
| 
 | |
| import java.util.*;
 | |
| import java.lang.reflect.*;
 | |
| 
 | |
| /**
 | |
|  ** IndexedPropertyDescriptor describes information about a JavaBean
 | |
|  ** indexed property, by which we mean an array-like property that
 | |
|  ** has been exposed via a pair of get and set methods and another
 | |
|  ** pair that allows you to get to the property by an index.<P>
 | |
|  **
 | |
|  ** An example property would have four methods like this:<P>
 | |
|  ** <CODE>FooBar[] getFoo()</CODE><BR>
 | |
|  ** <CODE>void setFoo(FooBar[])</CODE><BR>
 | |
|  ** <CODE>FooBar getFoo(int)</CODE><BR>
 | |
|  ** <CODE>void setFoo(int,FooBar)</CODE><P>
 | |
|  **
 | |
|  ** The constraints put on get and set methods are:<P>
 | |
|  ** <OL>
 | |
|  ** <LI>There must be at least a get(int) or a set(int,...) method.
 | |
|  ** Nothing else is required.  <B>Spec note:</B>One nice restriction
 | |
|  ** would be that if there is a get() there must be a get(int), same
 | |
|  ** with set, but that is not in the spec and is fairly harmless.)</LI>
 | |
|  ** <LI>A get array method must have signature
 | |
|  **     <CODE><propertyType>[] <getMethodName>()</CODE></LI>
 | |
|  ** <LI>A set array method must have signature
 | |
|  **     <CODE>void <setMethodName>(<propertyType>[])</CODE></LI>
 | |
|  ** <LI>A get index method must have signature
 | |
|  **     <CODE><propertyType> <getMethodName>(int)</CODE></LI>
 | |
|  ** <LI>A set index method must have signature
 | |
|  **     <CODE>void <setMethodName>(int,<propertyType>)</CODE></LI>
 | |
|  ** <LI>All these methods may throw any exception.</LI>
 | |
|  ** <LI>All these methods must be public.</LI>
 | |
|  ** </OL>
 | |
|  **
 | |
|  ** @author John Keiser
 | |
|  ** @since JDK1.1
 | |
|  ** @version 1.1.0, 26 Jul 1998
 | |
|  **/
 | |
| 
 | |
| public class IndexedPropertyDescriptor extends PropertyDescriptor {
 | |
| 	private Class indexedPropertyType;
 | |
| 	private Method setIndex;
 | |
| 	private Method getIndex;
 | |
| 
 | |
| 	/** Create a new IndexedPropertyDescriptor by introspection.
 | |
| 	 ** This form of constructor creates the PropertyDescriptor by
 | |
| 	 ** looking for getter methods named <CODE>get<name>()</CODE>
 | |
| 	 ** and setter methods named
 | |
| 	 ** <CODE>set<name>()</CODE> in class
 | |
| 	 ** <CODE><beanClass></CODE>, where <name> has its
 | |
| 	 ** first letter capitalized by the constructor.<P>
 | |
| 	 **
 | |
| 	 ** <B>Implementation note:</B> If there is a get(int) method,
 | |
| 	 ** then the return type of that method is used to find the
 | |
| 	 ** remaining methods.  If there is no get method, then the
 | |
| 	 ** set(int) method is searched for exhaustively and that type
 | |
| 	 ** is used to find the others.<P>
 | |
| 	 **
 | |
| 	 ** <B>Spec note:</B>
 | |
| 	 ** If there is no get(int) method and multiple set(int) methods with
 | |
| 	 ** the same name and the correct parameters (different type of course),
 | |
| 	 ** then an IntrospectionException is thrown.  While Sun's spec
 | |
| 	 ** does not state this, it can make Bean behavior different on
 | |
| 	 ** different systems (since method order is not guaranteed) and as
 | |
| 	 ** such, can be treated as a bug in the spec.  I am not aware of
 | |
| 	 ** whether Sun's implementation catches this.
 | |
| 	 **
 | |
| 	 ** @param name the programmatic name of the property, usually
 | |
| 	 **             starting with a lowercase letter (e.g. fooManChu
 | |
| 	 **             instead of FooManChu).
 | |
| 	 ** @param beanClass the class the get and set methods live in.
 | |
| 	 ** @exception IntrospectionException if the methods are not found or invalid.
 | |
| 	 **/
 | |
| 	public IndexedPropertyDescriptor(String name, Class beanClass) throws IntrospectionException {
 | |
| 		super(name);
 | |
| 		String capitalized;
 | |
| 		try {
 | |
| 			capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1);
 | |
| 		} catch(StringIndexOutOfBoundsException e) {
 | |
| 			capitalized = "";
 | |
| 		}
 | |
| 		findMethods(beanClass, "get" + capitalized, "set" + capitalized, "get" + capitalized, "set" + capitalized);
 | |
| 	}
 | |
| 
 | |
| 	/** Create a new IndexedPropertyDescriptor by introspection.
 | |
| 	 ** This form of constructor allows you to specify the
 | |
| 	 ** names of the get and set methods to search for.<P>
 | |
| 	 **
 | |
| 	 ** <B>Implementation note:</B> If there is a get(int) method,
 | |
| 	 ** then the return type of that method is used to find the
 | |
| 	 ** remaining methods.  If there is no get method, then the
 | |
| 	 ** set(int) method is searched for exhaustively and that type
 | |
| 	 ** is used to find the others.<P>
 | |
| 	 **
 | |
| 	 ** <B>Spec note:</B>
 | |
| 	 ** If there is no get(int) method and multiple set(int) methods with
 | |
| 	 ** the same name and the correct parameters (different type of course),
 | |
| 	 ** then an IntrospectionException is thrown.  While Sun's spec
 | |
| 	 ** does not state this, it can make Bean behavior different on
 | |
| 	 ** different systems (since method order is not guaranteed) and as
 | |
| 	 ** such, can be treated as a bug in the spec.  I am not aware of
 | |
| 	 ** whether Sun's implementation catches this.
 | |
| 	 **
 | |
| 	 ** @param name the programmatic name of the property, usually
 | |
| 	 **             starting with a lowercase letter (e.g. fooManChu
 | |
| 	 **             instead of FooManChu).
 | |
| 	 ** @param beanClass the class the get and set methods live in.
 | |
| 	 ** @param getMethodName the name of the get array method.
 | |
| 	 ** @param setMethodName the name of the set array method.
 | |
| 	 ** @param getIndexName the name of the get index method.
 | |
| 	 ** @param setIndexName the name of the set index method.
 | |
| 	 ** @exception IntrospectionException if the methods are not found or invalid.
 | |
| 	 **/
 | |
| 	public IndexedPropertyDescriptor(String name, Class beanClass, String getMethodName, String setMethodName, String getIndexName, String setIndexName) throws IntrospectionException {
 | |
| 		super(name);
 | |
| 		findMethods(beanClass, getMethodName, setMethodName, getIndexName, setIndexName);
 | |
| 	}
 | |
| 
 | |
| 	/** Create a new PropertyDescriptor using explicit Methods.
 | |
| 	 ** Note that the methods will be checked for conformance to standard
 | |
| 	 ** Property method rules, as described above at the top of this class.
 | |
| 	 ** 
 | |
| 	 ** @param name the programmatic name of the property, usually
 | |
| 	 **             starting with a lowercase letter (e.g. fooManChu
 | |
| 	 **             instead of FooManChu).
 | |
| 	 ** @param getMethod the get array method.
 | |
| 	 ** @param setMethod the set array method.
 | |
| 	 ** @param getIndex the get index method.
 | |
| 	 ** @param setIndex the set index method.
 | |
| 	 ** @exception IntrospectionException if the methods are not found or invalid.
 | |
| 	 **/
 | |
| 	public IndexedPropertyDescriptor(String name, Method getMethod, Method setMethod, Method getIndex, Method setIndex) throws IntrospectionException {
 | |
| 		super(name);
 | |
| 		if(getMethod != null && getMethod.getParameterTypes().length > 0) {
 | |
| 			throw new IntrospectionException("get method has parameters");
 | |
| 		}
 | |
| 		if(getMethod != null && setMethod.getParameterTypes().length != 1) {
 | |
| 			throw new IntrospectionException("set method does not have exactly one parameter");
 | |
| 		}
 | |
| 		if(getMethod != null && setMethod != null) {
 | |
| 			if(!getMethod.getReturnType().equals(setMethod.getParameterTypes()[0])) {
 | |
| 				throw new IntrospectionException("set and get methods do not share the same type");
 | |
| 			}
 | |
| 			if(!getMethod.getDeclaringClass().isAssignableFrom(setMethod.getDeclaringClass())
 | |
| 			   && !setMethod.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())) {
 | |
| 				throw new IntrospectionException("set and get methods are not in the same class.");
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if(getIndex != null && (getIndex.getParameterTypes().length != 1
 | |
| 		   || !(getIndex.getParameterTypes()[0]).equals(java.lang.Integer.TYPE))) {
 | |
| 			throw new IntrospectionException("get index method has wrong parameters");
 | |
| 		}
 | |
| 		if(setIndex != null && (setIndex.getParameterTypes().length != 2
 | |
| 		   || !(setIndex.getParameterTypes()[0]).equals(java.lang.Integer.TYPE))) {
 | |
| 			throw new IntrospectionException("set index method has wrong parameters");
 | |
| 		}
 | |
| 		if(getIndex != null && setIndex != null) {
 | |
| 			if(!getIndex.getReturnType().equals(setIndex.getParameterTypes()[1])) {
 | |
| 				throw new IntrospectionException("set index methods do not share the same type");
 | |
| 			}
 | |
| 			if(!getIndex.getDeclaringClass().isAssignableFrom(setIndex.getDeclaringClass())
 | |
| 			   && !setIndex.getDeclaringClass().isAssignableFrom(getIndex.getDeclaringClass())) {
 | |
| 				throw new IntrospectionException("get and set index methods are not in the same class.");
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if(getIndex != null && getMethod != null && !getIndex.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())
 | |
| 		   && !getMethod.getDeclaringClass().isAssignableFrom(getIndex.getDeclaringClass())) {
 | |
| 			throw new IntrospectionException("methods are not in the same class.");
 | |
| 		}
 | |
| 
 | |
| 		if(getIndex != null && getMethod != null && !Array.newInstance(getIndex.getReturnType(),0).getClass().equals(getMethod.getReturnType())) {
 | |
| 			throw new IntrospectionException("array methods do not match index methods.");
 | |
| 		}
 | |
| 
 | |
| 		this.getMethod = getMethod;
 | |
| 		this.setMethod = setMethod;
 | |
| 		this.getIndex = getIndex;
 | |
| 		this.setIndex = getIndex;
 | |
| 		this.indexedPropertyType = getIndex != null ? getIndex.getReturnType() : setIndex.getParameterTypes()[1];
 | |
| 		this.propertyType = getMethod != null ? getMethod.getReturnType() : (setMethod != null ? setMethod.getParameterTypes()[0] : Array.newInstance(this.indexedPropertyType,0).getClass());
 | |
| 	}
 | |
| 
 | |
| 	public Class getIndexedPropertyType() {
 | |
| 		return indexedPropertyType;
 | |
| 	}
 | |
| 
 | |
| 	public Method getIndexedReadMethod() {
 | |
| 		return getIndex;
 | |
| 	}
 | |
| 
 | |
| 	public Method getIndexedWriteMethod() {
 | |
| 		return setIndex;
 | |
| 	}
 | |
| 
 | |
| 	private void findMethods(Class beanClass, String getMethodName, String setMethodName, String getIndexName, String setIndexName) throws IntrospectionException {
 | |
| 		try {
 | |
| 			if(getIndexName != null) {
 | |
| 				try {
 | |
| 					Class[] getArgs = new Class[1];
 | |
| 					getArgs[0] = java.lang.Integer.TYPE;
 | |
| 					getIndex = beanClass.getMethod(getIndexName,getArgs);
 | |
| 					indexedPropertyType = getIndex.getReturnType();
 | |
| 				} catch(NoSuchMethodException E) {
 | |
| 				}
 | |
| 			}
 | |
| 			if(getIndex != null) {
 | |
| 				if(setIndexName != null) {
 | |
| 					try {
 | |
| 						Class[] setArgs = new Class[2];
 | |
| 						setArgs[0] = java.lang.Integer.TYPE;
 | |
| 						setArgs[1] = indexedPropertyType;
 | |
| 						setIndex = beanClass.getMethod(setIndexName,setArgs);
 | |
| 						if(!setIndex.getReturnType().equals(java.lang.Void.TYPE)) {
 | |
| 							throw new IntrospectionException(setIndexName + " has non-void return type");
 | |
| 						}
 | |
| 					} catch(NoSuchMethodException E) {
 | |
| 					}
 | |
| 				}
 | |
| 			} else if(setIndexName != null) {
 | |
| 				Method[] m = beanClass.getMethods();
 | |
| 				for(int i=0;i<m.length;i++) {
 | |
| 					Method current = m[i];
 | |
| 					if(current.getName().equals(setIndexName)
 | |
| 					   && current.getParameterTypes().length == 2
 | |
| 					   && (current.getParameterTypes()[0]).equals(java.lang.Integer.TYPE)
 | |
| 					   && current.getReturnType().equals(java.lang.Void.TYPE)) {
 | |
| 						if(setIndex != null) {
 | |
| 							throw new IntrospectionException("Multiple, different set methods found that fit the bill!");
 | |
| 						} else {
 | |
| 							setIndex = current;
 | |
| 							indexedPropertyType = current.getParameterTypes()[1];
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 				if(setIndex == null) {
 | |
| 					throw new IntrospectionException("Cannot find get or set methods.");
 | |
| 				}
 | |
| 			} else {
 | |
| 				throw new IntrospectionException("Cannot find get or set methods.");
 | |
| 			}
 | |
| 
 | |
| 			Class arrayType = Array.newInstance(indexedPropertyType,0).getClass();
 | |
| 
 | |
| 			Class[] setArgs = new Class[1];
 | |
| 			setArgs[0] = arrayType;
 | |
| 			try {
 | |
| 				setMethod = beanClass.getMethod(setMethodName,setArgs);
 | |
| 				if(!setMethod.getReturnType().equals(java.lang.Void.TYPE)) {
 | |
| 					setMethod = null;
 | |
| 				}
 | |
| 			} catch(NoSuchMethodException E) {
 | |
| 			}
 | |
| 
 | |
| 			Class[] getArgs = new Class[0];
 | |
| 			try {
 | |
| 				getMethod = beanClass.getMethod(getMethodName,getArgs);
 | |
| 				if(!getMethod.getReturnType().equals(arrayType)) {
 | |
| 					getMethod = null;
 | |
| 				}
 | |
| 			} catch(NoSuchMethodException E) {
 | |
| 			}
 | |
| 		} catch(SecurityException E) {
 | |
| 			throw new IntrospectionException("SecurityException while trying to find methods.");
 | |
| 		}
 | |
| 	}
 | |
| }
 |