[jbosscache-commits] JBoss Cache SVN: r5804 - core/trunk/src/main/java/org/jboss/cache/factories.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Thu May 8 05:04:25 EDT 2008


Author: manik.surtani at jboss.com
Date: 2008-05-08 05:04:25 -0400 (Thu, 08 May 2008)
New Revision: 5804

Removed:
   core/trunk/src/main/java/org/jboss/cache/factories/ComponentRegistry.java
Log:


Deleted: core/trunk/src/main/java/org/jboss/cache/factories/ComponentRegistry.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/factories/ComponentRegistry.java	2008-05-08 08:50:28 UTC (rev 5803)
+++ core/trunk/src/main/java/org/jboss/cache/factories/ComponentRegistry.java	2008-05-08 09:04:25 UTC (rev 5804)
@@ -1,1016 +0,0 @@
-package org.jboss.cache.factories;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.Cache;
-import org.jboss.cache.CacheSPI;
-import org.jboss.cache.DataContainer;
-import org.jboss.cache.LifecycleManager;
-import org.jboss.cache.config.Configuration;
-import org.jboss.cache.config.ConfigurationException;
-import org.jboss.cache.config.RuntimeConfig;
-import static org.jboss.cache.factories.ComponentRegistry.State.*;
-import org.jboss.cache.factories.annotations.CacheInjectionMethods;
-import org.jboss.cache.factories.annotations.ComponentName;
-import org.jboss.cache.factories.annotations.DefaultFactoryFor;
-import org.jboss.cache.factories.annotations.Destroy;
-import org.jboss.cache.factories.annotations.Inject;
-import org.jboss.cache.factories.annotations.Start;
-import org.jboss.cache.factories.annotations.Stop;
-import org.jboss.cache.interceptors.InterceptorChain;
-import org.jboss.cache.util.BeanUtils;
-import org.jboss.cache.util.reflect.CachedMethod;
-import org.jboss.cache.util.reflect.ReflectionUtil;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * A registry where components which have been created are stored.  Components are stored as singletons, registered under
- * a specific name.  When retrieving components from the registry, callers may specify a component name or just the type
- * of component needed (in which case the fully qualified class name is used as the component name).
- * <p/>
- * Components can be retrieved from the registry using {@link #getComponent(Class)}, or they can be constructed using
- * {@link #getOrCreateComponent(String, Class)} which will scan for default factories and attempt to use such
- * factpries to create the component if needed.
- * <p/>
- * Default factories are treated as components too and will need to be wired and started before being used.
- * <p/>
- * Components can exist in one of 4 states, as defined by the {@link State} enumeration.  The component registry also
- * has a state for the overall component set.  While some components may move to the {@link org.jboss.cache.factories.ComponentRegistry.State#STARTED}
- * state before others (such as factories to create other components) the ComponentRegistry's overall state depicts the lowest
- * possible form for all components.
- * <p/>
- * In terms of the cache, overall state changes in the following manner:
- * <ul>
- * <li>CONSTRUCTED - when created using the DefaultCacheFactory</li>
- * <li>WIRED - when {@link org.jboss.cache.Cache#create()} is called</li>
- * <li>STARTED - when {@link org.jboss.cache.Cache#start()} is called</li>
- * <li>STOPPED - when {@link org.jboss.cache.Cache#stop()} is called</li>
- * </ul>
- * <p/>
- * Cache configuration can only be changed and will only be reinjected if the cache is not in the {@link org.jboss.cache.CacheStatus#STARTED} state.
- *
- * @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
- * @since 2.1.0
- */
-public class ComponentRegistry
-{
-   // TODO: 2.2.0: Needs refactoring
-   //TODO:  2.2.x+ @Start annotation bug: BaseClass.start() and ChildrenClass.start() are annotated with @Start then only base class method is being called
-   static final Object NULL_COMPONENT = new Object();
-
-   State overallState = CONSTRUCTED;
-
-   /**
-    * The registry of components.  Components are stored under their name.
-    */
-   final Map<String, Component> componentLookup = new HashMap<String, Component>();
-
-   /**
-    * Contains class definitions of component factories that can be used to construct certain components
-    */
-   Map<Class, Class<? extends ComponentFactory>> defaultFactories = null;
-
-   private static final Log log = LogFactory.getLog(ComponentRegistry.class);
-   private static final boolean trace = log.isTraceEnabled();
-   private Bootstrap bootstrap;
-
-   // cache of reflection methods to call during injections.  These will be emptied when start() is called.
-   Map<Class, List<CachedMethod>> shortTermMethodCache = null;
-   // these will hang around longer - for components that are frequently created during normal operation.
-   Map<Class, List<CachedMethod>> longTermMethodCache = null;
-
-   /**
-    * Creates an instance of the component registry.  The configuration passed in is automatically registered.
-    *
-    * @param configuration
-    */
-   public ComponentRegistry(Configuration configuration)
-   {
-      // bootstrap.
-      registerDefaultClassLoader(null);
-      registerComponent(this, ComponentRegistry.class);
-      registerComponent(configuration, Configuration.class);
-   }
-
-   /**
-    * Registers the default class loader.  This method *must* be called before any other components are registered,
-    * typically called by bootstrap code.  Defensively, it is called in the constructor of ComponentRegistry with a null
-    * parameter.
-    *
-    * @param loader a class loader to use by default.  If this is null, the class loader used to load this instance of ComponentRegistry is used.
-    */
-   public void registerDefaultClassLoader(ClassLoader loader)
-   {
-      registerComponent("deployerClassLoader", loader == null ? getClass().getClassLoader() : loader, ClassLoader.class);
-   }
-
-
-   public State getOverallState()
-   {
-      return overallState;
-   }
-
-   /**
-    * This is hard coded for now, since scanning the classpath for factories annotated with {@link org.jboss.cache.factories.annotations.DefaultFactoryFor}
-    * does not work with all class loaders.  This is a temporary solution until a more elegant one can be designed.
-    * <p/>
-    * BE SURE TO ADD ANY NEW FACTORY TYPES ANNOTATED WITH DefaultFactoryFor TO THIS SET!!
-    * <p/>
-    *
-    * @return set of known factory types.
-    */
-   private Set<Class<? extends ComponentFactory>> getHardcodedFactories()
-   {
-      Set<Class<? extends ComponentFactory>> s = new HashSet<Class<? extends ComponentFactory>>();
-      s.add(BuddyManagerFactory.class);
-      s.add(EmptyConstructorFactory.class);
-      s.add(InterceptorChainFactory.class);
-      s.add(RuntimeConfigAwareFactory.class);
-      s.add(TransactionManagerFactory.class);
-      s.add(ReplicationQueueFactory.class);
-      return s;
-   }
-
-
-   /**
-    * Adds a singleton instance to the registry.  Note that if an instance of this component already exists in the
-    * registry it is overwritten.  The instance is registered under type <tt>component.getClass()</tt>.  If the component
-    * implements an interface or extends an abstract class, it may make more sense to use {@link #registerComponent(String, Object, Class)}
-    * <p/>
-    * The status of the component is updated th the overall state of the registry, which may involve calling of methods annotated
-    * with {@link org.jboss.cache.factories.annotations.Inject}, {@link org.jboss.cache.factories.annotations.Start} or
-    * {@link org.jboss.cache.factories.annotations.Stop}.
-    * <p/>
-    *
-    * @param component component to add to the registry.
-    */
-   public void registerComponent(Object component, Class type)
-   {
-      registerComponent(type.getName(), component, type);
-   }
-
-   /**
-    * Adds an instance component to the registry, registering the component under the given name.  If an instance already
-    * exists in the registry under the given name, it will be overwritten.
-    * <p/>
-    * The status of the component is updated th the overall state of the registry, which may involve calling of methods annotated
-    * with {@link org.jboss.cache.factories.annotations.Inject}, {@link org.jboss.cache.factories.annotations.Start} or
-    * {@link org.jboss.cache.factories.annotations.Stop}.
-    * <p/>
-    *
-    * @param name      name of the instance
-    * @param component component to add
-    */
-   public void registerComponent(String name, Object component, Class type)
-   {
-      // this will make sure all dependent components are stopped or set to CONSTRUCTED so they can be re-wired later.
-      Component c = new Component(name, component, type);
-      Component old = componentLookup.get(name);
-      if (trace)
-         log.trace("Registering component " + c + " under name " + name + " replacing old component " + old);
-      if (old != null)
-      {
-         // if they are equal don't bother
-         if (old.instance.equals(component))
-         {
-            if (trace)
-               log.trace("Attempting to register a component equal to one that already exists under the same name (" + name + ").  Not doing anything.");
-            return;
-         }
-         // unregister the old component so that components that depend on it can be stopped if necessary
-         unregisterComponent(name);
-         // components that depended on the old component should now depend on the new one.
-         c.dependencyFor.addAll(old.dependencyFor);
-      }
-      componentLookup.put(name, c);
-
-      addComponentDependencies(c, old == null);
-
-      State stateToMoveTo = overallState == null ? CONSTRUCTED : overallState;
-      c.changeState(stateToMoveTo);
-
-      // make sure any other omponents that have inadvertently been stopped are now restarted.
-      if (old != null)
-      {
-         for (Component comp : old.dependencyFor)
-         {
-            if (comp.state != stateToMoveTo) comp.changeState(stateToMoveTo);
-         }
-      }
-   }
-
-   protected void addComponentDependencies(Component c, boolean firstTimeAdded)
-   {
-      // build any dependent components if necessary
-      for (Component d : c.dependencies)
-      {
-         getOrCreateComponent(d.name, d.type);
-         Component dependencyComponent = componentLookup.get(d.name);
-         if (dependencyComponent != null) dependencyComponent.dependencyFor.add(c);
-      }
-
-      if (firstTimeAdded)
-      {
-         // loop through all other components already registered and make sure the current component's dependencyFor map is accurate
-         for (Component other : componentLookup.values())
-         {
-            if (other.dependencies.contains(c)) c.dependencyFor.add(other);
-         }
-      }
-
-   }
-
-   public <T> T getComponent(Class<T> c)
-   {
-      return getComponent(c.getName(), c);
-   }
-
-   /**
-    * Retrieves a named component which can be assigned to the type passed in.  Will return a null if no such component
-    * is registered
-    *
-    * @param c type to be able to assign component to.
-    * @return component, if found, or a null otherwise.
-    */
-   @SuppressWarnings("unchecked")
-   public <T> T getComponent(String name, Class<T> c)
-   {
-      Component wrapper = componentLookup.get(name);
-      if (wrapper == null) return null;
-
-      T component = (T) (wrapper.instance == NULL_COMPONENT ? null : wrapper.instance);
-
-      if (component == null || c.isAssignableFrom(component.getClass())) return component;
-      else
-         throw new ConfigurationException("Component registered under " + name + " is of type " + component.getClass() + " and cannot be assigned to " + c);
-   }
-
-   /**
-    * Retrieves a named component if one exists, and if not, attempts to find a factory capable of constructing the component
-    * (factories annotated with the {@link org.jboss.cache.factories.annotations.DefaultFactoryFor} annotation that is capable
-    * of creating the component class).
-    * <p/>
-    * If an instance needs to be constructed, dependencies are then automatically wired into the instance, based on methods
-    * on the component type annotated with {@link org.jboss.cache.factories.annotations.Inject}.
-    * <p/>
-    * Summing it up, component retrieval happens in the following order:<br />
-    * 1.  Look for an appropriate component that exists in the {@link Configuration} that may be injected from an external system.
-    * 2.  Look for a class definition passed in to the {@link org.jboss.cache.config.Configuration} - such as an EvictionPolicy implementation
-    * 3.  Attempt to create it by looking for an appropriate factory (annotated with {@link org.jboss.cache.factories.annotations.DefaultFactoryFor})
-    * <p/>
-    *
-    * @param componentClass type of component to be retrieved.  Should not be null.
-    * @return a fully wired component instance, or null if one cannot be found or constructed.
-    * @throws ConfigurationException if there is a problem with consructing or wiring the instance.
-    */
-   public <T> T getOrCreateComponent(Class<T> componentClass)
-   {
-      return getOrCreateComponent(null, componentClass);
-   }
-
-   /**
-    * Retrieves a named component if one exists, and if not, attempts to find a factory capable of constructing the component
-    * (factories annotated with the {@link org.jboss.cache.factories.annotations.DefaultFactoryFor} annotation that is capable
-    * of creating the component class).
-    * <p/>
-    * If an instance needs to be constructed, dependencies are then automatically wired into the instance, based on methods
-    * on the component type annotated with {@link org.jboss.cache.factories.annotations.Inject}.
-    * <p/>
-    * Summing it up, component retrieval happens in the following order:<br />
-    * 1.  Look for an appropriate component that exists in the {@link Configuration} that may be injected from an external system.
-    * 2.  Look for a class definition passed in to the {@link org.jboss.cache.config.Configuration} - such as an EvictionPolicy implementation
-    * 3.  Attempt to create it by looking for an appropriate factory (annotated with {@link org.jboss.cache.factories.annotations.DefaultFactoryFor})
-    * <p/>
-    *
-    * @param componentName  name of component to be created.  If null, uses the fully qualified class name as component name.
-    * @param componentClass type of component to be retrieved.  Should not be null.
-    * @return a fully wired component instance, or null if one cannot be found or constructed.
-    * @throws ConfigurationException if there is a problem with consructing or wiring the instance.
-    */
-   public <T> T getOrCreateComponent(String componentName, Class<T> componentClass)
-   {
-      T component = getComponent(componentName == null ? componentClass.getName() : componentName, componentClass);
-
-      if (component == null)
-      {
-         // first see if this has been injected externally.
-         component = getFromConfiguration(componentClass);
-         boolean attemptedFactoryConstruction = false;
-
-         if (component == null && isNonBootstrapClass(componentClass))
-         {
-            // create this component and add it to the registry
-            ComponentFactory factory = getFactory(componentClass);
-            component = factory.construct(componentName, componentClass);
-            attemptedFactoryConstruction = true;
-
-         }
-
-         String componentNameToUse = componentName == null ? componentClass.getName() : componentName;
-
-         if (component != null)
-         {
-            registerComponent(componentNameToUse, component, componentClass);
-         }
-         else if (attemptedFactoryConstruction)
-         {
-            if (trace) log.trace("Registering a null for component " + componentNameToUse);
-            registerNullComponent(componentNameToUse, componentClass);
-         }
-      }
-
-      return component;
-   }
-
-   // registers a special "null" component that has no dependencies.
-   void registerNullComponent(String componentName, Class type)
-   {
-      registerComponent(componentName, NULL_COMPONENT, type);
-   }
-
-   private boolean isNonBootstrapClass(Class<?> componentClass)
-   {
-      return !(componentClass.equals(CacheSPI.class) || componentClass.equals(LifecycleManager.class) ||
-            componentClass.equals(Cache.class) || componentClass.equals(ComponentRegistry.class) ||
-            componentClass.equals(Configuration.class));
-   }
-
-   @SuppressWarnings("unchecked")
-         <T> T getFromConfiguration(Class<T> componentClass)
-   {
-      if (log.isDebugEnabled())
-         log.debug("Looking in configuration for an instance of " + componentClass + " that may have been injected from an external source.");
-      Method getter = BeanUtils.getterMethod(Configuration.class, componentClass);
-      T returnValue = null;
-
-      if (getter != null)
-      {
-         try
-         {
-            returnValue = (T) getter.invoke(getConfiguration());
-         }
-         catch (Exception e)
-         {
-            log.warn("Unable to invoke getter " + getter + " on Configuration.class!", e);
-         }
-      }
-
-      // now try the RuntimeConfig - a legacy "registry" of sorts.
-      if (returnValue == null)
-      {
-         getter = BeanUtils.getterMethod(RuntimeConfig.class, componentClass);
-         if (getter != null)
-         {
-            try
-            {
-               returnValue = (T) getter.invoke(getConfiguration().getRuntimeConfig());
-            }
-            catch (Exception e)
-            {
-               log.warn("Unable to invoke getter " + getter + " on RuntimeConfig.class!", e);
-            }
-         }
-      }
-      return returnValue;
-   }
-
-   Configuration getConfiguration()
-   {
-      // this is assumed to always be present as a part of the bootstrap/construction of a ComponentRegistry.
-      return getComponent(Configuration.class);
-   }
-
-   /**
-    * Updates (re-injects) any dependencies needed by all components already in the registry.
-    */
-   public void updateDependencies()
-   {
-      State originalState = overallState;
-      moveComponentsToState(overallState == STARTED ? STOPPED : CONSTRUCTED);
-      moveComponentsToState(originalState);
-      // re- add a few key components - this is a hack for now
-      LifecycleManager clm = getComponent(LifecycleManager.class);
-      CacheSPI spi = getComponent(CacheSPI.class.getName(), CacheSPI.class);
-      CommandsFactory commandsFactory = getComponent(CommandsFactory.class.getName(), CommandsFactory.class);
-
-      unregisterComponent(LifecycleManager.class);
-      unregisterComponent(CacheSPI.class);
-      unregisterComponent(CommandsFactory.class);
-
-      overallState = CONSTRUCTED;
-
-      registerComponent(LifecycleManager.class.getName(), clm, LifecycleManager.class);
-      registerComponent(CacheSPI.class.getName(), spi, CacheSPI.class);
-      registerComponent(CommandsFactory.class.getName(), commandsFactory, CommandsFactory.class);
-
-      overallState = originalState;
-      moveComponentsToState(overallState);
-   }
-
-   /**
-    * Removes a component from the registry.  If the component has already been injected into other components, you should
-    * call {@link #updateDependencies()} to ensure dependencies are updated.
-    *
-    * @param clazz class of component to remove.
-    */
-   public void unregisterComponent(Class<?> clazz)
-   {
-      unregisterComponent(clazz.getName());
-   }
-
-   /**
-    * Removes a component from the registry.  If the component has already been injected into other components, you should
-    * call {@link #updateDependencies()} to ensure dependencies are updated.
-    *
-    * @param name name of the component to remove.
-    */
-   public void unregisterComponent(String name)
-   {
-      Component c = componentLookup.remove(name);
-      if (c != null) c.changeState(c.state == STARTED ? STOPPED : CONSTRUCTED);
-   }
-
-   /**
-    * Wires an object instance with dependencies annotated with the {@link org.jboss.cache.factories.annotations.Inject} annotation, creating more components
-    * as needed based on the Configuration passed in if these additional components don't exist in the
-    * {@link ComponentRegistry}.  Strictly for components that don't otherwise live in the registry and have a lifecycle, such as Nodes.
-    *
-    * @param target object to wire
-    * @throws ConfigurationException if there is a problem wiring the instance
-    */
-   public void wireDependencies(Object target) throws ConfigurationException
-   {
-      //if (trace) log.trace("Inspecting class " + target.getClass());
-      try
-      {
-         // look in caches first
-         List<CachedMethod> methods = lookupInjectionMethods(target.getClass());
-         //if (trace) log.trace("Found method set containing " + methods.size() + " methods that need injection: " + methods);
-
-         // search for anything we need to inject
-         for (CachedMethod method : methods)
-         {
-            //if (trace) log.trace("Method " + method + " needs some other components injected!");
-            performInjection(method, target);
-         }
-      }
-      catch (Exception e)
-      {
-         throw new ConfigurationException("Unable to configure component (type: " + target.getClass() + ", instance " + target + ")", e);
-      }
-   }
-
-   private List<CachedMethod> lookupInjectionMethods(Class type)
-   {
-      if (longTermMethodCache != null && longTermMethodCache.containsKey(type)) return longTermMethodCache.get(type);
-      if (shortTermMethodCache != null && shortTermMethodCache.containsKey(type)) return shortTermMethodCache.get(type);
-
-      List<CachedMethod> methods = ReflectionUtil.getAllCachedMethods(type, Inject.class);
-      if (type.isAnnotationPresent(CacheInjectionMethods.class))
-      {
-         if (longTermMethodCache == null) longTermMethodCache = new HashMap<Class, List<CachedMethod>>();
-         longTermMethodCache.put(type, methods);
-      }
-      else
-      {
-         if (shortTermMethodCache == null) shortTermMethodCache = new HashMap<Class, List<CachedMethod>>();
-         shortTermMethodCache.put(type, methods);
-      }
-
-      return methods;
-   }
-
-   /**
-    * Looks through the parameter list of the given method, attempts to locate parameters that fit the types that may
-    * exist in the {@link ComponentRegistry}, and then calls the method on the target object with the necessary parameters.
-    *
-    * @param method Method to call
-    * @param target Instance on which to call the method
-    * @throws IllegalAccessException if the method cannot be called
-    * @throws java.lang.reflect.InvocationTargetException
-    *                                if the method cannot be called
-    */
-   @SuppressWarnings("unchecked")
-   private <T> void performInjection(CachedMethod method, T target) throws IllegalAccessException, InvocationTargetException
-   {
-      Class[] parameterTypes = method.getParameterTypes();
-      List<Component> componentsToInject = getDeclaredDependencies(method);
-
-      Object[] parameters = new Object[parameterTypes.length];
-
-      for (int i = 0; i < parameterTypes.length; i++)
-      {
-         parameters[i] = getOrCreateComponent(componentsToInject.get(i).name, parameterTypes[i]);
-      }
-
-      Method reflectMethod = method.getMethod();
-      // make sure we set this method to be accessible, so we can call private, package and protected
-      // methods rather than just public ones.
-      reflectMethod.setAccessible(true);
-
-      // invoke the method with the parameters we've worked out.
-      reflectMethod.invoke(target, parameters);
-   }
-
-   private String extractComponentName(Annotation[] annotationsOnParameter)
-   {
-      for (Annotation a : annotationsOnParameter)
-      {
-         if (a instanceof ComponentName)
-         {
-            ComponentName cn = (ComponentName) a;
-            return cn.value();
-         }
-      }
-      return null;
-   }
-
-   private List<Component> getDeclaredDependencies(CachedMethod method)
-   {
-      List<Component> dependencies = new LinkedList<Component>();
-      Class[] parameterTypes = method.getParameterTypes();
-      Annotation[][] annotationsOnParams = method.getParameterAnnotations();
-      for (int i = 0; i < parameterTypes.length; i++)
-      {
-         String componentName = extractComponentName(annotationsOnParams[i]);
-         String componentNameToUse = componentName == null ? parameterTypes[i].getName() : componentName;
-         // if the component exists in the lookup, use it.  Otherwise use a placeholder which will be constructed later, on demand.
-         Component d = componentLookup.containsKey(componentNameToUse) ? componentLookup.get(componentNameToUse) : new Component(componentNameToUse, parameterTypes[i]);
-         dependencies.add(d);
-      }
-      return dependencies;
-   }
-
-   /**
-    * Retrieves a component factory instance capable of constructing components of a specified type.  If the factory doesn't
-    * exist in the registry, one is created.  Always changes the state of any factory to {@link State#STARTED} before returning.
-    *
-    * @param componentClass type of component to construct
-    * @return component factory capable of constructing such components
-    */
-   protected ComponentFactory getFactory(Class componentClass)
-   {
-      if (defaultFactories == null) scanDefaultFactories();
-      Class<? extends ComponentFactory> cfClass = defaultFactories.get(componentClass);
-      if (cfClass == null)
-         throw new ConfigurationException("No registered default factory for component " + componentClass + " found!");
-      // a component factory is a component too!  See if one has been created and exists in the registry
-      ComponentFactory cf = getComponent(cfClass);
-      if (cf == null)
-      {
-         // hasn't yet been created.  Create and put in registry
-         cf = instantiateFactory(cfClass);
-         if (cf != null)
-         {
-            // we simply register this factory.  Registration will take care of constructing any dependencies.
-            registerComponent(cf, cfClass);
-         }
-      }
-
-      if (cf == null)
-         throw new ConfigurationException("Unable to locate component factory for component " + componentClass);
-
-      // ensure the component factory is in the STARTED state!
-      Component c = componentLookup.get(cfClass.getName());
-      if (c.instance != cf)
-         throw new ConfigurationException("Component factory " + cfClass + " incorrectly registered!");
-      c.changeState(STARTED);
-      return cf;
-   }
-
-   /**
-    * Scans the class path for classes annotated with {@link org.jboss.cache.factories.annotations.DefaultFactoryFor}, and
-    * analyses which components can be created by such factories.
-    */
-   void scanDefaultFactories()
-   {
-      defaultFactories = new HashMap<Class, Class<? extends ComponentFactory>>();
-
-      Set<Class<? extends ComponentFactory>> factories = getHardcodedFactories();
-
-      for (Class<? extends ComponentFactory> factory : factories)
-      {
-         DefaultFactoryFor dFFAnnotation = factory.getAnnotation(DefaultFactoryFor.class);
-         for (Class targetClass : dFFAnnotation.classes()) defaultFactories.put(targetClass, factory);
-      }
-   }
-
-   /**
-    * No such thing as a meta factory yet.  Factories are created using this method which attempts to use an empty public
-    * constructor.
-    *
-    * @param factory class of factory to be created
-    * @return factory instance
-    */
-   ComponentFactory instantiateFactory(Class<? extends ComponentFactory> factory)
-   {
-      try
-      {
-         return factory.newInstance();
-      }
-      catch (Exception e)
-      {
-         // unable to get a hold of an instance!!
-         throw new ConfigurationException("Unable to instantiate factory " + factory, e);
-      }
-   }
-
-   /**
-    * Wipes everything in the registry.  Use with care.
-    */
-   public void reset()
-   {
-      // the bootstrap classes
-      Component deployerClassLoader = componentLookup.get("deployerClassLoader");
-      Component spi = componentLookup.get(CacheSPI.class.getName());
-      Component interceptorChain = componentLookup.get(InterceptorChain.class.getName());
-      Component lifeCycleManager = componentLookup.get(LifecycleManager.class.getName());
-      Component dataContainer = componentLookup.get(DataContainer.class.getName());
-      Component conf = componentLookup.get(Configuration.class.getName());
-      Component cr = componentLookup.get(ComponentRegistry.class.getName());
-
-      // destroy all components to clean up resources
-      for (Component c : componentLookup.values()) c.changeState(DESTROYED);
-
-      // remove from componentLookup
-      componentLookup.clear();
-
-      // bootstrap components
-      deployerClassLoader.changeState(CONSTRUCTED);
-      spi.changeState(CONSTRUCTED);
-      interceptorChain.changeState(CONSTRUCTED);
-      lifeCycleManager.changeState(CONSTRUCTED);
-      dataContainer.changeState(CONSTRUCTED);
-      conf.changeState(CONSTRUCTED);
-      cr.changeState(CONSTRUCTED);
-
-      bootstrap = new Bootstrap((ClassLoader) deployerClassLoader.instance, (InterceptorChain) interceptorChain.instance,
-            (LifecycleManager) lifeCycleManager.instance, (DataContainer) dataContainer.instance, (CacheSPI) spi.instance,
-            (ComponentRegistry) cr.instance, (Configuration) conf.instance);
-
-      overallState = null;
-   }
-
-   /**
-    * Starts all components that contain the {@link Start} annotation.
-    */
-   public void start()
-   {
-      moveComponentsToState(STARTED);
-      shortTermMethodCache = null;
-   }
-
-   /**
-    * Stops all components that contain the {@link Stop} annotation.
-    */
-   public void stop()
-   {
-      moveComponentsToState(STOPPED);
-   }
-
-   /**
-    * Injects dependencies to all components that require injection.
-    */
-   public void wire()
-   {
-      moveComponentsToState(WIRED);
-   }
-
-   void moveComponentsToState(State state)
-   {
-      if (overallState == null && bootstrap != null && !bootstrap.isBootstrapped())
-      {
-         // we have been destroyed!  Need to bootstrap again.
-         bootstrap.bootstrap();
-      }
-
-      // copy the component lookup CHM to prevent concurrent modification exceptions later on, if components need to be
-      // constructed and added to the system on the fly.
-      Set<Component> components = new HashSet<Component>(componentLookup.values());
-      for (Component c : components) c.changeState(state);
-
-      overallState = state;
-   }
-
-   /**
-    * Represents the state of a component
-    */
-   public enum State
-   {
-      DESTROYED, STOPPED, CONSTRUCTED, WIRED, STARTED;
-
-      /**
-       * Tests whether the current state is "greater" than the state passed in
-       *
-       * @param other state to compare with
-       * @return true if the current state is "greater" than the state passed in
-       */
-      boolean isGreaterThan(State other)
-      {
-         return this.ordinal() > other.ordinal();
-      }
-
-      /**
-       * Tests whether the current state is "less" than the state passed in
-       *
-       * @param other state to compare with
-       * @return true if the current state is "less" than the state passed in
-       */
-      boolean isLessThan(State other)
-      {
-         return this.ordinal() < other.ordinal();
-      }
-
-      /**
-       * @param other state to compare with
-       * @return the absolute difference in ordinal places between 2 states
-       */
-      int absoluteDifference(State other)
-      {
-         return Math.abs(this.ordinal() - other.ordinal());
-      }
-   }
-
-   /**
-    * Represents a component in the registry, along with state and dependencies.
-    */
-   class Component
-   {
-      Object instance;
-      final String name;
-      final Class type;
-      State state = CONSTRUCTED;
-      final Set<Component> dependencies = new HashSet<Component>(3);
-      final Set<Component> dependencyFor = new HashSet<Component>(3);
-      boolean deepRecursionDetector = false;
-
-      public Component(String name, Class type)
-      {
-         this.name = name;
-         this.type = type;
-      }
-
-      /**
-       * Constructs a Component out of an instance and a name.  Scans instance for dependencies and populates
-       * the "dependencies" and "dependencyFor" collections.
-       *
-       * @param name     name of component
-       * @param instance component instance
-       */
-      public Component(String name, Object instance, Class type)
-      {
-         this(name, type);
-         this.instance = instance;
-
-         // now scan the instance for all dependencies.
-         List<CachedMethod> injectionMethods = lookupInjectionMethods(instance.getClass());
-
-         // now for each injection method, get dependencies
-         for (CachedMethod m : injectionMethods) dependencies.addAll(getDeclaredDependencies(m));
-      }
-
-      /**
-       * Changes the state of a component - along with all dependent components - to a new state.  This method is recursion
-       * and cyclic dependency safe.
-       *
-       * @param newState new state to move component to
-       */
-      void changeState(State newState)
-      {
-         // Deep recursion is when this component depends on another component which in turn may depend on this component again.
-         // if this is encountered then break out of the recursive loop.
-         if (state != newState && !deepRecursionDetector)
-         {
-            // Step by step.  If the new state is > 1 step away from the current state, change state gradually.
-            boolean increase = newState.isGreaterThan(state);
-            int numSteps = newState.absoluteDifference(state);
-
-            while (numSteps > 1)
-            {
-               changeState(State.values()[state.ordinal() + (increase ? 1 : -1)]);
-               numSteps = newState.absoluteDifference(state);
-            }
-
-            // now we update the state of dependent components accordingly.
-            Set<Component> dependentComponents = new HashSet<Component>();
-            Set<Component> shallowCyclic = new HashSet<Component>();
-
-            if (increase)
-            {
-               // if I am moving to a "higher" state make sure all components that I depend on have moved to that state as well.
-               dependentComponents.addAll(dependencies);
-            }
-            else
-            {
-               // if I am moving to a "lower" state make sure all components depend on me have moved to that state as well.
-               dependentComponents.addAll(dependencyFor);
-            }
-
-            // switch on the deep recursion detector
-            deepRecursionDetector = true;
-            for (Component d : dependentComponents)
-            {
-               if (d != null)
-               {
-                  // always look up again in the component lookup.  The dependencies and dependenciesFor sets are just
-                  // used as references.  The actual component instances may be out of date.
-                  d = componentLookup.get(d.name);
-
-                  if (d != null)
-                  {
-                     if (isShallowCyclic(d))
-                     {
-                        // don't invoke shallow cyclic deps here - shoud do that after we set our state.
-                        shallowCyclic.add(d);
-                     }
-                     else
-                     {
-                        // of we are "moving up" - only do this if the component is lower than what is needed.
-                        if ((increase && newState.isGreaterThan(d.state)) || (!increase && newState.isLessThan(d.state)))
-                        {
-                           d.changeState(newState);
-                        }
-                     }
-                  }
-               }
-            }
-
-            // NOW we update our state.
-            switch (newState)
-            {
-               case STOPPED:
-                  stop();
-                  break;
-               case WIRED:
-                  if (increase) wire();
-                  break;
-               case STARTED:
-                  start();
-                  break;
-               case DESTROYED:
-                  destroy();
-                  break;
-               case CONSTRUCTED:
-                  // do nothing
-            }
-
-            state = newState;
-
-            // now process the shallow cyclic deps
-            for (Component c : shallowCyclic)
-            {
-               // of we are "moving up" - only do this if the component is lower than what is needed.
-               if ((increase && newState.isGreaterThan(c.state)) || (!increase && newState.isLessThan(c.state)))
-                  c.changeState(newState);
-            }
-
-            // make sure we switch off the deep recursion detector now.
-            deepRecursionDetector = false;
-         }
-      }
-
-      /**
-       * Tests whether there is an immediate cyclic dependency (i.e., both components depend on each other) between the current component and another one.
-       *
-       * @param c other component to test with
-       * @return true if there is an immediate cyclic dependency between the 2 components
-       */
-      private boolean isShallowCyclic(Component c)
-      {
-         return dependencies.contains(c) && c.dependencies.contains(this);
-      }
-
-      /**
-       * Used to wire dependencies into this component instance.
-       */
-      void wire()
-      {
-         try
-         {
-            List<CachedMethod> methods = lookupInjectionMethods(instance.getClass());
-
-            // search for anything we need to inject
-            for (CachedMethod method : methods) performInjection(method, instance);
-         }
-         catch (Exception e)
-         {
-            throw new ConfigurationException("Unable to configure component (type: " + instance.getClass() + ", instance " + instance + ")", e);
-         }
-      }
-
-      /**
-       * Used to call all methods annotated with {@link Start} on component instance
-       */
-      void start()
-      {
-         invokeMethods(Start.class);
-      }
-
-      /**
-       * Used to call all methods annotated with {@link Stop} on component instance
-       */
-      void stop()
-      {
-         invokeMethods(Stop.class);
-      }
-
-      /**
-       * Used to call all methods annotated with {@link org.jboss.cache.factories.annotations.Destroy} on component instance
-       */
-      void destroy()
-      {
-         invokeMethods(Destroy.class);
-      }
-
-      private void invokeMethods(Class<? extends Annotation> annotation)
-      {
-         List<Method> methods = ReflectionUtil.getAllMethods(instance.getClass(), annotation);
-         for (Method m : methods)
-         {
-            try
-            {
-               m.setAccessible(true);
-               m.invoke(instance);
-            }
-            catch (Exception e)
-            {
-               log.warn("Unable to invoke annotated method " + m, e);
-            }
-         }
-      }
-
-      @Override
-      public String toString()
-      {
-         return "Component (name = " + name + ", state = " + state + ")";
-      }
-
-      @Override
-      public int hashCode()
-      {
-         return 31 * name.hashCode();
-      }
-
-      @Override
-      public boolean equals(Object other)
-      {
-         return other instanceof Component && name.equals(((Component) other).name);
-      }
-
-   }
-
-   class Bootstrap
-   {
-      final InterceptorChain interceptorChain;
-      final LifecycleManager lifecycleManager;
-      final DataContainer dataContainer;
-      final CacheSPI cacheSPI;
-      final ComponentRegistry componentRegistry;
-      final Configuration configuration;
-      private final ClassLoader deployerClassLoader;
-
-      Bootstrap(ClassLoader deployerClassLoader, InterceptorChain interceptorChain, LifecycleManager lifecycleManager,
-                DataContainer dataContainer, CacheSPI cacheSPI, ComponentRegistry componentRegistry, Configuration configuration)
-      {
-         this.deployerClassLoader = deployerClassLoader;
-         this.lifecycleManager = lifecycleManager;
-         this.dataContainer = dataContainer;
-         this.interceptorChain = interceptorChain;
-         this.cacheSPI = cacheSPI;
-         this.componentRegistry = componentRegistry;
-         this.configuration = configuration;
-      }
-
-      boolean isBootstrapped()
-      {
-         return componentLookup.containsKey(Configuration.class.getName()) &&
-               componentLookup.containsKey(LifecycleManager.class.getName()) &&
-               componentLookup.containsKey(InterceptorChain.class.getName()) &&
-               componentLookup.containsKey(DataContainer.class.getName()) &&
-               componentLookup.containsKey(CacheSPI.class.getName()) &&
-               componentLookup.containsKey(ComponentRegistry.class.getName()) &&
-               componentLookup.containsKey("deployerClassLoader");
-      }
-
-      void bootstrap()
-      {
-         overallState = CONSTRUCTED;
-         registerComponent("deployerClassLoader", deployerClassLoader, ClassLoader.class);
-         registerComponent(Configuration.class.getName(), configuration, Configuration.class);
-         registerComponent(ComponentRegistry.class.getName(), componentRegistry, ComponentRegistry.class);
-         registerComponent(InterceptorChain.class.getName(), interceptorChain, InterceptorChain.class);
-         registerComponent(LifecycleManager.class.getName(), lifecycleManager, LifecycleManager.class);
-         registerComponent(DataContainer.class.getName(), dataContainer, DataContainer.class);
-         registerComponent(CacheSPI.class.getName(), cacheSPI, CacheSPI.class);
-      }
-   }
-}
\ No newline at end of file




More information about the jbosscache-commits mailing list