View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.spring.security.interceptor;
20  
21  import org.aopalliance.intercept.MethodInterceptor;
22  import org.aopalliance.intercept.MethodInvocation;
23  import org.apache.shiro.aop.AnnotationResolver;
24  import org.apache.shiro.authz.aop.*;
25  import org.apache.shiro.spring.aop.SpringAnnotationResolver;
26  
27  import java.lang.reflect.Method;
28  import java.util.ArrayList;
29  import java.util.List;
30  
31  /**
32   * Allows Shiro Annotations to work in any <a href="http://aopalliance.sourceforge.net/">AOP Alliance</a>
33   * specific implementation environment (for example, Spring).
34   *
35   * @since 0.2
36   */
37  public class AopAllianceAnnotationsAuthorizingMethodInterceptor
38          extends AnnotationsAuthorizingMethodInterceptor implements MethodInterceptor {
39  
40      public AopAllianceAnnotationsAuthorizingMethodInterceptor() {
41          List<AuthorizingAnnotationMethodInterceptor> interceptors =
42                  new ArrayList<AuthorizingAnnotationMethodInterceptor>(5);
43  
44          //use a Spring-specific Annotation resolver - Spring's AnnotationUtils is nicer than the
45          //raw JDK resolution process.
46          AnnotationResolver resolver = new SpringAnnotationResolver();
47          //we can re-use the same resolver instance - it does not retain state:
48          interceptors.add(new RoleAnnotationMethodInterceptor(resolver));
49          interceptors.add(new PermissionAnnotationMethodInterceptor(resolver));
50          interceptors.add(new AuthenticatedAnnotationMethodInterceptor(resolver));
51          interceptors.add(new UserAnnotationMethodInterceptor(resolver));
52          interceptors.add(new GuestAnnotationMethodInterceptor(resolver));
53  
54          setMethodInterceptors(interceptors);
55      }
56      /**
57       * Creates a {@link MethodInvocation MethodInvocation} that wraps an
58       * {@link org.aopalliance.intercept.MethodInvocation org.aopalliance.intercept.MethodInvocation} instance,
59       * enabling Shiro Annotations in <a href="http://aopalliance.sourceforge.net/">AOP Alliance</a> environments
60       * (Spring, etc).
61       *
62       * @param implSpecificMethodInvocation AOP Alliance {@link org.aopalliance.intercept.MethodInvocation MethodInvocation}
63       * @return a Shiro {@link MethodInvocation MethodInvocation} instance that wraps the AOP Alliance instance.
64       */
65      protected org.apache.shiro.aop.MethodInvocation createMethodInvocation(Object implSpecificMethodInvocation) {
66          final MethodInvocation mi = (MethodInvocation) implSpecificMethodInvocation;
67  
68          return new org.apache.shiro.aop.MethodInvocation() {
69              public Method getMethod() {
70                  return mi.getMethod();
71              }
72  
73              public Object[] getArguments() {
74                  return mi.getArguments();
75              }
76  
77              public String toString() {
78                  return "Method invocation [" + mi.getMethod() + "]";
79              }
80  
81              public Object proceed() throws Throwable {
82                  return mi.proceed();
83              }
84  
85              public Object getThis() {
86                  return mi.getThis();
87              }
88          };
89      }
90  
91      /**
92       * Simply casts the method argument to an
93       * {@link org.aopalliance.intercept.MethodInvocation org.aopalliance.intercept.MethodInvocation} and then
94       * calls <code>methodInvocation.{@link org.aopalliance.intercept.MethodInvocation#proceed proceed}()</code>
95       *
96       * @param aopAllianceMethodInvocation the {@link org.aopalliance.intercept.MethodInvocation org.aopalliance.intercept.MethodInvocation}
97       * @return the {@link org.aopalliance.intercept.MethodInvocation#proceed() org.aopalliance.intercept.MethodInvocation.proceed()} method call result.
98       * @throws Throwable if the underlying AOP Alliance <code>proceed()</code> call throws a <code>Throwable</code>.
99       */
100     protected Object continueInvocation(Object aopAllianceMethodInvocation) throws Throwable {
101         MethodInvocation mi = (MethodInvocation) aopAllianceMethodInvocation;
102         return mi.proceed();
103     }
104 
105     /**
106      * Creates a Shiro {@link MethodInvocation MethodInvocation} instance and then immediately calls
107      * {@link org.apache.shiro.authz.aop.AuthorizingMethodInterceptor#invoke super.invoke}.
108      *
109      * @param methodInvocation the AOP Alliance-specific <code>methodInvocation</code> instance.
110      * @return the return value from invoking the method invocation.
111      * @throws Throwable if the underlying AOP Alliance method invocation throws a <code>Throwable</code>.
112      */
113     public Object invoke(MethodInvocation methodInvocation) throws Throwable {
114         org.apache.shiro.aop.MethodInvocation mi = createMethodInvocation(methodInvocation);
115         return super.invoke(mi);
116     }
117 }