View Javadoc
1   package com.atlassian.plugin.manager;
2   
3   import com.atlassian.plugin.ModuleDescriptor;
4   import com.atlassian.plugin.PluginController;
5   import com.google.common.base.Function;
6   import com.google.common.base.Predicates;
7   import org.slf4j.Logger;
8   import org.slf4j.LoggerFactory;
9   
10  import javax.annotation.Nullable;
11  
12  import static com.google.common.collect.Iterables.filter;
13  import static com.google.common.collect.Iterables.transform;
14  
15  /**
16   * Safely extracts the module instance from module descriptors,
17   * handling exceptions and disabling broken plugins as appropriate.
18   *
19   * @since 4.0
20   */
21  public class SafeModuleExtractor {
22      private static final Logger log = LoggerFactory.getLogger(SafeModuleExtractor.class);
23  
24      private final PluginController pluginController;
25  
26      public SafeModuleExtractor(PluginController pluginController) {
27          this.pluginController = pluginController;
28      }
29  
30      /**
31       * Safely extracts the module instance from the given module descriptors. This method will disable any plugin it
32       * can't successfully extract the module instance from.
33       */
34      public <M> Iterable<M> getModules(final Iterable<? extends ModuleDescriptor<M>> moduleDescriptors) {
35          return filter(
36                  transform(
37                          moduleDescriptors,
38                          new Function<ModuleDescriptor<M>, M>() {
39                              @Override
40                              public M apply(@Nullable ModuleDescriptor<M> descriptor) {
41                                  if (descriptor == null || descriptor.isBroken()) {
42                                      return null;
43                                  }
44  
45                                  try {
46                                      return descriptor.getModule();
47                                  } catch (final RuntimeException ex) {
48                                      final String pluginKey = descriptor.getPlugin().getKey();
49  
50                                      log.error("Exception when retrieving plugin module {}, disabling plugin {}",
51                                              descriptor.getCompleteKey(), pluginKey, ex);
52  
53                                      descriptor.setBroken();
54                                      // Don't persist: don't want to create a snowflake config in Cloud instance,
55                                      // and the module might work following restart if something has changed.
56                                      pluginController.disablePluginWithoutPersisting(pluginKey);
57                                      return null;
58                                  }
59                              }
60                          }),
61                  Predicates.notNull());
62      }
63  }