    001    /*****************************************************************************
    002     * Copyright (C) PicoContainer Organization. All rights reserved.            *
    003     * ------------------------------------------------------------------------- *
    004     * The software in this package is published under the terms of the BSD      *
    005     * style license a copy of which has been included with this distribution in *
    006     * the LICENSE.txt file.                                                     *
    007     *****************************************************************************/
    008    package org.picocontainer.lifecycle;
    009
    010    import java.lang.reflect.InvocationTargetException;
    011    import java.lang.reflect.Method;
    012    import java.lang.annotation.Annotation;
    013
    014    import org.picocontainer.ComponentMonitor;
    015    import org.picocontainer.PicoLifecycleException;
    016
    017    import javax.annotation.PreDestroy;
    018    import javax.annotation.PostConstruct;
    019
    020    /**
    021     * Java EE 5 has some annotations PreDestroy and PostConstruct that map to start() and dispose() in our world
    022     *
    023     * @author Paul Hammant
    024     */
    025    @SuppressWarnings("serial")
    026    public final class JavaEE5LifecycleStrategy extends AbstractMonitoringLifecycleStrategy {
    027
    028        /**
    029         * Construct a JavaEE5LifecycleStrategy.
    030         *
    031         * @param monitor the monitor to use
    032         * @throws NullPointerException if the monitor is <code>null</code>
    033         */
    034        public JavaEE5LifecycleStrategy(final ComponentMonitor monitor) {
    035            super(monitor);
    036        }
    037
    038        /** {@inheritDoc} **/
    039        public void start(final Object component) {
    040            doLifecycleMethod(component, PostConstruct.class);
    041        }
    042
    043            /** {@inheritDoc} **/
    044        public void stop(final Object component) {
    045        }
    046
    047        /** {@inheritDoc} **/
    048        public void dispose(final Object component) {
    049            doLifecycleMethod(component, PreDestroy.class);
    050        }
    051
    052        private void doLifecycleMethod(final Object component, Class<? extends Annotation> annotation) {
    053            Method[] methods = component.getClass().getDeclaredMethods();
    054            for (int i = 0; i < methods.length; i++) {
    055                Method method = methods[i];
    056                if (method.isAnnotationPresent(annotation)) {
    057                    try {
    058                        long str = System.currentTimeMillis();
    059                        currentMonitor().invoking(null, null, method, component, new Object[0]);
    060                        method.invoke(component);
    061                        currentMonitor().invoked(null, null, method, component, System.currentTimeMillis() - str, new Object[0], null);
    062                    } catch (IllegalAccessException e) {
    063                        throw new PicoLifecycleException(method, component, e);
    064                    } catch (InvocationTargetException e) {
    065                        throw new PicoLifecycleException(method, component, e);
    066                    }
    067                }
    068            }
    069        }
    070
    071
    072        /**
    073         * {@inheritDoc} The component has a lifecycle PreDestroy or PostConstruct are on a method
    074         */
    075        public boolean hasLifecycle(final Class<?> type) {
    076            Method[] methods = type.getDeclaredMethods();
    077            for (int i = 0; i < methods.length; i++) {
    078                Method method = methods[i];
    079                if (method.isAnnotationPresent(PreDestroy.class) || method.isAnnotationPresent(PostConstruct.class)) {
    080                    return true;
    081                }
    082            }
    083            return false;
    084        }
    085
    086    }