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     */
019    package org.apache.shiro.spring.security.interceptor;
020    
021    import org.aopalliance.intercept.MethodInterceptor;
022    import org.aopalliance.intercept.MethodInvocation;
023    import org.apache.shiro.authz.aop.AnnotationsAuthorizingMethodInterceptor;
024    
025    import java.lang.reflect.Method;
026    
027    /**
028     * Allows Shiro Annotations to work in any <a href="http://aopalliance.sourceforge.net/">AOP Alliance</a>
029     * specific implementation environment (for example, Spring).
030     *
031     * @author Les Hazlewood
032     * @since 0.2
033     */
034    public class AopAllianceAnnotationsAuthorizingMethodInterceptor
035            extends AnnotationsAuthorizingMethodInterceptor implements MethodInterceptor {
036    
037        /**
038         * Creates a {@link MethodInvocation MethodInvocation} that wraps an
039         * {@link org.aopalliance.intercept.MethodInvocation org.aopalliance.intercept.MethodInvocation} instance,
040         * enabling Shiro Annotations in <a href="http://aopalliance.sourceforge.net/">AOP Alliance</a> environments
041         * (Spring, etc).
042         *
043         * @param implSpecificMethodInvocation AOP Alliance {@link org.aopalliance.intercept.MethodInvocation MethodInvocation}
044         * @return a Shiro {@link MethodInvocation MethodInvocation} instance that wraps the AOP Alliance instance.
045         */
046        protected org.apache.shiro.aop.MethodInvocation createMethodInvocation(Object implSpecificMethodInvocation) {
047            final MethodInvocation mi = (MethodInvocation) implSpecificMethodInvocation;
048    
049            return new org.apache.shiro.aop.MethodInvocation() {
050                public Method getMethod() {
051                    return mi.getMethod();
052                }
053    
054                public Object[] getArguments() {
055                    return mi.getArguments();
056                }
057    
058                public String toString() {
059                    return "Method invocation [" + mi.getMethod() + "]";
060                }
061    
062                public Object proceed() throws Throwable {
063                    return mi.proceed();
064                }
065    
066                public Object getThis() {
067                    return mi.getThis();
068                }
069            };
070        }
071    
072        /**
073         * Simply casts the method argument to an
074         * {@link org.aopalliance.intercept.MethodInvocation org.aopalliance.intercept.MethodInvocation} and then
075         * calls <code>methodInvocation.{@link org.aopalliance.intercept.MethodInvocation#proceed proceed}()</code>
076         *
077         * @param aopAllianceMethodInvocation the {@link org.aopalliance.intercept.MethodInvocation org.aopalliance.intercept.MethodInvocation}
078         * @return the {@link org.aopalliance.intercept.MethodInvocation#proceed() org.aopalliance.intercept.MethodInvocation.proceed()} method call result.
079         * @throws Throwable if the underlying AOP Alliance <code>proceed()</code> call throws a <code>Throwable</code>.
080         */
081        protected Object continueInvocation(Object aopAllianceMethodInvocation) throws Throwable {
082            MethodInvocation mi = (MethodInvocation) aopAllianceMethodInvocation;
083            return mi.proceed();
084        }
085    
086        /**
087         * Creates a Shiro {@link MethodInvocation MethodInvocation} instance and then immediately calls
088         * {@link org.apache.shiro.authz.aop.AuthorizingMethodInterceptor#invoke super.invoke}.
089         *
090         * @param methodInvocation the AOP Alliance-specific <code>methodInvocation</code> instance.
091         * @return the return value from invoking the method invocation.
092         * @throws Throwable if the underlying AOP Alliance method invocation throws a <code>Throwable</code>.
093         */
094        public Object invoke(MethodInvocation methodInvocation) throws Throwable {
095            org.apache.shiro.aop.MethodInvocation mi = createMethodInvocation(methodInvocation);
096            return super.invoke(mi);
097        }
098    }