1   package com.atlassian.plugins.rest.common.sal.websudo;
2   
3   import static com.google.common.base.Preconditions.checkNotNull;
4   
5   import com.atlassian.sal.api.websudo.WebSudoNotRequired;
6   import com.atlassian.sal.api.websudo.WebSudoRequired;
7   import com.sun.jersey.api.model.AbstractMethod;
8   import com.sun.jersey.api.model.AbstractResource;
9   import com.sun.jersey.spi.container.ContainerRequest;
10  import com.sun.jersey.spi.container.ContainerRequestFilter;
11  import com.sun.jersey.spi.container.ContainerResponseFilter;
12  import com.sun.jersey.spi.container.ResourceFilter;
13  
14  import java.lang.reflect.Method;
15  
16  /**
17   * This is a Jersey resource filter that checks whether the resource requires or opts out of WebSudo protection.
18   * The check is based on annotations ({@link com.atlassian.sal.api.websudo.WebSudoRequired} and
19   * {@link com.atlassian.sal.api.websudo.WebSudoNotRequired}) that can be applied on the method, class and package level.
20   * <p/>
21   * Annotations on more specific elements override annotations applied to more general elements (in ascending order from specific to general):
22   * <ul>
23   * <li>Method level</li>
24   * <li>Class level</li>
25   * <li>Package level</li>
26   * </li>
27   */
28  final class WebSudoResourceFilter implements ResourceFilter, ContainerRequestFilter
29  {
30      private final AbstractMethod abstractMethod;
31      private final WebSudoResourceContext webSudoResourceContext;
32  
33      public WebSudoResourceFilter(final AbstractMethod abstractMethod, final WebSudoResourceContext webSudoResourceContext)
34      {
35          this.abstractMethod = checkNotNull(abstractMethod);
36          this.webSudoResourceContext = checkNotNull(webSudoResourceContext);
37      }
38  
39      public ContainerRequestFilter getRequestFilter()
40      {
41          return this;
42      }
43  
44      public ContainerResponseFilter getResponseFilter()
45      {
46          return null;
47      }
48  
49      public ContainerRequest filter(final ContainerRequest request)
50      {
51          if (requiresWebSudo() && webSudoResourceContext.shouldEnforceWebSudoProtection())
52          {
53              throw new WebSudoRequiredException("This resource requires WebSudo.");
54          }
55          return request;
56      }
57  
58      private boolean requiresWebSudo()
59      {
60          final Method m = abstractMethod.getMethod();
61          if (null != m && m.getAnnotation(WebSudoRequired.class) != null)
62          {
63              return true;
64          }
65          if (null != m && m.getAnnotation(WebSudoNotRequired.class) != null)
66          {
67              return false;
68          }
69  
70          final AbstractResource resource = abstractMethod.getResource();
71          if (resource.isAnnotationPresent(WebSudoRequired.class))
72          {
73              return true;
74          }
75          if (resource.isAnnotationPresent(WebSudoNotRequired.class))
76          {
77              return false;
78          }
79  
80          final Package p = abstractMethod.getResource().getResourceClass().getPackage();
81          if (p.getAnnotation(WebSudoRequired.class) != null)
82          {
83              return true;
84          }
85          if (p.getAnnotation(WebSudoNotRequired.class) != null)
86          {
87              return false;
88          }
89          return false;
90      }
91  }