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.aop; 020 021import java.lang.annotation.Annotation; 022 023/** 024 * MethodInterceptor that inspects a specific annotation on the method invocation before continuing 025 * its execution. 026 * </p> 027 * The annotation is acquired from the {@link MethodInvocation MethodInvocation} via a 028 * {@link AnnotationResolver AnnotationResolver} instance that may be configured. Unless 029 * overridden, the default {@code AnnotationResolver} is a 030 * 031 * @since 0.9 032 */ 033public abstract class AnnotationMethodInterceptor extends MethodInterceptorSupport { 034 035 private AnnotationHandler handler; 036 037 /** 038 * The resolver to use to find annotations on intercepted methods. 039 * 040 * @since 1.1 041 */ 042 private AnnotationResolver resolver; 043 044 /** 045 * Constructs an <code>AnnotationMethodInterceptor</code> with the 046 * {@link AnnotationHandler AnnotationHandler} that will be used to process annotations of a 047 * corresponding type. 048 * 049 * @param handler the handler to delegate to for processing the annotation. 050 */ 051 public AnnotationMethodInterceptor(AnnotationHandler handler) { 052 this(handler, new DefaultAnnotationResolver()); 053 } 054 055 /** 056 * Constructs an <code>AnnotationMethodInterceptor</code> with the 057 * {@link AnnotationHandler AnnotationHandler} that will be used to process annotations of a 058 * corresponding type, using the specified {@code AnnotationResolver} to acquire annotations 059 * at runtime. 060 * 061 * @param handler the handler to use to process any discovered annotation 062 * @param resolver the resolver to use to locate/acquire the annotation 063 * @since 1.1 064 */ 065 public AnnotationMethodInterceptor(AnnotationHandler handler, AnnotationResolver resolver) { 066 if (handler == null) { 067 throw new IllegalArgumentException("AnnotationHandler argument cannot be null."); 068 } 069 setHandler(handler); 070 setResolver(resolver != null ? resolver : new DefaultAnnotationResolver()); 071 } 072 073 /** 074 * Returns the {@code AnnotationHandler} used to perform authorization behavior based on 075 * an annotation discovered at runtime. 076 * 077 * @return the {@code AnnotationHandler} used to perform authorization behavior based on 078 * an annotation discovered at runtime. 079 */ 080 public AnnotationHandler getHandler() { 081 return handler; 082 } 083 084 /** 085 * Sets the {@code AnnotationHandler} used to perform authorization behavior based on 086 * an annotation discovered at runtime. 087 * 088 * @param handler the {@code AnnotationHandler} used to perform authorization behavior based on 089 * an annotation discovered at runtime. 090 */ 091 public void setHandler(AnnotationHandler handler) { 092 this.handler = handler; 093 } 094 095 /** 096 * Returns the {@code AnnotationResolver} to use to acquire annotations from intercepted 097 * methods at runtime. The annotation is then used by the {@link #getHandler handler} to 098 * perform authorization logic. 099 * 100 * @return the {@code AnnotationResolver} to use to acquire annotations from intercepted 101 * methods at runtime. 102 * @since 1.1 103 */ 104 public AnnotationResolver getResolver() { 105 return resolver; 106 } 107 108 /** 109 * Returns the {@code AnnotationResolver} to use to acquire annotations from intercepted 110 * methods at runtime. The annotation is then used by the {@link #getHandler handler} to 111 * perform authorization logic. 112 * 113 * @param resolver the {@code AnnotationResolver} to use to acquire annotations from intercepted 114 * methods at runtime. 115 * @since 1.1 116 */ 117 public void setResolver(AnnotationResolver resolver) { 118 this.resolver = resolver; 119 } 120 121 /** 122 * Returns <code>true</code> if this interceptor supports, that is, should inspect, the specified 123 * <code>MethodInvocation</code>, <code>false</code> otherwise. 124 * <p/> 125 * The default implementation simply does the following: 126 * <p/> 127 * <code>return {@link #getAnnotation(MethodInvocation) getAnnotation(mi)} != null</code> 128 * 129 * @param mi the <code>MethodInvocation</code> for the method being invoked. 130 * @return <code>true</code> if this interceptor supports, that is, should inspect, the specified 131 * <code>MethodInvocation</code>, <code>false</code> otherwise. 132 */ 133 public boolean supports(MethodInvocation mi) { 134 return getAnnotation(mi) != null; 135 } 136 137 /** 138 * Returns the Annotation that this interceptor will process for the specified method invocation. 139 * <p/> 140 * The default implementation acquires the annotation using an annotation 141 * {@link #getResolver resolver} using the internal annotation {@link #getHandler handler}'s 142 * {@link org.apache.shiro.aop.AnnotationHandler#getAnnotationClass() annotationClass}. 143 * 144 * @param mi the MethodInvocation wrapping the Method from which the Annotation will be acquired. 145 * @return the Annotation that this interceptor will process for the specified method invocation. 146 */ 147 protected Annotation getAnnotation(MethodInvocation mi) { 148 return getResolver().getAnnotation(mi, getHandler().getAnnotationClass()); 149 } 150}