package org.apache.struts.action; import java.lang.reflect.Array; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import org.apache.commons.beanutils.ConversionException; import org.apache.commons.beanutils.DynaBean; import org.apache.commons.beanutils.DynaClass; import org.apache.commons.beanutils.DynaProperty; import org.apache.struts.config.FormBeanConfig; import org.apache.struts.config.FormPropertyConfig; public class DynaActionForm extends ActionForm implements DynaBean { protected DynaActionFormClass dynaClass = null; protected HashMap dynaValues = new HashMap(); public void initialize(ActionMapping mapping) { String name = mapping.getName(); if (name == null) return; FormBeanConfig config = mapping.getModuleConfig().findFormBeanConfig(name); if (config == null) return; FormPropertyConfig[] props = config.findFormPropertyConfigs(); for (int i = 0; i < props.length; i++) set(props[i].getName(), props[i].initial()); } public void reset(ActionMapping mapping, ServletRequest request) { try { reset(mapping, (HttpServletRequest)request); } catch (ClassCastException e) {} } public void reset(ActionMapping mapping, HttpServletRequest request) {} public boolean contains(String name, String key) { Object value = this.dynaValues.get(name); if (value == null) throw new NullPointerException("No mapped value for '" + name + "(" + key + ")'"); if (value instanceof Map) return ((Map)value).containsKey(key); throw new IllegalArgumentException("Non-mapped property for '" + name + "(" + key + ")'"); } public Object get(String name) { Object value = this.dynaValues.get(name); if (value != null) return value; Class type = getDynaProperty(name).getType(); if (type == null) throw new NullPointerException("The type for property " + name + " is invalid"); if (!type.isPrimitive()) return value; if (type == boolean.class) return Boolean.FALSE; if (type == byte.class) return new Byte((byte)0); if (type == char.class) return new Character(false); if (type == double.class) return new Double(0.0D); if (type == float.class) return new Float(0.0F); if (type == int.class) return new Integer(0); if (type == long.class) return new Long(0L); if (type == short.class) return new Short((short)0); return null; } public Object get(String name, int index) { Object value = this.dynaValues.get(name); if (value == null) throw new NullPointerException("No indexed value for '" + name + "[" + index + "]'"); if (value.getClass().isArray()) return Array.get(value, index); if (value instanceof List) return ((List)value).get(index); throw new IllegalArgumentException("Non-indexed property for '" + name + "[" + index + "]'"); } public Object get(String name, String key) { Object value = this.dynaValues.get(name); if (value == null) throw new NullPointerException("No mapped value for '" + name + "(" + key + ")'"); if (value instanceof Map) return ((Map)value).get(key); throw new IllegalArgumentException("Non-mapped property for '" + name + "(" + key + ")'"); } public DynaClass getDynaClass() { return this.dynaClass; } public Map getMap() { return this.dynaValues; } public void remove(String name, String key) { Object value = this.dynaValues.get(name); if (value == null) throw new NullPointerException("No mapped value for '" + name + "(" + key + ")'"); if (value instanceof Map) { ((Map)value).remove(key); } else { throw new IllegalArgumentException("Non-mapped property for '" + name + "(" + key + ")'"); } } public void set(String name, Object value) { DynaProperty descriptor = getDynaProperty(name); if (descriptor.getType() == null) throw new NullPointerException("The type for property " + name + " is invalid"); if (value == null) { if (descriptor.getType().isPrimitive()) throw new NullPointerException("Primitive value for '" + name + "'"); } else if (!isDynaAssignable(descriptor.getType(), value.getClass())) { throw new ConversionException("Cannot assign value of type '" + value.getClass().getName() + "' to property '" + name + "' of type '" + descriptor.getType().getName() + "'"); } this.dynaValues.put(name, value); } public void set(String name, int index, Object value) { Object prop = this.dynaValues.get(name); if (prop == null) throw new NullPointerException("No indexed value for '" + name + "[" + index + "]'"); if (prop.getClass().isArray()) { Array.set(prop, index, value); } else if (prop instanceof List) { try { ((List)prop).set(index, value); } catch (ClassCastException e) { throw new ConversionException(e.getMessage()); } } else { throw new IllegalArgumentException("Non-indexed property for '" + name + "[" + index + "]'"); } } public void set(String name, String key, Object value) { Object prop = this.dynaValues.get(name); if (prop == null) throw new NullPointerException("No mapped value for '" + name + "(" + key + ")'"); if (prop instanceof Map) { ((Map)prop).put(key, value); } else { throw new IllegalArgumentException("Non-mapped property for '" + name + "(" + key + ")'"); } } public String toString() { StringBuffer sb = new StringBuffer("DynaActionForm[dynaClass="); sb.append(getDynaClass().getName()); DynaProperty[] props = getDynaClass().getDynaProperties(); if (props == null) props = new DynaProperty[0]; for (int i = 0; i < props.length; i++) { sb.append(','); sb.append(props[i].getName()); sb.append('='); Object value = get(props[i].getName()); if (value == null) { sb.append(""); } else if (value.getClass().isArray()) { int n = Array.getLength(value); sb.append("{"); for (int j = 0; j < n; j++) { if (j > 0) sb.append(','); sb.append(Array.get(value, j)); } sb.append("}"); } else if (value instanceof List) { int n = ((List)value).size(); sb.append("{"); for (int j = 0; j < n; j++) { if (j > 0) sb.append(','); sb.append(((List)value).get(j)); } sb.append("}"); } else if (value instanceof Map) { int n = 0; Iterator keys = ((Map)value).keySet().iterator(); sb.append("{"); while (keys.hasNext()) { if (n > 0) sb.append(','); n++; String key = keys.next(); sb.append(key); sb.append('='); sb.append(((Map)value).get(key)); } sb.append("}"); } else { sb.append(value); } } sb.append("]"); return sb.toString(); } void setDynaActionFormClass(DynaActionFormClass dynaClass) { this.dynaClass = dynaClass; } protected DynaProperty getDynaProperty(String name) { DynaProperty descriptor = getDynaClass().getDynaProperty(name); if (descriptor == null) throw new IllegalArgumentException("Invalid property name '" + name + "'"); return descriptor; } protected boolean isDynaAssignable(Class dest, Class source) { if (dest.isAssignableFrom(source) || (dest == boolean.class && source == Boolean.class) || (dest == byte.class && source == Byte.class) || (dest == char.class && source == Character.class) || (dest == double.class && source == Double.class) || (dest == float.class && source == Float.class) || (dest == int.class && source == Integer.class) || (dest == long.class && source == Long.class) || (dest == short.class && source == Short.class)) return true; return false; } }