View Javadoc

1   package com.atlassian.sal.spring.component;
2   
3   import com.atlassian.sal.spi.HostContextAccessor;
4   import org.slf4j.Logger;
5   import org.slf4j.LoggerFactory;
6   import org.springframework.beans.BeansException;
7   import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
8   import org.springframework.beans.factory.support.DefaultListableBeanFactory;
9   import org.springframework.context.ApplicationContext;
10  import org.springframework.context.ApplicationContextAware;
11  import org.springframework.context.support.AbstractApplicationContext;
12  import org.springframework.transaction.PlatformTransactionManager;
13  import org.springframework.transaction.TransactionDefinition;
14  import org.springframework.transaction.TransactionStatus;
15  import org.springframework.transaction.support.DefaultTransactionDefinition;
16  
17  import java.util.HashMap;
18  import java.util.Map;
19  
20  /**
21   * Implements the host context accessor for Spring environments
22   */
23  public class SpringHostContextAccessor implements HostContextAccessor, ApplicationContextAware {
24      private ApplicationContext applicationContext;
25      private final PlatformTransactionManager transactionManager;
26      private static final Logger log = LoggerFactory.getLogger(SpringHostContextAccessor.class);
27  
28      public SpringHostContextAccessor(final PlatformTransactionManager transactionManager) {
29          this.transactionManager = transactionManager;
30      }
31  
32      @SuppressWarnings("unchecked")
33      public <T> Map<String, T> getComponentsOfType(final Class<T> iface) {
34          try {
35              return applicationContext.getBeansOfType(iface);
36          } catch (final RuntimeException ex) {
37              // This exception will start occuring after removing bean from the context (eg: disabling plugin)
38              // until next restart of Confluence. See https://studio.atlassian.com/browse/JST-509
39              log.debug("Can't get beans", ex);
40              final Map<String, T> results = new HashMap<String, T>();
41              if (applicationContext instanceof AbstractApplicationContext) {
42                  final AbstractApplicationContext abstractApplicationContext = (AbstractApplicationContext) applicationContext;
43                  final ConfigurableListableBeanFactory beanFactory = abstractApplicationContext.getBeanFactory();
44                  if (beanFactory instanceof DefaultListableBeanFactory) {
45                      final DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;
46                      final String[] beanDefinitionNames = defaultListableBeanFactory.getBeanDefinitionNames();
47                      for (final String beanName : beanDefinitionNames) {
48                          try {
49                              final Object bean = defaultListableBeanFactory.getBean(beanName);
50                              if (bean != null && iface.isAssignableFrom(bean.getClass())) {
51                                  results.put(beanName, (T) bean);
52                              }
53                          } catch (final BeansException e) {
54                              // ignore
55                          }
56                      }
57                  }
58              }
59              return results;
60          }
61  
62  
63      }
64  
65      public Object doInTransaction(final HostTransactionCallback callback) {
66          final org.springframework.transaction.support.TransactionTemplate txTemplate =
67                  new org.springframework.transaction.support.TransactionTemplate(transactionManager, getTransactionDefinition());
68          return txTemplate.execute(new org.springframework.transaction.support.TransactionCallback() {
69              public Object doInTransaction(final TransactionStatus transactionStatus) {
70                  try {
71                      return callback.doInTransaction();
72                  } catch (final RuntimeException e) {
73                      //rollback if something weird happened.
74                      transactionStatus.setRollbackOnly();
75                      throw e;
76                  }
77              }
78          });
79      }
80  
81      public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
82          this.applicationContext = applicationContext;
83      }
84  
85      protected DefaultTransactionDefinition getTransactionDefinition() {
86          final DefaultTransactionDefinition def = new DefaultTransactionDefinition();
87          def.setName("PluginReadWriteTx");
88          def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
89          def.setReadOnly(false);
90          return def;
91      }
92  
93  
94  }
95