001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.openejb.config.rules;
017:
018: import org.apache.openejb.config.EjbModule;
019: import org.apache.openejb.jee.EnterpriseBean;
020: import org.apache.openejb.jee.AroundInvoke;
021: import org.apache.openejb.jee.CallbackMethod;
022: import org.apache.openejb.jee.LifecycleCallback;
023: import org.apache.openejb.jee.Session;
024: import org.apache.openejb.jee.Interceptor;
025: import org.apache.openejb.jee.TimerConsumer;
026: import org.apache.openejb.jee.NamedMethod;
027: import org.apache.openejb.OpenEJBException;
028:
029: import javax.interceptor.InvocationContext;
030: import java.lang.reflect.Method;
031: import java.util.List;
032: import java.util.ArrayList;
033:
034: /**
035: * @version $Rev: 637726 $ $Date: 2008-03-16 22:34:37 -0700 $
036: */
037: public class CheckCallbacks extends ValidationBase {
038:
039: public void validate(EjbModule module) {
040: for (EnterpriseBean bean : module.getEjbJar()
041: .getEnterpriseBeans()) {
042: Class ejbClass = null;
043: try {
044: ejbClass = loadClass(bean.getEjbClass());
045: } catch (OpenEJBException e) {
046: continue;
047: }
048:
049: for (AroundInvoke aroundInvoke : bean.getAroundInvoke()) {
050: checkAroundInvoke(ejbClass, aroundInvoke, bean
051: .getEjbName());
052: }
053:
054: for (LifecycleCallback callback : bean.getPostConstruct()) {
055: checkCallback(ejbClass, "PostConstruct", callback, bean);
056: }
057:
058: for (LifecycleCallback callback : bean.getPreDestroy()) {
059: checkCallback(ejbClass, "PreDestroy", callback, bean);
060: }
061:
062: if (bean instanceof Session) {
063: Session session = (Session) bean;
064:
065: for (LifecycleCallback callback : session
066: .getPrePassivate()) {
067: checkCallback(ejbClass, "PrePassivate", callback,
068: bean);
069: }
070:
071: for (LifecycleCallback callback : session
072: .getPostActivate()) {
073: checkCallback(ejbClass, "PostActivate", callback,
074: bean);
075: }
076:
077: }
078:
079: if (bean instanceof TimerConsumer) {
080: TimerConsumer timerConsumer = (TimerConsumer) bean;
081: checkTimeOut(ejbClass,
082: timerConsumer.getTimeoutMethod(), bean);
083: }
084: }
085:
086: for (Interceptor interceptor : module.getEjbJar()
087: .getInterceptors()) {
088: Class interceptorClass = null;
089: try {
090: interceptorClass = loadClass(interceptor
091: .getInterceptorClass());
092: } catch (OpenEJBException e) {
093: continue;
094: }
095:
096: for (AroundInvoke aroundInvoke : interceptor
097: .getAroundInvoke()) {
098: checkAroundInvoke(interceptorClass, aroundInvoke,
099: "Interceptor");
100: }
101:
102: for (LifecycleCallback callback : interceptor
103: .getPostConstruct()) {
104: checkCallback(interceptorClass, "PostConstruct",
105: callback, interceptor);
106: }
107:
108: for (LifecycleCallback callback : interceptor
109: .getPreDestroy()) {
110: checkCallback(interceptorClass, "PreDestroy", callback,
111: interceptor);
112: }
113:
114: for (LifecycleCallback callback : interceptor
115: .getPrePassivate()) {
116: checkCallback(interceptorClass, "PrePassivate",
117: callback, interceptor);
118: }
119:
120: for (LifecycleCallback callback : interceptor
121: .getPostActivate()) {
122: checkCallback(interceptorClass, "PostActivate",
123: callback, interceptor);
124: }
125: }
126: }
127:
128: private void checkAroundInvoke(Class ejbClass,
129: AroundInvoke aroundInvoke, String componentName) {
130: try {
131: Method method = getMethod(ejbClass, aroundInvoke
132: .getMethodName(), InvocationContext.class);
133:
134: Class<?> returnType = method.getReturnType();
135:
136: if (!returnType.equals(Object.class)) {
137: fail(componentName, "aroundInvoke.badReturnType",
138: aroundInvoke.getMethodName(), returnType
139: .getName(), aroundInvoke.getClassName());
140: }
141:
142: boolean throwsException = false;
143: for (Class<?> exceptionType : method.getExceptionTypes()) {
144: if (exceptionType.getName().equals(
145: Exception.class.getName())) {
146: throwsException = true;
147: }
148: }
149:
150: if (!throwsException) {
151: fail(componentName, "aroundInvoke.mustThrowException",
152: aroundInvoke.getMethodName(), aroundInvoke
153: .getClassName());
154: }
155:
156: } catch (NoSuchMethodException e) {
157: List<Method> possibleMethods = getMethods(ejbClass,
158: aroundInvoke.getMethodName());
159:
160: if (possibleMethods.size() == 0) {
161: fail(componentName, "aroundInvoke.missing",
162: aroundInvoke.getMethodName(), aroundInvoke
163: .getClassName());
164: } else if (possibleMethods.size() == 1) {
165: fail(componentName, "aroundInvoke.invalidArguments",
166: aroundInvoke.getMethodName(),
167: getParameters(possibleMethods.get(0)),
168: aroundInvoke.getClassName());
169: } else {
170: fail(componentName,
171: "aroundInvoke.missing.possibleTypo",
172: aroundInvoke.getMethodName(), possibleMethods
173: .size(), aroundInvoke.getClassName());
174: }
175: }
176: }
177:
178: private void checkCallback(Class ejbClass, String type,
179: CallbackMethod callback, EnterpriseBean bean) {
180: try {
181: Method method = getMethod(ejbClass, callback
182: .getMethodName());
183:
184: Class<?> returnType = method.getReturnType();
185:
186: if (!returnType.equals(Void.TYPE)) {
187: fail(bean, "callback.badReturnType", type, callback
188: .getMethodName(), returnType.getName(),
189: callback.getClassName());
190: }
191: } catch (NoSuchMethodException e) {
192: List<Method> possibleMethods = getMethods(ejbClass,
193: callback.getMethodName());
194:
195: if (possibleMethods.size() == 0) {
196: fail(bean, "callback.missing", type, callback
197: .getMethodName(), callback.getClassName());
198: } else if (possibleMethods.size() == 1) {
199: fail(bean, "callback.invalidArguments", type, callback
200: .getMethodName(), getParameters(possibleMethods
201: .get(0)), callback.getClassName());
202: } else {
203: fail(bean, "callback.missing.possibleTypo", type,
204: callback.getMethodName(), possibleMethods
205: .size(), callback.getClassName());
206: }
207: }
208: }
209:
210: private void checkCallback(Class interceptorClass, String type,
211: CallbackMethod callback, Interceptor interceptor) {
212: try {
213: Method method = getMethod(interceptorClass, callback
214: .getMethodName(), InvocationContext.class);
215:
216: Class<?> returnType = method.getReturnType();
217:
218: if (!returnType.equals(Void.TYPE)) {
219: fail("Interceptor",
220: "interceptor.callback.badReturnType",
221: interceptorClass, type, callback
222: .getMethodName(), returnType.getName());
223: }
224: } catch (NoSuchMethodException e) {
225: List<Method> possibleMethods = getMethods(interceptorClass,
226: callback.getMethodName());
227:
228: if (possibleMethods.size() == 0) {
229: fail("Interceptor", "interceptor.callback.missing",
230: type, callback.getMethodName(),
231: interceptorClass.getName());
232: } else if (possibleMethods.size() == 1) {
233: fail("Interceptor",
234: "interceptor.callback.invalidArguments", type,
235: callback.getMethodName(),
236: getParameters(possibleMethods.get(0)),
237: interceptorClass.getName());
238: } else {
239: fail("Interceptor",
240: "interceptor.callback.missing.possibleTypo",
241: type, callback.getMethodName(), possibleMethods
242: .size(), interceptorClass.getName());
243: }
244: }
245: }
246:
247: private void checkTimeOut(Class ejbClass, NamedMethod timeout,
248: EnterpriseBean bean) {
249: if (timeout == null)
250: return;
251: try {
252: Method method = getMethod(ejbClass,
253: timeout.getMethodName(), javax.ejb.Timer.class);
254:
255: Class<?> returnType = method.getReturnType();
256:
257: if (!returnType.equals(Void.TYPE)) {
258: fail(bean, "timeout.badReturnType", timeout
259: .getMethodName(), returnType.getName());
260: }
261: } catch (NoSuchMethodException e) {
262: List<Method> possibleMethods = getMethods(ejbClass, timeout
263: .getMethodName());
264:
265: if (possibleMethods.size() == 0) {
266: fail(bean, "timeout.missing", timeout.getMethodName());
267: } else if (possibleMethods.size() == 1) {
268: fail(bean, "timeout.invalidArguments", timeout
269: .getMethodName(), getParameters(possibleMethods
270: .get(0)));
271: } else {
272: fail(bean, "timeout.missing.possibleTypo", timeout
273: .getMethodName(), possibleMethods.size());
274: }
275: }
276: }
277:
278: private Method getMethod(Class clazz, String methodName,
279: Class... parameterTypes) throws NoSuchMethodException {
280: NoSuchMethodException original = null;
281: while (clazz != null) {
282: try {
283: return clazz.getDeclaredMethod(methodName,
284: parameterTypes);
285: } catch (NoSuchMethodException e) {
286: if (original == null)
287: original = e;
288: }
289: clazz = clazz.getSuperclass();
290: }
291: throw original;
292: }
293:
294: private List<Method> getMethods(Class clazz, String methodName) {
295: List<Method> methods = new ArrayList<Method>();
296: while (clazz != null) {
297: for (Method method : clazz.getDeclaredMethods()) {
298: if (method.getName().equals(methodName)) {
299: methods.add(method);
300: }
301: }
302: }
303: return methods;
304: }
305:
306: }
|