    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
    015package org.apache.tapestry5.ioc.internal.services;
    016
    017import org.apache.tapestry5.func.F;
    018import org.apache.tapestry5.func.Worker;
    019import org.apache.tapestry5.ioc.internal.util.OneShotLock;
    020import org.apache.tapestry5.ioc.services.RegistryShutdownHub;
    021import org.apache.tapestry5.ioc.services.RegistryShutdownListener;
    022import org.slf4j.Logger;
    023
    024import java.util.List;
    025
    026import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newThreadSafeList;
    027
    028public 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    @Override
    044    public void addRegistryShutdownListener(final RegistryShutdownListener listener)
    045    {
    046        assert listener != null;
    047
    048        addRegistryShutdownListener(new Runnable()
    049        {
    050            @Override
    051            public void run()
    052            {
    053                listener.registryDidShutdown();
    054            }
    055        });
    056    }
    057
    058    @Override
    059    public void addRegistryShutdownListener(Runnable listener)
    060    {
    061        assert listener != null;
    062
    063        lock.check();
    064
    065        listeners.add(listener);
    066    }
    067
    068    @Override
    069    public void addRegistryWillShutdownListener(Runnable listener)
    070    {
    071        assert listener != null;
    072
    073        lock.check();
    074
    075        preListeners.add(listener);
    076    }
    077
    078    /**
    079     * Fires the {@link RegistryShutdownListener#registryDidShutdown()} method on each listener. At the end, all the
    080     * listeners are discarded.
    081     */
    082    public void fireRegistryDidShutdown()
    083    {
    084        lock.lock();
    085
    086        F.flow(preListeners).concat(listeners).each(new Worker<Runnable>()
    087        {
    088            @Override
    089            public void work(Runnable element)
    090            {
    091                try
    092                {
    093                    element.run();
    094                } catch (RuntimeException ex)
    095                {
    096                    logger.error(ServiceMessages.shutdownListenerError(element, ex), ex);
    097                }
    098            }
    099        });
    100
    101        preListeners.clear();
    102        listeners.clear();
    103    }
    104
    105}