View Javadoc
1   package org.springframework.osgi.atlassian;
2   
3   import org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext;
4   import org.springframework.beans.BeansException;
5   import org.springframework.beans.factory.config.BeanPostProcessor;
6   import org.springframework.beans.factory.support.DefaultListableBeanFactory;
7   import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
8   import org.springframework.core.ParameterNameDiscoverer;
9   import org.springframework.osgi.context.BundleContextAware;
10  
11  import javax.annotation.Nonnull;
12  import java.lang.reflect.Constructor;
13  import java.lang.reflect.Method;
14  
15  /**
16   * Application context that initializes the bean definition reader to not validate via XML Schema. Note that by
17   * turning this off, certain defaults won't be populated like expected. For example, XML Schema provides the default
18   * autowire value of "default", but without this validation, that value is not set so autowiring will be turned off.
19   *
20   * This class exists in the same package as the parent so the log messages won't get confused as the parent class
21   * logs against the instance class.
22   *
23   * @since 2.5.0
24   */
25  public class NonValidatingOsgiBundleXmlApplicationContext extends OsgiBundleXmlApplicationContext {
26      public NonValidatingOsgiBundleXmlApplicationContext(final String[] configLocations) {
27          super(configLocations);
28      }
29  
30      @Override
31      protected void initBeanDefinitionReader(final XmlBeanDefinitionReader beanDefinitionReader) {
32          super.initBeanDefinitionReader(beanDefinitionReader);
33          beanDefinitionReader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
34          beanDefinitionReader.setNamespaceAware(true);
35      }
36  
37      @Override
38      protected void customizeBeanFactory(@Nonnull final DefaultListableBeanFactory beanFactory) {
39          if (Boolean.getBoolean("atlassian.disable.spring.cache.bean.metadata")) {
40              beanFactory.setCacheBeanMetadata(false);
41          }
42          if (!Boolean.getBoolean("atlassian.enable.spring.parameter.name.discoverer")) {
43              beanFactory.setParameterNameDiscoverer(new ParameterNameDiscoverer() {
44                  @Override
45                  public String[] getParameterNames(@Nonnull final Method method) {
46                      // We never discover parameter names (for now)
47                      return null;
48                  }
49  
50                  @Override
51                  public String[] getParameterNames(@Nonnull final Constructor<?> ctor) {
52                      // We never discover parameter names (for now)
53                      return null;
54                  }
55              });
56          }
57          super.customizeBeanFactory(beanFactory);
58          beanFactory.addBeanPostProcessor(new ShimSpringDmBundleContextAwareBeanPostProcessor());
59          beanFactory.setAutowireCandidateResolver(new ExcludableContextAnnotationAutowireCandidateResolver());
60      }
61  
62      private class ShimSpringDmBundleContextAwareBeanPostProcessor implements BeanPostProcessor {
63          @Override
64          public Object postProcessBeforeInitialization(@Nonnull final Object bean, final String beanName) throws BeansException {
65              // Inject the BundleContext into beans which mark themselves as needing it.
66              if (bean instanceof BundleContextAware) {
67                  ((BundleContextAware) bean).setBundleContext(getBundleContext());
68              }
69              return bean;
70          }
71  
72          @Override
73          public Object postProcessAfterInitialization(@Nonnull final Object bean, final String beanName) throws BeansException {
74              // Nothing to do after initialization
75              return bean;
76          }
77      }
78  }