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.support.DefaultTransactionDefinition;
15  import org.springframework.transaction.support.TransactionCallback;
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<>();
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((TransactionCallback) transactionStatus -> {
69              try {
70                  return callback.doInTransaction();
71              } catch (final RuntimeException e) {
72                  //rollback if something weird happened.
73                  transactionStatus.setRollbackOnly();
74                  throw e;
75              }
76          });
77      }
78  
79      public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
80          this.applicationContext = applicationContext;
81      }
82  
83      protected DefaultTransactionDefinition getTransactionDefinition() {
84          final DefaultTransactionDefinition def = new DefaultTransactionDefinition();
85          def.setName("PluginReadWriteTx");
86          def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
87          def.setReadOnly(false);
88          return def;
89      }
90  
91  
92  }
93