// // ERDObjectCreationDelegate.java // ERDirectToWeb // // Created by Max Muller on Wed Nov 20 2002. // package er.directtoweb.assignments.delayed; import java.lang.reflect.Constructor; import org.apache.log4j.Logger; import com.webobjects.directtoweb.D2WContext; import com.webobjects.eocontrol.EOKeyValueUnarchiver; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSDictionary; /** * Assignment used to create objects on the fly. This assignment * can be used in two different manner. The first is by just * specifing the class name as a string, ie "foo.bar.MyClass". This * will create an instance of the MyClass object. The second form * allows one to specify the object to be created in a dictionary format:<pre><code> * { * className = "foo.bar.MyClass"; * arguments = ( { * className = "com.webobjects.appserver.WOSession"; * contextKey = "session"; * }, { * className = "java.lang.String"; * contextKey = "propertyKey"; * }); * }</code></pre> * * This will create an object of type MyClass using the constructor: * MyClass(WOSession session, String key), using the arguments found * by resolving the contextKey off of the current {@link D2WContext context}. */ public class ERDDelayedObjectCreationAssignment extends ERDDelayedAssignment { /** * Do I need to update serialVersionUID? * See section 5.6 <cite>Type Changes Affecting Serialization</cite> on page 51 of the * <a href="http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf">Java Object Serialization Spec</a> */ private static final long serialVersionUID = 1L; // =========================================================================== // Class variable(s) // --------------------------------------------------------------------------- /** logging support */ public static final Logger log = Logger.getLogger(ERDDelayedObjectCreationAssignment.class); // =========================================================================== // Class method(s) // --------------------------------------------------------------------------- /** * Static constructor required by the EOKeyValueUnarchiver * interface. If this isn't implemented then the default * behavior is to construct the first super class that does * implement this method. Very lame. * @param eokeyvalueunarchiver to be unarchived * @return decoded assignment of this class */ public static Object decodeWithKeyValueUnarchiver(EOKeyValueUnarchiver eokeyvalueunarchiver) { return new ERDDelayedObjectCreationAssignment(eokeyvalueunarchiver); } // =========================================================================== // Constructor(s) // --------------------------------------------------------------------------- /** * Public constructor * @param u key-value unarchiver used when unarchiving * from rule files. */ public ERDDelayedObjectCreationAssignment(EOKeyValueUnarchiver u) { super(u); } /** * Public constructor * @param key context key * @param value of the assignment */ public ERDDelayedObjectCreationAssignment(String key, Object value) { super(key,value); } // =========================================================================== // Instance method(s) // --------------------------------------------------------------------------- /** * Delayed firing of assignment. Creates an object * for the specified class. See description of the * class for the correct format. * @param context current context * @return newly created object */ @Override public Object fireNow(D2WContext context) { Object createdObject = null; try { if (log.isDebugEnabled()) log.debug("Creating object for value: " + value()); if (value() instanceof String) { Class c = Class.forName((String)value()); createdObject = c.newInstance(); } else if (value() instanceof NSDictionary) { String mainClassName = (String)((NSDictionary)value()).objectForKey("className"); Class mainClass = Class.forName(mainClassName); NSArray arguments = (NSArray)((NSDictionary)value()).objectForKey("arguments"); if (arguments != null && arguments.count() > 0) { Class argumentClasses[] = new Class[arguments.count()]; Object argumentValues[] = new Object[arguments.count()]; int count = 0; while (count < arguments.count()) { NSDictionary anArgument = (NSDictionary)arguments.objectAtIndex(count); String argumentClassName = (String)anArgument.objectForKey("className"); String argumentContextKey = (String)anArgument.objectForKey("contextKey"); argumentValues[count] = context.valueForKeyPath(argumentContextKey); argumentClasses[count] = Class.forName(argumentClassName); count++; } Constructor constructor = mainClass.getConstructor(argumentClasses); if (constructor != null) { createdObject = constructor.newInstance(argumentValues); } else { log.warn("Unable to find constructor on class: " + mainClass.getName() + " for argument classes: " + argumentClasses); } } else { createdObject = mainClass.newInstance(); } } else { log.warn("Unsupported value: " + value()); } } catch (Exception e) { log.warn("Exception happened when attempting to create object for value: " + value() + " exception: " + e); } return createdObject; } }