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.aop;
20
21 import java.lang.annotation.Annotation;
22
23 /**
24 * MethodInterceptor that inspects a specific annotation on the method invocation before continuing
25 * its execution.
26 * </p>
27 * The annotation is acquired from the {@link MethodInvocation MethodInvocation} via a
28 * {@link AnnotationResolver AnnotationResolver} instance that may be configured. Unless
29 * overridden, the default {@code AnnotationResolver} is a
30 *
31 * @since 0.9
32 */
33 public abstract class AnnotationMethodInterceptor extends MethodInterceptorSupport {
34
35 private AnnotationHandler handler;
36
37 /**
38 * The resolver to use to find annotations on intercepted methods.
39 *
40 * @since 1.1
41 */
42 private AnnotationResolver resolver;
43
44 /**
45 * Constructs an <code>AnnotationMethodInterceptor</code> with the
46 * {@link AnnotationHandler AnnotationHandler} that will be used to process annotations of a
47 * corresponding type.
48 *
49 * @param handler the handler to delegate to for processing the annotation.
50 */
51 public AnnotationMethodInterceptor(AnnotationHandler handler) {
52 this(handler, new DefaultAnnotationResolver());
53 }
54
55 /**
56 * Constructs an <code>AnnotationMethodInterceptor</code> with the
57 * {@link AnnotationHandler AnnotationHandler} that will be used to process annotations of a
58 * corresponding type, using the specified {@code AnnotationResolver} to acquire annotations
59 * at runtime.
60 *
61 * @param handler the handler to use to process any discovered annotation
62 * @param resolver the resolver to use to locate/acquire the annotation
63 * @since 1.1
64 */
65 public AnnotationMethodInterceptor(AnnotationHandler handler, AnnotationResolver resolver) {
66 if (handler == null) {
67 throw new IllegalArgumentException("AnnotationHandler argument cannot be null.");
68 }
69 setHandler(handler);
70 setResolver(resolver != null ? resolver : new DefaultAnnotationResolver());
71 }
72
73 /**
74 * Returns the {@code AnnotationHandler} used to perform authorization behavior based on
75 * an annotation discovered at runtime.
76 *
77 * @return the {@code AnnotationHandler} used to perform authorization behavior based on
78 * an annotation discovered at runtime.
79 */
80 public AnnotationHandler getHandler() {
81 return handler;
82 }
83
84 /**
85 * Sets the {@code AnnotationHandler} used to perform authorization behavior based on
86 * an annotation discovered at runtime.
87 *
88 * @param handler the {@code AnnotationHandler} used to perform authorization behavior based on
89 * an annotation discovered at runtime.
90 */
91 public void setHandler(AnnotationHandler handler) {
92 this.handler = handler;
93 }
94
95 /**
96 * Returns the {@code AnnotationResolver} to use to acquire annotations from intercepted
97 * methods at runtime. The annotation is then used by the {@link #getHandler handler} to
98 * perform authorization logic.
99 *
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 }