/*******************************************************************************
 * Copyright (c) 2010, 2015 Sonatype, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Stuart McCulloch (Sonatype, Inc.) - initial API and implementation
 *******************************************************************************/
package org.eclipse.sisu.bean;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * {@link BeanManager} that manages JSR250 beans and schedules lifecycle events.
 */
public final class LifecycleManager
    extends BeanScheduler
    implements BeanManager
{
    // ----------------------------------------------------------------------
    // Implementation fields
    // ----------------------------------------------------------------------

    private final LifecycleBuilder builder = new LifecycleBuilder();

    private final Map<Class<?>, BeanLifecycle> lifecycles = //
        new ConcurrentHashMap<Class<?>, BeanLifecycle>( 16, 0.75f, 1 );

    private final List<Object> stoppableBeans = new ArrayList<Object>();

    // ----------------------------------------------------------------------
    // Public methods
    // ----------------------------------------------------------------------

    public boolean manage( final Class<?> clazz )
    {
        return buildLifecycle( clazz );
    }

    public PropertyBinding manage( final BeanProperty<?> property )
    {
        return null; // no custom property bindings
    }

    public boolean manage( final Object bean )
    {
        final BeanLifecycle lifecycle = lifecycleFor( bean );
        if ( lifecycle.isStoppable() )
        {
            pushStoppable( bean );
        }
        if ( lifecycle.isStartable() )
        {
            schedule( bean );
        }
        return true;
    }

    public boolean unmanage( final Object bean )
    {
        if ( removeStoppable( bean ) )
        {
            lifecycleFor( bean ).stop( bean );
        }
        return true;
    }

    public boolean unmanage()
    {
        for ( Object bean; ( bean = popStoppable() ) != null; )
        {
            lifecycleFor( bean ).stop( bean );
        }
        return true;
    }

    // ----------------------------------------------------------------------
    // Customized methods
    // ----------------------------------------------------------------------

    @Override
    protected void activate( final Object bean )
    {
        lifecycleFor( bean ).start( bean );
    }

    // ----------------------------------------------------------------------
    // Implementation methods
    // ----------------------------------------------------------------------

    /**
     * Attempts to build a JSR250 lifecycle for the given bean type.
     * 
     * @param clazz The bean type
     * @return {@code true} if the bean defines a lifecycle; otherwise {@code false}
     */
    private boolean buildLifecycle( final Class<?> clazz )
    {
        BeanLifecycle lifecycle = lifecycles.get( clazz );
        if ( null == lifecycle )
        {
            lifecycle = builder.build( clazz );
            lifecycles.put( clazz, lifecycle );
        }
        return lifecycle != BeanLifecycle.NO_OP;
    }

    /**
     * Looks up the JSR250 lifecycle previously built for this bean.
     * 
     * @param bean The bean instance
     * @return Lifecycle for the bean
     */
    private BeanLifecycle lifecycleFor( final Object bean )
    {
        if ( null != bean )
        {
            // check the class hierarchy, just in case the bean instance has been proxied/enhanced
            for ( Class<?> c = bean.getClass(); null != c && c != Object.class; c = c.getSuperclass() )
            {
                final BeanLifecycle lifecycle = lifecycles.get( c );
                if ( null != lifecycle )
                {
                    return lifecycle;
                }
            }
        }
        return BeanLifecycle.NO_OP;
    }

    private boolean pushStoppable( final Object bean )
    {
        synchronized ( stoppableBeans )
        {
            return stoppableBeans.add( bean );
        }
    }

    private boolean removeStoppable( final Object bean )
    {
        synchronized ( stoppableBeans )
        {
            return stoppableBeans.remove( bean );
        }
    }

    private Object popStoppable()
    {
        synchronized ( stoppableBeans )
        {
            final int size = stoppableBeans.size();
            return size > 0 ? stoppableBeans.remove( size - 1 ) : null;
        }
    }
}

@@ -592,20 +592,21 @@
 il.Array
-List
+Deque
 ;%0Aimport
@@ -616,20 +616,21 @@
 va.util.
-List
+Deque
 ;%0Aimport
@@ -1283,20 +1283,21 @@
 e final 
-List
+Deque
 %3CObject%3E
@@ -1327,12 +1327,13 @@
 rray
-List
+Deque
 %3CObj
@@ -4249,23 +4249,20 @@
 private 
-boolean
+void
  pushSto
@@ -4349,39 +4349,32 @@
   %7B%0A            
-return 
 stoppableBeans.a
@@ -4375,16 +4375,20 @@
 eans.add
+Last
 ( bean )
@@ -4692,118 +4692,40 @@
     
-final int size = stoppableBeans.size();%0A            return size %3E 0 ? stoppableBeans.remove( size - 1 ) : null
+return stoppableBeans.pollLast()
 ;%0A  

Use deque to manage lifecycle components