View Javadoc
1   package com.atlassian.plugin.spring;
2   
3   import com.atlassian.plugin.osgi.hostcomponents.ContextClassLoaderStrategy;
4   import org.springframework.beans.factory.config.BeanDefinition;
5   import org.springframework.beans.factory.support.BeanDefinitionBuilder;
6   import org.springframework.beans.factory.support.BeanDefinitionRegistry;
7   
8   import java.util.ArrayList;
9   import java.util.Collection;
10  import java.util.Collections;
11  import java.util.HashMap;
12  import java.util.HashSet;
13  import java.util.List;
14  import java.util.Map;
15  import java.util.Set;
16  
17  import static com.atlassian.plugin.util.Assertions.notNull;
18  
19  public class PluginBeanDefinitionRegistry {
20      public static final String HOST_COMPONENT_PROVIDER = "hostComponentProvider";
21  
22      private static final String BEAN_NAMES = "beanNames";
23      private static final String BEAN_INTERFACES = "beanInterfaces";
24      private static final String BEAN_CONTEXT_CLASS_LOADER_STRATEGIES = "beanContextClassLoaderStrategies";
25      private static final String BUNDLE_TRACKING_BEANS = "bundleTrackingBeans";
26  
27      private final BeanDefinitionRegistry registry;
28  
29      public PluginBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
30          this.registry = notNull("registry", registry);
31      }
32  
33      public BeanDefinition getBeanDefinition() {
34          if (!registry.containsBeanDefinition(HOST_COMPONENT_PROVIDER)) {
35              BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(SpringHostComponentProviderFactoryBean.class);
36              BeanDefinition beanDef = builder.getBeanDefinition();
37              primeHostComponentBeanDefinition(beanDef);
38  
39              registry.registerBeanDefinition(HOST_COMPONENT_PROVIDER, beanDef);
40          }
41  
42          final BeanDefinition beanDef = registry.getBeanDefinition(HOST_COMPONENT_PROVIDER);
43          primeHostComponentBeanDefinition(beanDef);
44  
45          if (beanDef == null) {
46              throw new IllegalStateException("Host component provider not found nor created. This should never happen.");
47          }
48          return beanDef;
49      }
50  
51      private void primeHostComponentBeanDefinition(BeanDefinition beanDef) {
52          ensurePropertyNotNull(beanDef, BEAN_NAMES, new ArrayList<String>());
53          ensurePropertyNotNull(beanDef, BEAN_INTERFACES, new HashMap<String, List<String>>());
54          ensurePropertyNotNull(beanDef, BEAN_CONTEXT_CLASS_LOADER_STRATEGIES, new HashMap<String, ContextClassLoaderStrategy>());
55          ensurePropertyNotNull(beanDef, BUNDLE_TRACKING_BEANS, new HashSet<String>());
56      }
57  
58      private void ensurePropertyNotNull(BeanDefinition beanDef, String propertyName, Object defaultValue) {
59          if (!beanDef.getPropertyValues().contains(propertyName)) {
60              beanDef.getPropertyValues().addPropertyValue(propertyName, defaultValue);
61          }
62      }
63  
64      public void addBeanName(String beanName) {
65          getBeanNames().add(beanName);
66      }
67  
68      public void addBeanInterface(String beanName, String ifce) {
69          addBeanInterfaces(beanName, Collections.singleton(ifce));
70      }
71  
72      public void addBeanInterfaces(String beanName, Collection<String> ifces) {
73          final Map<String, List<String>> beanInterfaces = getBeanInterfaces();
74  
75          List<String> interfaces = beanInterfaces.get(beanName);
76          if (interfaces == null) {
77              interfaces = new ArrayList<>();
78              beanInterfaces.put(beanName, interfaces);
79          }
80          interfaces.addAll(ifces);
81      }
82  
83      public void addContextClassLoaderStrategy(String beanName, ContextClassLoaderStrategy strategy) {
84          getBeanContextClassLoaderStrategies().put(beanName, strategy);
85      }
86  
87      public void addBundleTrackingBean(String beanName) {
88          getBundleTrackingBeans().add(beanName);
89      }
90  
91      @SuppressWarnings("unchecked")
92      private Map<String, ContextClassLoaderStrategy> getBeanContextClassLoaderStrategies() {
93          return (Map<String, ContextClassLoaderStrategy>) getPropertyValue(BEAN_CONTEXT_CLASS_LOADER_STRATEGIES);
94      }
95  
96      @SuppressWarnings("unchecked")
97      private Map<String, List<String>> getBeanInterfaces() {
98          return (Map<String, List<String>>) getPropertyValue(BEAN_INTERFACES);
99      }
100 
101     @SuppressWarnings("unchecked")
102     private List<String> getBeanNames() {
103         return (List<String>) getPropertyValue(BEAN_NAMES);
104     }
105 
106     @SuppressWarnings("unchecked")
107     private Set<String> getBundleTrackingBeans() {
108         return (Set<String>) getPropertyValue(BUNDLE_TRACKING_BEANS);
109     }
110 
111     private Object getPropertyValue(String propertyName) {
112         return getBeanDefinition().getPropertyValues().getPropertyValue(propertyName).getValue();
113     }
114 }