Save This Page
Home » xwork-2.1.1-src » com.opensymphony.xwork2 » [javadoc | source]
    1   /*
    2    * Copyright (c) 2002-2006 by OpenSymphony
    3    * All rights reserved.
    4    */
    5   package com.opensymphony.xwork2;
    6   
    7   import java.io.Serializable;
    8   import java.util.HashMap;
    9   import java.util.Map;
   10   
   11   import com.opensymphony.xwork2.config.ConfigurationException;
   12   import com.opensymphony.xwork2.config.entities.ActionConfig;
   13   import com.opensymphony.xwork2.config.entities.InterceptorConfig;
   14   import com.opensymphony.xwork2.config.entities.ResultConfig;
   15   import com.opensymphony.xwork2.inject.Container;
   16   import com.opensymphony.xwork2.inject.Inject;
   17   import com.opensymphony.xwork2.interceptor.Interceptor;
   18   import com.opensymphony.xwork2.util.ClassLoaderUtil;
   19   import com.opensymphony.xwork2.util.logging.Logger;
   20   import com.opensymphony.xwork2.util.logging.LoggerFactory;
   21   import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
   22   import com.opensymphony.xwork2.validator.Validator;
   23   
   24   
   25   /**
   26    * ObjectFactory is responsible for building the core framework objects. Users may register their 
   27    * own implementation of the ObjectFactory to control instantiation of these Objects.
   28    * <p/>
   29    * This default implementation uses the {@link #buildBean(Class,java.util.Map) buildBean} 
   30    * method to create all classes (interceptors, actions, results, etc).
   31    * <p/>
   32    *
   33    * @author Jason Carreira
   34    */
   35   public class ObjectFactory implements Serializable {
   36       private static final Logger LOG = LoggerFactory.getLogger(ObjectFactory.class);
   37   
   38       private transient ClassLoader ccl;
   39       private Container container;
   40       protected ReflectionProvider reflectionProvider;
   41   
   42       @Inject(value="objectFactory.classloader", required=false)
   43       public void setClassLoader(ClassLoader cl) {
   44           this.ccl = cl;
   45       }
   46       
   47       @Inject
   48       public void setReflectionProvider(ReflectionProvider prov) {
   49           this.reflectionProvider = prov;
   50       }
   51   
   52       public ObjectFactory() {
   53       }
   54       
   55       public ObjectFactory(ReflectionProvider prov) {
   56           this.reflectionProvider = prov;
   57       }
   58       
   59       @Inject
   60       public void setContainer(Container container) {
   61           this.container = container;
   62       }
   63   
   64       /**
   65        * @deprecated Since 2.1
   66        */
   67       public static ObjectFactory getObjectFactory() {
   68           return ActionContext.getContext().getContainer().getInstance(ObjectFactory.class);
   69       }
   70   
   71       /**
   72        * Allows for ObjectFactory implementations that support
   73        * Actions without no-arg constructors.
   74        *
   75        * @return true if no-arg constructor is required, false otherwise
   76        */
   77       public boolean isNoArgConstructorRequired() {
   78           return true;
   79       }
   80   
   81       /**
   82        * Utility method to obtain the class matched to className. Caches look ups so that subsequent
   83        * lookups will be faster.
   84        *
   85        * @param className The fully qualified name of the class to return
   86        * @return The class itself
   87        * @throws ClassNotFoundException
   88        */
   89       public Class getClassInstance(String className) throws ClassNotFoundException {
   90           if (ccl != null) {
   91               return ccl.loadClass(className);
   92           }
   93   
   94           return ClassLoaderUtil.loadClass(className, this.getClass());
   95       }
   96   
   97       /**
   98        * Build an instance of the action class to handle a particular request (eg. web request)
   99        * @param actionName the name the action configuration is set up with in the configuration
  100        * @param namespace the namespace the action is configured in
  101        * @param config the action configuration found in the config for the actionName / namespace
  102        * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext}
  103        * @return instance of the action class to handle a web request
  104        * @throws Exception
  105        */
  106       public Object buildAction(String actionName, String namespace, ActionConfig config, Map extraContext) throws Exception {
  107           return buildBean(config.getClassName(), extraContext);
  108       }
  109   
  110       /**
  111        * Build a generic Java object of the given type.
  112        *
  113        * @param clazz the type of Object to build
  114        * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext}
  115        */
  116       public Object buildBean(Class clazz, Map extraContext) throws Exception {
  117           return clazz.newInstance();
  118       }
  119   
  120       /**
  121        * @param obj
  122        */
  123       protected Object injectInternalBeans(Object obj) {
  124           if (obj != null && container != null) {
  125               container.inject(obj);
  126           }
  127           return obj;
  128       }
  129   
  130       /**
  131        * Build a generic Java object of the given type.
  132        *
  133        * @param className the type of Object to build
  134        * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext}
  135        */
  136       public Object buildBean(String className, Map extraContext) throws Exception {
  137           return buildBean(className, extraContext, true);
  138       }
  139       
  140       /**
  141        * Build a generic Java object of the given type.
  142        *
  143        * @param className the type of Object to build
  144        * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext}
  145        */
  146       public Object buildBean(String className, Map extraContext, boolean injectInternal) throws Exception {
  147           Class clazz = getClassInstance(className);
  148           Object obj = buildBean(clazz, extraContext);
  149           if (injectInternal) {
  150               injectInternalBeans(obj);
  151           }
  152           return obj;
  153       }
  154   
  155       /**
  156        * Builds an Interceptor from the InterceptorConfig and the Map of
  157        * parameters from the interceptor reference. Implementations of this method
  158        * should ensure that the Interceptor is parameterized with both the
  159        * parameters from the Interceptor config and the interceptor ref Map (the
  160        * interceptor ref params take precedence), and that the Interceptor.init()
  161        * method is called on the Interceptor instance before it is returned.
  162        *
  163        * @param interceptorConfig    the InterceptorConfig from the configuration
  164        * @param interceptorRefParams a Map of params provided in the Interceptor reference in the
  165        *                             Action mapping or InterceptorStack definition
  166        */
  167       public Interceptor buildInterceptor(InterceptorConfig interceptorConfig, Map interceptorRefParams) throws ConfigurationException {
  168           String interceptorClassName = interceptorConfig.getClassName();
  169           Map thisInterceptorClassParams = interceptorConfig.getParams();
  170           Map params = (thisInterceptorClassParams == null) ? new HashMap() : new HashMap(thisInterceptorClassParams);
  171           params.putAll(interceptorRefParams);
  172   
  173           String message;
  174           Throwable cause;
  175   
  176           try {
  177               // interceptor instances are long-lived and used across user sessions, so don't try to pass in any extra context
  178               Interceptor interceptor = (Interceptor) buildBean(interceptorClassName, null);
  179               reflectionProvider.setProperties(params, interceptor);
  180               interceptor.init();
  181   
  182               return interceptor;
  183           } catch (InstantiationException e) {
  184               cause = e;
  185               message = "Unable to instantiate an instance of Interceptor class [" + interceptorClassName + "].";
  186           } catch (IllegalAccessException e) {
  187               cause = e;
  188               message = "IllegalAccessException while attempting to instantiate an instance of Interceptor class [" + interceptorClassName + "].";
  189           } catch (ClassCastException e) {
  190               cause = e;
  191               message = "Class [" + interceptorClassName + "] does not implement com.opensymphony.xwork2.interceptor.Interceptor";
  192           } catch (Exception e) {
  193               cause = e;
  194               message = "Caught Exception while registering Interceptor class " + interceptorClassName;
  195           } catch (NoClassDefFoundError e) {
  196               cause = e;
  197               message = "Could not load class " + interceptorClassName + ". Perhaps it exists but certain dependencies are not available?";
  198           }
  199   
  200           throw new ConfigurationException(message, cause, interceptorConfig);
  201       }
  202   
  203       /**
  204        * Build a Result using the type in the ResultConfig and set the parameters in the ResultConfig.
  205        *
  206        * @param resultConfig the ResultConfig found for the action with the result code returned
  207        * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext}
  208        */
  209       public Result buildResult(ResultConfig resultConfig, Map extraContext) throws Exception {
  210           String resultClassName = resultConfig.getClassName();
  211           Result result = null;
  212   
  213           if (resultClassName != null) {
  214               result = (Result) buildBean(resultClassName, extraContext);
  215           	reflectionProvider.setProperties(resultConfig.getParams(), result, extraContext, true);
  216           }
  217   
  218           return result;
  219       }
  220   
  221       /**
  222        * Build a Validator of the given type and set the parameters on it
  223        *
  224        * @param className the type of Validator to build
  225        * @param params    property name -> value Map to set onto the Validator instance
  226        * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext}
  227        */
  228       public Validator buildValidator(String className, Map params, Map extraContext) throws Exception {
  229           Validator validator = (Validator) buildBean(className, null);
  230           reflectionProvider.setProperties(params, validator);
  231   
  232           return validator;
  233       }
  234   
  235       static class ContinuationsClassLoader extends ClassLoader {
  236           
  237       }
  238   }

Save This Page
Home » xwork-2.1.1-src » com.opensymphony.xwork2 » [javadoc | source]