001    // Copyright 2006, 2007, 2011 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry5.ioc.internal.services;
016    
017    import org.apache.tapestry5.func.F;
018    import org.apache.tapestry5.func.Worker;
019    import org.apache.tapestry5.ioc.internal.util.OneShotLock;
020    import org.apache.tapestry5.ioc.services.RegistryShutdownHub;
021    import org.apache.tapestry5.ioc.services.RegistryShutdownListener;
022    import org.slf4j.Logger;
023    
024    import java.util.List;
025    
026    import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newThreadSafeList;
027    
028    public class RegistryShutdownHubImpl implements RegistryShutdownHub
029    {
030        private final OneShotLock lock = new OneShotLock();
031    
032        private final Logger logger;
033    
034        private final List<Runnable> listeners = newThreadSafeList();
035    
036        private final List<Runnable> preListeners = newThreadSafeList();
037    
038        public RegistryShutdownHubImpl(Logger logger)
039        {
040            this.logger = logger;
041        }
042    
043        public void addRegistryShutdownListener(final RegistryShutdownListener listener)
044        {
045            assert listener != null;
046    
047            addRegistryShutdownListener(new Runnable()
048            {
049                public void run()
050                {
051                    listener.registryDidShutdown();
052                }
053            });
054        }
055    
056        public void addRegistryShutdownListener(Runnable listener)
057        {
058            assert listener != null;
059    
060            lock.check();
061    
062            listeners.add(listener);
063        }
064    
065        public void addRegistryWillShutdownListener(Runnable listener)
066        {
067            assert listener != null;
068    
069            lock.check();
070    
071            preListeners.add(listener);
072        }
073    
074        /**
075         * Fires the {@link RegistryShutdownListener#registryDidShutdown()} method on each listener. At the end, all the
076         * listeners are discarded.
077         */
078        public void fireRegistryDidShutdown()
079        {
080            lock.lock();
081    
082            F.flow(preListeners).concat(listeners).each(new Worker<Runnable>()
083            {
084                public void work(Runnable element)
085                {
086                    try
087                    {
088                        element.run();
089                    } catch (RuntimeException ex)
090                    {
091                        logger.error(ServiceMessages.shutdownListenerError(element, ex), ex);
092                    }
093                }
094            });
095    
096            preListeners.clear();
097            listeners.clear();
098        }
099    
100    }