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    }