View Javadoc

1   package com.atlassian.plugins.rest.module;
2   
3   import com.atlassian.plugins.rest.common.error.jersey.NotFoundExceptionMapper;
4   import com.atlassian.plugins.rest.common.error.jersey.ThrowableExceptionMapper;
5   import com.atlassian.plugins.rest.common.json.JacksonJsonProviderFactory;
6   import com.atlassian.plugins.rest.common.security.jersey.SecurityExceptionMapper;
7   import com.atlassian.plugins.rest.common.security.jersey.SysadminOnlyResourceFilter;
8   import com.atlassian.plugins.rest.module.scanner.AnnotatedClassScanner;
9   import com.google.common.base.Preconditions;
10  import com.google.common.collect.Lists;
11  import com.google.common.collect.Sets;
12  import com.sun.jersey.api.core.DefaultResourceConfig;
13  import com.sun.jersey.api.core.ResourceConfig;
14  import com.sun.jersey.spi.container.ContainerRequestFilter;
15  import com.sun.jersey.spi.container.ContainerResponseFilter;
16  import com.sun.jersey.spi.container.ResourceFilterFactory;
17  import org.osgi.framework.Bundle;
18  
19  import javax.ws.rs.Path;
20  import javax.ws.rs.ext.Provider;
21  import java.util.Collection;
22  import java.util.Collections;
23  import java.util.HashSet;
24  import java.util.Set;
25  
26  /**
27   * An implementation of {@link ResourceConfig} that scans a given Osgi Bundle for Jersey resources ({#link Provider} and {@link Path}.
28   */
29  class OsgiResourceConfig extends DefaultResourceConfig
30  {
31      private final Bundle bundle;
32  
33      private final Set<Class<?>> classes = new HashSet<Class<?>>()
34      {{
35              add(NotFoundExceptionMapper.class);
36              add(SecurityExceptionMapper.class);
37              add(ThrowableExceptionMapper.class);
38              add(SysadminOnlyResourceFilter.class);
39          }};
40  
41      private final Set<Object> instances;
42  
43      private Set<Class<?>> scannedClasses;
44      private final String[] packages;
45  
46      OsgiResourceConfig(Bundle bundle,
47                         Set<String> packages,
48                         Collection<? extends ContainerRequestFilter> containerRequestFilters,
49                         Collection<? extends ContainerResponseFilter> containerResponseFilters,
50                         Collection<? extends ResourceFilterFactory> resourceFilterFactories,
51                         Collection<?> providers)
52      {
53          this.packages = packages.toArray(new String[packages.size()]);
54          this.bundle = Preconditions.checkNotNull(bundle);
55  
56          // adds "filters" to Jersey
57          getProperties().put(PROPERTY_CONTAINER_REQUEST_FILTERS, Lists.newLinkedList(containerRequestFilters));
58          getProperties().put(PROPERTY_CONTAINER_RESPONSE_FILTERS, Lists.newLinkedList(containerResponseFilters));
59          getProperties().put(PROPERTY_RESOURCE_FILTER_FACTORIES, Lists.newLinkedList(resourceFilterFactories));
60  
61          this.instances = Sets.newHashSet(Preconditions.checkNotNull(providers));
62          this.instances.add(new JacksonJsonProviderFactory().create());
63  
64          addInstancesClassesToClasses();
65      }
66  
67      private void addInstancesClassesToClasses()
68      {
69          for (Object o : instances)
70          {
71              classes.add(o.getClass());
72          }
73      }
74  
75      @Override
76      public synchronized Set<Class<?>> getClasses()
77      {
78          if (scannedClasses == null)
79          {
80              scannedClasses = scanForAnnotatedClasses();
81              classes.addAll(scannedClasses);
82          }
83  
84          return classes;
85      }
86  
87      private Set<Class<?>> scanForAnnotatedClasses()
88      {
89          return new AnnotatedClassScanner(bundle, Provider.class, Path.class).scan(packages);
90      }
91  
92      public Set<?> getInstances()
93      {
94          return Collections.unmodifiableSet(instances);
95      }
96  }