001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.shiro.spring.security.interceptor; 020 021import org.aopalliance.intercept.MethodInterceptor; 022import org.aopalliance.intercept.MethodInvocation; 023import org.apache.shiro.aop.AnnotationResolver; 024import org.apache.shiro.authz.aop.AnnotationsAuthorizingMethodInterceptor; 025import org.apache.shiro.authz.aop.AuthorizingAnnotationMethodInterceptor; 026import org.apache.shiro.authz.aop.RoleAnnotationMethodInterceptor; 027import org.apache.shiro.authz.aop.PermissionAnnotationMethodInterceptor; 028import org.apache.shiro.authz.aop.AuthenticatedAnnotationMethodInterceptor; 029import org.apache.shiro.authz.aop.GuestAnnotationMethodInterceptor; 030import org.apache.shiro.authz.aop.UserAnnotationMethodInterceptor; 031import org.apache.shiro.spring.aop.SpringAnnotationResolver; 032 033import java.lang.reflect.Method; 034import java.util.ArrayList; 035import java.util.List; 036 037/** 038 * Allows Shiro Annotations to work in any <a href="http://aopalliance.sourceforge.net/">AOP Alliance</a> 039 * specific implementation environment (for example, Spring). 040 * 041 * @since 0.2 042 */ 043public class AopAllianceAnnotationsAuthorizingMethodInterceptor 044 extends AnnotationsAuthorizingMethodInterceptor implements MethodInterceptor { 045 046 public AopAllianceAnnotationsAuthorizingMethodInterceptor() { 047 List<AuthorizingAnnotationMethodInterceptor> interceptors = 048 new ArrayList<AuthorizingAnnotationMethodInterceptor>(5); 049 050 //use a Spring-specific Annotation resolver - Spring's AnnotationUtils is nicer than the 051 //raw JDK resolution process. 052 AnnotationResolver resolver = new SpringAnnotationResolver(); 053 //we can re-use the same resolver instance - it does not retain state: 054 interceptors.add(new RoleAnnotationMethodInterceptor(resolver)); 055 interceptors.add(new PermissionAnnotationMethodInterceptor(resolver)); 056 interceptors.add(new AuthenticatedAnnotationMethodInterceptor(resolver)); 057 interceptors.add(new UserAnnotationMethodInterceptor(resolver)); 058 interceptors.add(new GuestAnnotationMethodInterceptor(resolver)); 059 060 setMethodInterceptors(interceptors); 061 } 062 063 /** 064 * Creates a {@link MethodInvocation MethodInvocation} that wraps an 065 * {@link org.aopalliance.intercept.MethodInvocation org.aopalliance.intercept.MethodInvocation} instance, 066 * enabling Shiro Annotations in <a href="http://aopalliance.sourceforge.net/">AOP Alliance</a> environments 067 * (Spring, etc.). 068 * 069 * @param implSpecificMethodInvocation AOP Alliance {@link org.aopalliance.intercept.MethodInvocation MethodInvocation} 070 * @return a Shiro {@link MethodInvocation MethodInvocation} instance that wraps the AOP Alliance instance. 071 */ 072 protected org.apache.shiro.aop.MethodInvocation createMethodInvocation(Object implSpecificMethodInvocation) { 073 final MethodInvocation mi = (MethodInvocation) implSpecificMethodInvocation; 074 075 return new org.apache.shiro.aop.MethodInvocation() { 076 public Method getMethod() { 077 return mi.getMethod(); 078 } 079 080 public Object[] getArguments() { 081 return mi.getArguments(); 082 } 083 084 public String toString() { 085 return "Method invocation [" + mi.getMethod() + "]"; 086 } 087 088 public Object proceed() throws Throwable { 089 return mi.proceed(); 090 } 091 092 public Object getThis() { 093 return mi.getThis(); 094 } 095 }; 096 } 097 098 /** 099 * Simply casts the method argument to an 100 * {@link org.aopalliance.intercept.MethodInvocation org.aopalliance.intercept.MethodInvocation} and then 101 * calls <code>methodInvocation.{@link org.aopalliance.intercept.MethodInvocation#proceed proceed}()</code> 102 * 103 * @param aopAllianceMethodInvocation the {@link MethodInvocation org.aopalliance.intercept.MethodInvocation} 104 * @return the {@link org.aopalliance.intercept.MethodInvocation#proceed() 105 * org.aopalliance.intercept.MethodInvocation.proceed()} method call result. 106 * @throws Throwable if the underlying AOP Alliance <code>proceed()</code> call throws a <code>Throwable</code>. 107 */ 108 protected Object continueInvocation(Object aopAllianceMethodInvocation) throws Throwable { 109 MethodInvocation mi = (MethodInvocation) aopAllianceMethodInvocation; 110 return mi.proceed(); 111 } 112 113 /** 114 * Creates a Shiro {@link MethodInvocation MethodInvocation} instance and then immediately calls 115 * {@link org.apache.shiro.authz.aop.AuthorizingMethodInterceptor#invoke super.invoke}. 116 * 117 * @param methodInvocation the AOP Alliance-specific <code>methodInvocation</code> instance. 118 * @return the return value from invoking the method invocation. 119 * @throws Throwable if the underlying AOP Alliance method invocation throws a <code>Throwable</code>. 120 */ 121 public Object invoke(MethodInvocation methodInvocation) throws Throwable { 122 org.apache.shiro.aop.MethodInvocation mi = createMethodInvocation(methodInvocation); 123 return super.invoke(mi); 124 } 125}