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