/* * Copyright 2014 Federal Chancellery Austria * MOA-ID has been developed in a cooperation between BRZ, the Federal * Chancellery Austria - ICT staff unit, and Graz University of Technology. * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * http://www.osor.eu/eupl/ * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. */ package at.gv.egovernment.moa.id.auth; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.TimeUnit; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextClosedEvent; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.stereotype.Component; import at.gv.egiz.eaaf.core.api.IDestroyableObject; import at.gv.egovernment.moa.logging.Logger; /** * @author tlenz * */ @Component public class MOAContextCloseHandler implements ApplicationListener, ApplicationContextAware, BeanPostProcessor { private ApplicationContext context; /* (non-Javadoc) * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent) */ @Override public void onApplicationEvent(ContextClosedEvent arg0) { Logger.info("MOA-ID-Auth shutdown process started ..."); try { Logger.debug("CleanUp objects with implements the IDestroyable interface ... "); Map objectsToDestroy = context.getBeansOfType(IDestroyableObject.class); if (objectsToDestroy != null) { Iterator> interator = objectsToDestroy.entrySet().iterator(); while (interator.hasNext()) { Entry object = interator.next(); try { object.getValue().fullyDestroy(); Logger.debug("Object with ID:" + object.getKey() + " is destroyed"); } catch (Exception e) { Logger.warn("Destroing object with ID:" + object.getKey() + " FAILED!", e); } } } Logger.info("Object cleanUp complete"); Logger.debug("Stopping Spring Thread-Pools ... "); //shut-down task schedulers Map schedulers = context.getBeansOfType(ThreadPoolTaskScheduler.class); for (ThreadPoolTaskScheduler scheduler : schedulers.values()) { scheduler.getScheduledExecutor().shutdown(); try { scheduler.getScheduledExecutor().awaitTermination(20000, TimeUnit.MILLISECONDS); if(scheduler.getScheduledExecutor().isTerminated() || scheduler.getScheduledExecutor().isShutdown()) Logger.debug("Scheduler "+scheduler.getThreadNamePrefix() + " has stoped"); else{ Logger.debug("Scheduler "+scheduler.getThreadNamePrefix() + " has not stoped normally and will be shut down immediately"); scheduler.getScheduledExecutor().shutdownNow(); Logger.info("Scheduler "+scheduler.getThreadNamePrefix() + " has shut down immediately"); } } catch (IllegalStateException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } finally { scheduler.shutdown(); } } //shut-down task executors Map executers = context.getBeansOfType(ThreadPoolTaskExecutor.class); for (ThreadPoolTaskExecutor executor: executers.values()) { int retryCount = 0; while(executor.getActiveCount()>0 && ++retryCount<51){ try { Logger.debug("Executer "+executor.getThreadNamePrefix()+" is still working with active " + executor.getActiveCount()+" work. Retry count is "+retryCount); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } if(!(retryCount<51)) Logger.debug("Executer "+executor.getThreadNamePrefix()+" is still working.Since Retry count exceeded max value "+retryCount+", will be killed immediately"); executor.shutdown(); Logger.debug("Executer "+executor.getThreadNamePrefix()+" with active " + executor.getActiveCount()+" work has killed"); } Logger.debug("Spring Thread-Pools stopped"); Logger.info("MOA-ID-Auth shutdown process finished"); } catch (Exception e) { Logger.warn("MOA-ID-Auth shutdown process has an error.", e); } //System.exit(0); //Thread.currentThread().interrupt(); } /* (non-Javadoc) * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String) */ @Override public Object postProcessAfterInitialization(Object arg0, String arg1) throws BeansException { if(arg0 instanceof ThreadPoolTaskScheduler) ((ThreadPoolTaskScheduler)arg0).setWaitForTasksToCompleteOnShutdown(true); if(arg0 instanceof ThreadPoolTaskExecutor) ((ThreadPoolTaskExecutor)arg0).setWaitForTasksToCompleteOnShutdown(true); return arg0; } /* (non-Javadoc) * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) */ @Override public Object postProcessBeforeInitialization(Object arg0, String arg1) throws BeansException { return arg0; } /* (non-Javadoc) * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) */ @Override public void setApplicationContext(ApplicationContext arg0) throws BeansException { this.context = arg0; } }