1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.catalina.util;
19
20 import java.lang.reflect.Field;
21 import java.lang.reflect.InvocationTargetException;
22 import java.lang.reflect.Method;
23 import java.lang.reflect.Modifier;
24
25 import javax.annotation.PostConstruct;
26 import javax.annotation.PreDestroy;
27 import javax.annotation.Resource;
28 import javax.ejb.EJB;
29 import javax.naming.NamingException;
30 import javax.persistence.PersistenceContext;
31 import javax.persistence.PersistenceUnit;
32 import javax.xml.ws.WebServiceRef;
33
34 import org.apache.AnnotationProcessor;
35
36
37 /**
38 * Verify the annotation and Process it.
39 *
40 * @author Fabien Carrion
41 * @author Remy Maucherat
42 * @version $Revision: 467222 $, $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
43 */
44 public class DefaultAnnotationProcessor implements AnnotationProcessor {
45
46 protected javax.naming.Context context = null;
47
48 public DefaultAnnotationProcessor(javax.naming.Context context) {
49 this.context = context;
50 }
51
52
53 /**
54 * Call postConstruct method on the specified instance.
55 */
56 public void postConstruct(Object instance)
57 throws IllegalAccessException, InvocationTargetException {
58
59 Method[] methods = instance.getClass().getDeclaredMethods();
60 Method postConstruct = null;
61 for (int i = 0; i < methods.length; i++) {
62 if (methods[i].isAnnotationPresent(PostConstruct.class)) {
63 if ((postConstruct != null)
64 || (methods[i].getParameterTypes().length != 0)
65 || (Modifier.isStatic(methods[i].getModifiers()))
66 || (methods[i].getExceptionTypes().length > 0)
67 || (!methods[i].getReturnType().getName().equals("void"))) {
68 throw new IllegalArgumentException("Invalid PostConstruct annotation");
69 }
70 postConstruct = methods[i];
71 }
72 }
73
74 // At the end the postconstruct annotated
75 // method is invoked
76 if (postConstruct != null) {
77 boolean accessibility = postConstruct.isAccessible();
78 postConstruct.setAccessible(true);
79 postConstruct.invoke(instance);
80 postConstruct.setAccessible(accessibility);
81 }
82
83 }
84
85
86 /**
87 * Call preDestroy method on the specified instance.
88 */
89 public void preDestroy(Object instance)
90 throws IllegalAccessException, InvocationTargetException {
91
92 Method[] methods = instance.getClass().getDeclaredMethods();
93 Method preDestroy = null;
94 for (int i = 0; i < methods.length; i++) {
95 if (methods[i].isAnnotationPresent(PreDestroy.class)) {
96 if ((preDestroy != null)
97 || (methods[i].getParameterTypes().length != 0)
98 || (Modifier.isStatic(methods[i].getModifiers()))
99 || (methods[i].getExceptionTypes().length > 0)
100 || (!methods[i].getReturnType().getName().equals("void"))) {
101 throw new IllegalArgumentException("Invalid PreDestroy annotation");
102 }
103 preDestroy = methods[i];
104 }
105 }
106
107 // At the end the postconstruct annotated
108 // method is invoked
109 if (preDestroy != null) {
110 boolean accessibility = preDestroy.isAccessible();
111 preDestroy.setAccessible(true);
112 preDestroy.invoke(instance);
113 preDestroy.setAccessible(accessibility);
114 }
115
116 }
117
118
119 /**
120 * Inject resources in specified instance.
121 */
122 public void processAnnotations(Object instance)
123 throws IllegalAccessException, InvocationTargetException, NamingException {
124
125 if (context == null) {
126 // No resource injection
127 return;
128 }
129
130 // Initialize fields annotations
131 Field[] fields = instance.getClass().getDeclaredFields();
132 for (int i = 0; i < fields.length; i++) {
133 if (fields[i].isAnnotationPresent(Resource.class)) {
134 Resource annotation = (Resource) fields[i].getAnnotation(Resource.class);
135 lookupFieldResource(context, instance, fields[i], annotation.name());
136 }
137 if (fields[i].isAnnotationPresent(EJB.class)) {
138 EJB annotation = (EJB) fields[i].getAnnotation(EJB.class);
139 lookupFieldResource(context, instance, fields[i], annotation.name());
140 }
141 if (fields[i].isAnnotationPresent(WebServiceRef.class)) {
142 WebServiceRef annotation =
143 (WebServiceRef) fields[i].getAnnotation(WebServiceRef.class);
144 lookupFieldResource(context, instance, fields[i], annotation.name());
145 }
146 if (fields[i].isAnnotationPresent(PersistenceContext.class)) {
147 PersistenceContext annotation =
148 (PersistenceContext) fields[i].getAnnotation(PersistenceContext.class);
149 lookupFieldResource(context, instance, fields[i], annotation.name());
150 }
151 if (fields[i].isAnnotationPresent(PersistenceUnit.class)) {
152 PersistenceUnit annotation =
153 (PersistenceUnit) fields[i].getAnnotation(PersistenceUnit.class);
154 lookupFieldResource(context, instance, fields[i], annotation.name());
155 }
156 }
157
158 // Initialize methods annotations
159 Method[] methods = instance.getClass().getDeclaredMethods();
160 for (int i = 0; i < methods.length; i++) {
161 if (methods[i].isAnnotationPresent(Resource.class)) {
162 Resource annotation = (Resource) methods[i].getAnnotation(Resource.class);
163 lookupMethodResource(context, instance, methods[i], annotation.name());
164 }
165 if (methods[i].isAnnotationPresent(EJB.class)) {
166 EJB annotation = (EJB) methods[i].getAnnotation(EJB.class);
167 lookupMethodResource(context, instance, methods[i], annotation.name());
168 }
169 if (methods[i].isAnnotationPresent(WebServiceRef.class)) {
170 WebServiceRef annotation =
171 (WebServiceRef) methods[i].getAnnotation(WebServiceRef.class);
172 lookupMethodResource(context, instance, methods[i], annotation.name());
173 }
174 if (methods[i].isAnnotationPresent(PersistenceContext.class)) {
175 PersistenceContext annotation =
176 (PersistenceContext) methods[i].getAnnotation(PersistenceContext.class);
177 lookupMethodResource(context, instance, methods[i], annotation.name());
178 }
179 if (methods[i].isAnnotationPresent(PersistenceUnit.class)) {
180 PersistenceUnit annotation =
181 (PersistenceUnit) methods[i].getAnnotation(PersistenceUnit.class);
182 lookupMethodResource(context, instance, methods[i], annotation.name());
183 }
184 }
185
186 }
187
188
189 /**
190 * Inject resources in specified field.
191 */
192 protected static void lookupFieldResource(javax.naming.Context context,
193 Object instance, Field field, String name)
194 throws NamingException, IllegalAccessException {
195
196 Object lookedupResource = null;
197 boolean accessibility = false;
198
199 if ((name != null) &&
200 (name.length() > 0)) {
201 lookedupResource = context.lookup(name);
202 } else {
203 lookedupResource = context.lookup(instance.getClass().getName() + "/" + field.getName());
204 }
205
206 accessibility = field.isAccessible();
207 field.setAccessible(true);
208 field.set(instance, lookedupResource);
209 field.setAccessible(accessibility);
210 }
211
212
213 /**
214 * Inject resources in specified method.
215 */
216 protected static void lookupMethodResource(javax.naming.Context context,
217 Object instance, Method method, String name)
218 throws NamingException, IllegalAccessException, InvocationTargetException {
219
220 if (!method.getName().startsWith("set")
221 || method.getParameterTypes().length != 1
222 || !method.getReturnType().getName().equals("void")) {
223 throw new IllegalArgumentException("Invalid method resource injection annotation");
224 }
225
226 Object lookedupResource = null;
227 boolean accessibility = false;
228
229 if ((name != null) &&
230 (name.length() > 0)) {
231 lookedupResource = context.lookup(name);
232 } else {
233 lookedupResource =
234 context.lookup(instance.getClass().getName() + "/" + method.getName().substring(3));
235 }
236
237 accessibility = method.isAccessible();
238 method.setAccessible(true);
239 method.invoke(instance, lookedupResource);
240 method.setAccessible(accessibility);
241 }
242
243
244 }