/* * Copyright 2008 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.rioproject.impl.bean; import org.rioproject.deploy.ServiceBeanInstantiationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * A utility class that assists in invoking bean lifecycle events, either using * annotations or declared method names * * @author Dennis Reedy */ public class BeanHelper { private static final Logger logger = LoggerFactory.getLogger("org.rioproject.bean"); /** * Invoke a lifecycle method * * @param annClass The annotation class to use * @param methodName The lifecycle method name to invoke if the annotation * is not found * @param bean The bean to invoke methods on * @throws ServiceBeanInstantiationException of errors occur */ public static void invokeLifeCycle(final Class<? extends Annotation> annClass, final String methodName, final Object bean) throws ServiceBeanInstantiationException { if(bean==null) { return; } /* First check if the annotation is declared */ String methodNameToInvoke = methodName; Method m = getAnnotatedMethod(bean, annClass); if (m != null) { methodNameToInvoke = m.getName(); } ClassLoader currentCL = Thread.currentThread().getContextClassLoader(); ClassLoader beanCL = bean.getClass().getClassLoader(); Thread.currentThread().setContextClassLoader(beanCL); Throwable abort = null; try { Method method = bean.getClass().getMethod(methodNameToInvoke, (Class[]) null); logger.trace("Invoking method [{}] on [{}]", methodNameToInvoke, bean.getClass().getName()); method.invoke(bean, (Object[]) null); } catch (NoSuchMethodException e) { logger.trace("Bean [{}] does not have lifecycle method {}() defined", bean.getClass().getName(), methodNameToInvoke); } catch (IllegalAccessException e) { logger.trace("Bean [{}] {}() method security access", bean.getClass().getName(), methodNameToInvoke, e); abort = e; } catch (InvocationTargetException e) { abort = e.getCause()==null? e.getTargetException(): e.getCause(); logger.trace("Bean [{}] {}() method invocation", bean.getClass().getName(), methodNameToInvoke, e); } catch(Throwable t) { abort = t; } finally { Thread.currentThread().setContextClassLoader(currentCL); } if(abort!=null) { String message = String.format("Invoking Bean [%s] %s() method", bean.getClass().getName(), methodNameToInvoke); logger.warn(message, abort); throw new ServiceBeanInstantiationException(message, abort, true); } } /** * Helper to invoke a method on the bean using reflection * * @param bean The bean to act on * @param annClass The annotation class to use * @param methodName The method name * @param classArgs Class arguments * @param objectArgs Object argument * @return The result of dispatching the method * @throws ServiceBeanInstantiationException If errors occur */ public static Object invokeBeanMethod(final Object bean, final Class<? extends Annotation> annClass, final String methodName, final Class[] classArgs, final Object[] objectArgs) throws ServiceBeanInstantiationException { /* First check if the annotation is declared */ Method m = getAnnotatedMethod(bean, annClass); String methodNameToInvoke = methodName; if (m != null) { methodNameToInvoke = m.getName(); } Object result = null; ClassLoader currentCL = Thread.currentThread().getContextClassLoader(); ClassLoader beanCL = bean.getClass().getClassLoader(); Throwable abort = null; Thread.currentThread().setContextClassLoader(beanCL); try { Method method = bean.getClass().getMethod(methodNameToInvoke, classArgs); result = method.invoke(bean, objectArgs); } catch (NoSuchMethodException e) { logger.trace("Bean [{}] does not have a {}() method defined", bean.getClass().getName(), methodNameToInvoke); } catch (IllegalAccessException e) { logger.trace("Bean [{}] {}() method security access", bean.getClass().getName(), methodNameToInvoke, e); abort = e; } catch (InvocationTargetException e) { abort = e.getCause()==null? e.getTargetException(): e.getCause(); logger.trace("Bean [{}] {}() method invocation", bean.getClass().getName(), methodNameToInvoke, abort); } catch(Throwable t) { logger.trace("Bean [{}] {}() method invocation", bean.getClass().getName(), methodNameToInvoke, abort); abort = t; } finally { Thread.currentThread().setContextClassLoader(currentCL); } if(abort!=null) { String message = String.format("Invoking Bean [%s] %s() method", bean.getClass().getName(), methodNameToInvoke); throw new ServiceBeanInstantiationException(message, abort, true); } return (result); } public static Class<?> getMethodFirstParamType(final String methodName, final Object o) { Class<?> firstParamType = null; Method[] methods = o.getClass().getMethods(); for (Method method : methods) { if (method.getName().equals(methodName)) { firstParamType = getMethodFirstParamType(method); } } return firstParamType; } public static Class getMethodFirstParamType(final Method method) { Class firstParamType = null; Class[] types = method.getParameterTypes(); if (types.length > 0) { firstParamType = types[0]; } return (firstParamType); } public static boolean hasAnnotation(final Object bean, final Class<? extends Annotation> annClass) { boolean hasAnnotation = false; if(bean!=null && annClass!=null) { Method[] methods = bean.getClass().getMethods(); for (Method method : methods) { if(method.getAnnotation(annClass)!=null) { hasAnnotation = true; break; } } } return hasAnnotation; } public static Method getAnnotatedMethod(final Object bean, final Class<? extends Annotation> annClass) { Method m = null; if(bean!=null && annClass!=null) { Method[] methods = bean.getClass().getMethods(); for (Method method : methods) { if(method.getAnnotation(annClass)!=null) { m = method; break; } } } return (m); } }