Package com.acciente.induction.dispatcher.model

Source Code of com.acciente.induction.dispatcher.model.ModelFactory$ModelClassNameSet

/*
* Copyright 2008-2011 Acciente, LLC
*
* Acciente, LLC licenses this file to you under the
* Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in
* writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
* OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.acciente.induction.dispatcher.model;

import com.acciente.commons.reflect.Invoker;
import com.acciente.commons.reflect.ParameterProvider;
import com.acciente.commons.reflect.ParameterProviderException;
import com.acciente.induction.controller.Form;
import com.acciente.induction.controller.HTMLForm;
import com.acciente.induction.dispatcher.resolver.RedirectResolverExecutor;
import com.acciente.induction.dispatcher.resolver.URLResolver;
import com.acciente.induction.init.config.Config;
import com.acciente.induction.template.TemplatingEngine;
import com.acciente.induction.util.ConstructorNotFoundException;
import com.acciente.induction.util.MethodNotFoundException;
import com.acciente.induction.util.ObjectFactory;
import com.acciente.induction.util.ReflectUtils;

import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.Set;

/**
* Internal.
* This class is the factory used to instantiate new Model object instances
*
* @created Mar 15, 2008
*
* @author Adinath Raveendra Raj
*/
public class ModelFactory
{
   private  ClassLoader                   _oClassLoader;
   private  ServletConfig                 _oServletConfig;
   private  TemplatingEngine              _oTemplatingEngine;
   private  Config.FileUpload             _oFileUploadConfig;
   private  RedirectResolverExecutor      _oRedirectResolverExecutor;

   private  ConfiguredModelFactoryPool    _oConfiguredModelFactoryPool;
   private  ModelPool                     _oModelPool;
   private  ThreadLocal                   _oCreateInProgressModelClassNameSet  = new ModelClassNameSet();

   public ModelFactory( ClassLoader       oClassLoader,
                        ServletConfig     oServletConfig,
                        Config.FileUpload oFileUploadConfig )
   {
      _oClassLoader        = oClassLoader;
      _oServletConfig      = oServletConfig;
      _oFileUploadConfig   = oFileUploadConfig;

      _oConfiguredModelFactoryPool = new ConfiguredModelFactoryPool( oClassLoader, oServletConfig );
   }

   /**
    * Used to set a model pool for use in model-to-model dendency injection (note the cyclic relationship
    * between ModelFactory class and the ModelPool class, also the same relationship between the object
    * instances)
    *
    * @param oModelPool a model pool instance
    */
   public void setModelPool( ModelPool oModelPool )
   {
      _oModelPool = oModelPool;
   }

   /**
    * This method exists to set the redirect resolver after construction of the model factory since there is
    * a cyclic dependency between the redirect resolver and the model factory
    * @param oRedirectResolverExecutor the redirect resolver
    */
   public void setRedirectResolver( RedirectResolverExecutor oRedirectResolverExecutor )
   {
      _oRedirectResolverExecutor = oRedirectResolverExecutor;
   }

   /**
    * This method exists to set the templating engine after construction of the model factory since there is
    * a cyclic dependency between the templating engine and the model factory
    * @param oTemplatingEngine the redirect resolver
    */
   public void setTemplatingEngine( TemplatingEngine oTemplatingEngine )
   {
      _oTemplatingEngine = oTemplatingEngine;
   }

   public Object createModel( Config.ModelDefs.ModelDef oModelDef, HttpServletRequest oHttpServletRequest )
      throws InvocationTargetException, ConstructorNotFoundException, ParameterProviderException, IllegalAccessException, InstantiationException, MethodNotFoundException, ClassNotFoundException
   {
      // we keep track of the model classname we are loading in a thread local set, this allows
      // us to detect cyclic dependencies which would otherwise cause infinite recursion
      Set oCreateInProgressModelClassNameSet = ( Set ) _oCreateInProgressModelClassNameSet.get();

      if ( oCreateInProgressModelClassNameSet.contains( oModelDef.getModelClassName() ) )
      {
         throw new IllegalArgumentException( "model-create-error: cyclical dependency detected between model: "
                                             + oModelDef.getModelClassName()
                                             + " and model(s): "
                                             + oCreateInProgressModelClassNameSet );
      }

      oCreateInProgressModelClassNameSet.add( oModelDef.getModelClassName() );

      Object   oModel;

      try
      {
         Object[]                oParameterValues        = new Object[]{ _oServletConfig, oModelDef, oHttpServletRequest, _oTemplatingEngine, _oClassLoader };
         ModelParameterProvider  oModelParameterProvider = new ModelParameterProvider( _oModelPool, _oFileUploadConfig, oHttpServletRequest, _oRedirectResolverExecutor );

         // does this model class have a factory class defined?
         if ( ! oModelDef.hasModelFactoryClassName() )
         {
            // no factory class, then we expect a single public constructor, which we use to
            // instantiate the model via a a direct parameter injected constructor call
            oModel
               =  ObjectFactory.createObject( _oClassLoader.loadClass( oModelDef.getModelClassName() ),
                                              oParameterValues, oModelParameterProvider );
         }
         else
         {
            // we have a factory class, so a few more steps in this case

            // first get a model factory instance
            Object   oConfiguredModelFactory = _oConfiguredModelFactoryPool.getConfiguredModelFactory( oModelDef.getModelFactoryClassName() );

            // next call the createModel() method on the factory instance
            oModel
               =  Invoker
                     .invoke( ReflectUtils.getSingletonMethod( oConfiguredModelFactory.getClass(), "createModel", true ),
                              oConfiguredModelFactory,
                              oParameterValues,
                              oModelParameterProvider );
         }
      }
      finally
      {
         ( ( Set ) _oCreateInProgressModelClassNameSet.get() ).remove( oModelDef.getModelClassName() );
      }

      return oModel;
   }

   public boolean isModelStale( Config.ModelDefs.ModelDef oModelDef, Object oModel )
      throws ClassNotFoundException, ConstructorNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException
   {
      boolean bStale;

      if ( oModelDef.hasModelFactoryClassName() )
      {
         // we have a factory class, also check if the factory class reloaded since the model was created
         bStale = _oConfiguredModelFactoryPool.isConfiguredModelFactoryStale( oModelDef.getModelFactoryClassName() ); // todo: reinspect this line
      }
      else
      {
         // first check if the model class has been reloaded since this model was created
         bStale = _oClassLoader.loadClass( oModelDef.getModelClassName() ).hashCode() != oModel.getClass().hashCode();
      }

      return bStale;
   }

   public Object createSystemModel( Class oSystemModelClass, HttpServletRequest oHttpServletRequest )
   {
      Object   oSystemModel = null;

      if ( oSystemModelClass.isAssignableFrom( Form.class ) )
      {
         oSystemModel = new HTMLForm( oHttpServletRequest, _oFileUploadConfig );

      }
      else if ( oSystemModelClass.isAssignableFrom( URLResolver.class ) )
      {
         oSystemModel = new URLResolver( _oRedirectResolverExecutor, oHttpServletRequest );
      }

      return oSystemModel;
   }

   /**
    * Internal.
    */
   private static class ModelParameterProvider implements ParameterProvider
   {
      private ModelPool                _oModelPool;
      private HttpServletRequest       _oHttpServletRequest;
      private Config.FileUpload        _oFileUploadConfig;
      private RedirectResolverExecutor _oRedirectResolverExecutor;

      public ModelParameterProvider( ModelPool                oModelPool,
                                     Config.FileUpload        oFileUploadConfig,
                                     HttpServletRequest       oHttpServletRequest,
                                     RedirectResolverExecutor oRedirectResolverExecutor )
      {
         _oModelPool                = oModelPool;
         _oHttpServletRequest       = oHttpServletRequest;
         _oFileUploadConfig         = oFileUploadConfig;
         _oRedirectResolverExecutor = oRedirectResolverExecutor;
      }

      public Object getParameter( Class oParamClass ) throws ParameterProviderException
      {
         final String sMessagePrefix = "model-factory: error resolving value for type: ";

         Object   oParamValue = null;

         try
         {
            if ( oParamClass.isAssignableFrom( Form.class ) )
            {
               if ( _oHttpServletRequest == null )
               {
                  throw new ParameterProviderException( oParamClass + " not available in this context" );
               }

               oParamValue = _oModelPool.getSystemModel( Form.class, _oHttpServletRequest );
            }
            else if ( oParamClass.isAssignableFrom( HttpServletRequest.class ) )
            {
               if ( _oHttpServletRequest == null )
               {
                  throw new ParameterProviderException( oParamClass + " not available in this context" );
               }

               oParamValue = _oHttpServletRequest;
            }
            else if ( oParamClass.isAssignableFrom( URLResolver.class ) )
            {
               if ( _oRedirectResolverExecutor == null )
               {
                  throw new ParameterProviderException( oParamClass + " not available in this context" );
               }

               oParamValue = _oModelPool.getSystemModel( URLResolver.class, _oHttpServletRequest );
            }
            else
            {
               oParamValue = _oModelPool.getModel( oParamClass, _oHttpServletRequest );
            }

            if ( oParamValue == null )
            {
               throw ( new ParameterProviderException( sMessagePrefix + oParamClass ) );
            }

            return oParamValue;
         }
         catch ( MethodNotFoundException e )
         {  throw new ParameterProviderException( sMessagePrefix + oParamClass, e );     }
         catch ( InvocationTargetException e )
         {  throw new ParameterProviderException( sMessagePrefix + oParamClass, e );     }
         catch ( ClassNotFoundException e )
         {  throw new ParameterProviderException( sMessagePrefix + oParamClass, e );     }
         catch ( ConstructorNotFoundException e )
         {  throw new ParameterProviderException( sMessagePrefix + oParamClass, e );     }
         catch ( IllegalAccessException e )
         {  throw new ParameterProviderException( sMessagePrefix + oParamClass, e );     }
         catch ( InstantiationException e )
         {  throw new ParameterProviderException( sMessagePrefix + oParamClass, e );     }
      }
   }

   private static class ModelClassNameSet extends ThreadLocal
   {
      public synchronized Object initialValue()
      {
         return new HashSet();
      }
   }
}

// EOF
TOP

Related Classes of com.acciente.induction.dispatcher.model.ModelFactory$ModelClassNameSet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
d', 'pageview');