View Javadoc
1   package com.atlassian.plugin.spring.scanner.runtime.impl.util;
2   
3   import com.atlassian.plugin.spring.scanner.ProductFilter;
4   import com.google.common.annotations.VisibleForTesting;
5   import com.google.common.collect.ImmutableMap;
6   import org.osgi.framework.BundleContext;
7   import org.slf4j.Logger;
8   import org.slf4j.LoggerFactory;
9   
10  import javax.annotation.Nullable;
11  import java.util.Map;
12  import java.util.concurrent.atomic.AtomicReference;
13  
14  /**
15   * Utility to figure out what the currently running product is and give us it's name/filter in various ways
16   */
17  public class ProductFilterUtil {
18      private static ProductFilterUtil INSTANCE;
19  
20      @VisibleForTesting
21      static final String CLASS_ON_BAMBOO_CLASSPATH = "com.atlassian.bamboo.build.BuildExecutionManager";
22      @VisibleForTesting
23      static final String CLASS_ON_BITBUCKET_CLASSPATH = "com.atlassian.bitbucket.repository.RepositoryService";
24      @VisibleForTesting
25      static final String CLASS_ON_CONFLUENCE_CLASSPATH = "com.atlassian.confluence.core.ContentEntityManager";
26      @VisibleForTesting
27      static final String CLASS_ON_FECRU_CLASSPATH = "com.atlassian.fisheye.spi.services.RepositoryService";
28      @VisibleForTesting
29      static final String CLASS_ON_JIRA_CLASSPATH = "com.atlassian.jira.bc.issue.IssueService";
30      @VisibleForTesting
31      static final String CLASS_ON_REFAPP_CLASSPATH = "com.atlassian.refapp.api.ConnectionProvider";
32      @VisibleForTesting
33      static final String CLASS_ON_STASH_CLASSPATH = "com.atlassian.stash.repository.RepositoryService";
34  
35      private static final Logger log = LoggerFactory.getLogger(ProductFilterUtil.class);
36  
37      private AtomicReference<ProductFilter> filterForProduct = new AtomicReference<ProductFilter>();
38  
39      private ProductFilterUtil() {
40      }
41  
42      /**
43       * @param bundleContext - the bundle context
44       * @return the ProductFilter instance that represents the currently running product.
45       */
46      public static ProductFilter getFilterForCurrentProduct(@Nullable BundleContext bundleContext) {
47          return getInstance().getFilterForProduct(bundleContext);
48      }
49  
50      public ProductFilter getFilterForProduct(@Nullable final BundleContext bundleContext) {
51          // lazy building of known product.
52          ProductFilter productFilter = filterForProduct.get();
53          if (productFilter == null) {
54              filterForProduct.compareAndSet(productFilter, detectProduct(bundleContext));
55              productFilter = filterForProduct.get();
56          }
57          return productFilter;
58      }
59  
60      /**
61       * We try to detect a OSGi service that is uniquely offered by the host.
62       * <p/>
63       * You should extend out this method as we add support for other products
64       */
65      private final static Map<String, ProductFilter> PRODUCTS_TO_HOSTCLASSES = ImmutableMap.<String, ProductFilter>builder()
66              .put(CLASS_ON_BAMBOO_CLASSPATH, ProductFilter.BAMBOO)
67              .put(CLASS_ON_BITBUCKET_CLASSPATH, ProductFilter.BITBUCKET)
68              .put(CLASS_ON_CONFLUENCE_CLASSPATH, ProductFilter.CONFLUENCE)
69              .put(CLASS_ON_FECRU_CLASSPATH, ProductFilter.FECRU)
70              .put(CLASS_ON_JIRA_CLASSPATH, ProductFilter.JIRA)
71              .put(CLASS_ON_REFAPP_CLASSPATH, ProductFilter.REFAPP)
72              .put(CLASS_ON_STASH_CLASSPATH, ProductFilter.STASH)
73  
74              .build();
75  
76      private ProductFilter detectProduct(final BundleContext bundleContext) {
77          if (bundleContext == null) {
78              log.warn("Couldn't detect product due to null bundleContext: will use ProductFilter.ALL");
79              return ProductFilter.ALL;
80          }
81  
82          for (Map.Entry<String, ProductFilter> entry : PRODUCTS_TO_HOSTCLASSES.entrySet()) {
83              if (detectService(bundleContext, entry.getKey())) {
84                  log.debug("Detected product: " + entry.getValue().name());
85                  return entry.getValue();
86              }
87          }
88  
89          log.warn("Couldn't detect product, no known services found: will use ProductFilter.ALL");
90          return ProductFilter.ALL;
91      }
92  
93      private boolean detectService(final BundleContext bundleContext, final String serviceClassName) {
94          // We don't actually need to get the service, we just check we can get a reference
95          return null != bundleContext.getServiceReference(serviceClassName);
96      }
97  
98      private static ProductFilterUtil getInstance() {
99          if (null == INSTANCE) {
100             INSTANCE = new ProductFilterUtil();
101         }
102 
103         return INSTANCE;
104     }
105 
106 }