1   package com.atlassian.user.configuration;
2   
3   import com.atlassian.user.GroupManager;
4   import com.atlassian.user.UserManager;
5   import com.atlassian.user.properties.PropertySetFactory;
6   import com.atlassian.user.util.ClassLoaderUtils;
7   import org.apache.log4j.Logger;
8   import org.springframework.beans.factory.support.DefaultListableBeanFactory;
9   import org.springframework.beans.factory.support.RootBeanDefinition;
10  
11  import java.util.Arrays;
12  import java.util.Iterator;
13  import java.util.List;
14  
15  public class DefaultRepositoryProcessor implements RepositoryProcessor
16  {
17      protected final Logger log = Logger.getLogger(this.getClass());
18  
19      public RepositoryAccessor process(RepositoryConfiguration config) throws ConfigurationException
20      {
21          DefaultListableBeanFactory beanFactory = createComponentContext(config);
22  
23          beanFactory.registerSingleton("identifier", config.getIdentifier());
24  
25          List componentNames = Arrays.asList(new String[]{
26              Configuration.PROPERTYSET_FACTORY,
27              Configuration.PASSWORD_ENCRYPTOR,
28              Configuration.USERMANAGER,
29              Configuration.AUTHENTICATOR,
30              Configuration.GROUPMANAGER,
31              Configuration.ENTITY_QUERY_PARSER,
32          });
33          for (Iterator it = componentNames.iterator(); it.hasNext();)
34          {
35              String component = (String) it.next();
36              if (!config.hasClassForComponent(component)) continue;
37              beanFactory.registerBeanDefinition(component,
38                  createBeanDefinition(config.getComponentClassName(component), true));
39          }
40  
41          beanFactory.registerBeanDefinition(Configuration.CLASS,
42              createBeanDefinition(config.getComponentClassName(Configuration.CLASS), false));
43          DefaultRepositoryAccessor accessor = (DefaultRepositoryAccessor) beanFactory.getBean(Configuration.CLASS);
44  
45          if (config.isCachingEnabled())
46          {
47              CacheConfiguration cacheConfiguration = config.getCacheConfiguration();
48              beanFactory.registerBeanDefinition("cachingUserManager", createBeanDefinition(
49                  cacheConfiguration.getUserManagerClassName(), true));
50              beanFactory.registerBeanDefinition("cachingGroupManager", createBeanDefinition(
51                  cacheConfiguration.getGroupManagerClassName(), true));
52              beanFactory.registerBeanDefinition("cachingPropertySetFactory", createBeanDefinition(
53                  cacheConfiguration.getPropertySetFactoryClassName(), true));
54  
55              accessor.setUserManager((UserManager) beanFactory.getBean("cachingUserManager"));
56              accessor.setGroupManager((GroupManager) beanFactory.getBean("cachingGroupManager"));
57              
58              if (beanFactory.containsBeanDefinition("propertySetFactory"))
59                  accessor.setPropertySetFactory((PropertySetFactory) beanFactory.getBean("cachingPropertySetFactory"));
60          }
61  
62          return accessor;
63      }
64  
65      protected Object createBean(String componentName, RepositoryConfiguration config)
66      {
67          return createBean(componentName, config, true);
68      }
69  
70      protected Object createBean(String componentName, RepositoryConfiguration config,
71          boolean useConstructorInjection)
72      {
73          DefaultListableBeanFactory beanFactory = createComponentContext(config);
74          String className = config.getComponentClassName(componentName);
75          if(className == null)
76          {
77              throw new RuntimeException("expected component [ "+componentName+" ] does not specify a className");
78          }
79          beanFactory.registerBeanDefinition(componentName, createBeanDefinition(className, useConstructorInjection));
80          return beanFactory.getBean(componentName);
81      }
82  
83      private RootBeanDefinition createBeanDefinition(String className, boolean useConstructorInjection)
84      {
85          int autowireMode = useConstructorInjection ? RootBeanDefinition.AUTOWIRE_CONSTRUCTOR :
86              RootBeanDefinition.AUTOWIRE_BY_TYPE;
87          return new RootBeanDefinition(getClassForName(className), autowireMode);
88      }
89  
90      /**
91       * Gets the specified class using {@link ClassLoaderUtils#loadClass(String,Class)}.
92       *
93       * @param className the fully qualified name of the class to retrieve
94       * @throws RuntimeException if the class cannot be found.
95       */
96      protected Class getClassForName(String className)
97      {
98          try
99          {
100             return ClassLoaderUtils.loadClass(className, this.getClass());
101         }
102         catch (ClassNotFoundException e)
103         {
104             throw new RuntimeException("Could not find class: [" + className + "]", e);
105         }
106     }
107 
108     /**
109      * Create a Spring bean factory containing the components in the provided map.
110      *
111      * @return the bean factory containing the components.
112      */
113     protected DefaultListableBeanFactory createComponentContext(RepositoryConfiguration config)
114     {
115         DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
116         for (Iterator iter = config.getComponentNames().iterator(); iter.hasNext();)
117         {
118             String name = (String) iter.next();
119             Object component = config.getComponent(name);
120             beanFactory.registerSingleton(name, component);
121         }
122         return beanFactory;
123     }
124 }