import java.beans.*; import java.lang.reflect.*; import java.util.*; /** * BeanProxy is a class for accessing a JavaBean dynamically at runtime. It * provides methods for getting properties, setting properties, and invoking * methods on a target bean. BeanProxy can be used in situations where bean * properties and methods are not known at compile time, or when compile time * access to a bean would result in brittle code. *

* Here is an example of brittle code: *
 * public class MyTableModel extends DefaultTableModel {
 *    ...
 *
 *    public Object getValueAt(int row, int col) {
 *       LogEntry entry;
 *       Object   value;
 *
 *       try {
 *          entry = log.get(row);
 *
 *          switch(col) {
 *             case 0: 
 *                value = entry.getWorkDate(); 
 *                break;
 *
 *             case 1: 
 *                value = entry.getStartTime(); 
 *                break;
 *             ...
 *          }
 *        } catch(Exception ex) {
 *           return "";
 *       }
 *
 *       return value;
 *    }
 *
 *    ...
 * }
 * 
* * Here is an example of non-brittle code using BeanProxy: *
 * public class MyTableModel extends DefaultTableModel {
 *    ...
 *
 *    public MyTableModel() {
 *       columns = new String[] { "workDate",  "startTime", "endTime", 
 *          "mealTime", "hours", "notes" };
 *       entryProxy = new BeanProxy(LogEntry.class);
 *       ...
 *    }
 *
 *    ...
 *
 *    public Object getValueAt(int row, int col) {
 *       LogEntry entry;
 *       Object   value;
 *
 *       try {
 *          entry = log.get(row);
 *          entryProxy.setBean(entry);
 *          value = entryProxy.get(columns[col]);
 *        } catch(Exception ex) {
 *           return "";
 *       }
 *
 *       return value;
 *    }
 * 
* * @author Thornton Rose * @version 1.2 */ public class BeanProxy implements IBeanProxy { private Object bean; private Class beanClass; private Hashtable pdsByName = new Hashtable(); /** * Constructs a proxy for the given class. * * @param theBeanClass The target bean class. */ public BeanProxy(Class theBeanClass) throws IntrospectionException { BeanInfo bi; PropertyDescriptor[] pds; String name; Method m; // Save reference to bean class. beanClass = theBeanClass; // Build hashtable for bean property descriptors. bi = Introspector.getBeanInfo(beanClass); pds = bi.getPropertyDescriptors(); for (int i = 0; i < pds.length; i ++) { name = pds[i].getName(); pdsByName.put(name, pds[i]); } } /** * Constructs a proxy for the given bean. * * @param theBean The target bean. */ public BeanProxy(Object theBean) throws IntrospectionException { this(theBean.getClass()); bean = theBean; } public Object getBean() { return bean; } public void setBean(Object newBean) { bean = newBean; } /** * Get bean property. * * @param name Bean property name. * * @return Bean property value as Object. */ public Object get(String name) throws Exception { PropertyDescriptor pd; Method getter; pd = (PropertyDescriptor) pdsByName.get(name); if (pd == null) { throw new NoSuchFieldException("Unknown property: " + name); } getter = pd.getReadMethod(); if (getter == null) { throw new NoSuchMethodException("No read method for: " + name); } return getter.invoke(bean, new Object[] {}); } /** * Set bean property. * * @param name Bean property name. * @param value Bean property value. */ public Object set(String name, Object value) throws Exception { PropertyDescriptor pd; Method setter; pd = (PropertyDescriptor) pdsByName.get(name); if (pd == null) { throw new NoSuchFieldException("Unknown property: " + name); } setter = pd.getWriteMethod(); if (setter == null) { throw new NoSuchMethodException("No write method for: " + name); } return setter.invoke(bean, new Object[] { value } ); } /** * Invoke named method on target bean. * * @param name Method name. * @param types Parameter types. * @param parameters List of parameters passed to method. * * @return Return value from method (may be null). * * @throws Throwable When any exception occurs. */ public Object invoke(String name, Class[] types, Object[] parameters) throws Exception { return beanClass.getMethod(name, types).invoke(bean, parameters); } }