View Javadoc

1   package com.atlassian.plugins.rest.module.scope;
2   
3   import com.atlassian.plugin.PluginAccessor;
4   import com.atlassian.plugin.event.PluginEventManager;
5   import com.atlassian.plugin.scope.ScopeManager;
6   import com.atlassian.plugin.tracker.DefaultPluginModuleTracker;
7   import com.atlassian.plugin.tracker.PluginModuleTracker;
8   import com.atlassian.plugins.rest.module.RestModuleDescriptor;
9   import com.sun.jersey.api.model.AbstractMethod;
10  import com.sun.jersey.spi.container.ResourceFilter;
11  import com.sun.jersey.spi.container.ResourceFilterFactory;
12  import org.slf4j.Logger;
13  import org.slf4j.LoggerFactory;
14  
15  import javax.ws.rs.ext.Provider;
16  import java.util.List;
17  import java.util.Optional;
18  import java.util.function.Predicate;
19  import java.util.stream.Stream;
20  import java.util.stream.StreamSupport;
21  
22  import static java.util.Collections.emptyList;
23  import static java.util.Collections.singletonList;
24  
25  /**
26   * Returns scope filter based on request's rest resource
27   *
28   * @since 3.2
29   */
30  @Provider
31  public class ScopeResourceFilterFactory implements ResourceFilterFactory {
32      private static final Logger log = LoggerFactory.getLogger(ScopeResourceFilterFactory.class);
33  
34      private final PluginModuleTracker<Object, RestModuleDescriptor> pluginModuleTracker;
35      private final ScopeManager scopeManager;
36  
37      public ScopeResourceFilterFactory(
38              PluginAccessor pluginAccessor,
39              PluginEventManager pluginEventManager,
40              ScopeManager scopeManager) {
41          this.pluginModuleTracker = new DefaultPluginModuleTracker<>(pluginAccessor, pluginEventManager, RestModuleDescriptor.class);
42          this.scopeManager = scopeManager;
43      }
44  
45      /**
46       * Returns scope resource filter if given method belongs to plugin where scope is enabled
47       */
48      public List<ResourceFilter> create(final AbstractMethod method) {
49          final Class clazz = method.getResource().getResourceClass();
50          final Iterable<RestModuleDescriptor> moduleDescriptors = pluginModuleTracker.getModuleDescriptors();
51          final Stream<RestModuleDescriptor> stream = StreamSupport.stream(moduleDescriptors.spliterator(), false);
52  
53          //for non initalized plugins rest api context won't be present
54          final Predicate<RestModuleDescriptor> restApiContextIsPresent = m -> m.getRestApiContext() !=null;
55  
56          //if config for current MD is not present it might be that it wasn't initialized yet
57          final Predicate<RestModuleDescriptor> configMatches = m -> m.getRestApiContext().getConfig().map(
58                  c -> c.getClasses().contains(clazz)).orElse(false);
59  
60          //composite predicate for initialized MDs and match resource class
61          final Predicate<RestModuleDescriptor> moduleDescriptorPredicate = restApiContextIsPresent.and(configMatches);
62  
63          //O(N) on all rest MDs registered. Given N is a constant no caching introduced, yet
64          final Optional<RestModuleDescriptor> descriptor = stream.filter(moduleDescriptorPredicate).findFirst();
65  
66          return descriptor.isPresent()
67                  ? singletonList(new ScopeResourceFilter(scopeManager, descriptor.get()))
68                  : emptyList();
69      }
70  }