package at.asitplus.eidas.specific.connector; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import org.slf4j.Logger; 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.context.event.EventListener; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import at.gv.egiz.components.spring.api.IDestroyableObject; import eu.eidas.auth.cache.IgniteInstanceInitializerSpecificCommunication; /** * SpringContext CloseHandler. * * @author tlenz * */ public class SpringContextCloseHandler implements ApplicationListener, ApplicationContextAware, BeanPostProcessor { private static final Logger log = org.slf4j.LoggerFactory.getLogger(SpringContextCloseHandler.class); private ApplicationContext context; /* * (non-Javadoc) * * @see org.springframework.context.ApplicationListener#onApplicationEvent(org. * springframework.context. ApplicationEvent) */ @Override @EventListener public void onApplicationEvent(final ContextClosedEvent arg0) { log.info("MS-specific eIDAS-Node shutdown process started ..."); try { log.debug("CleanUp objects with implements the IDestroyable interface ... "); final Map objectsToDestroy = context.getBeansOfType(IDestroyableObject.class); internalIDestroyableObject(objectsToDestroy); log.info("Object cleanUp complete"); log.debug("Stopping Spring Thread-Pools ... "); // shut-down task schedulers final Map schedulers = context.getBeansOfType(ThreadPoolTaskScheduler.class); internalThreadPoolTaskScheduler(schedulers); // shut-down task executors final Map executers = context.getBeansOfType(ThreadPoolTaskExecutor.class); internalThreadPoolTaskExecutor(executers); log.debug("Spring Thread-Pools stopped"); //clean-up eIDAS node Map nodeIgnite = context.getBeansOfType(IgniteInstanceInitializerSpecificCommunication.class); log.info("Find #{} Apache Ignite instances from eIDAS Ref. impl.", nodeIgnite.size()); for (Entry el : nodeIgnite.entrySet()) { if (el.getValue().getInstance() != null) { el.getValue().getInstance().close(); el.getValue().destroyInstance(); log.debug("Shutdown Apache-Ignite: {}", el.getKey()); } } log.info("MS-specific eIDAS-Node shutdown process finished"); } catch (final Exception e) { log.warn("MS-specific eIDAS-Node shutdown process has an error.", e); } } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.BeanPostProcessor# * postProcessAfterInitialization(java. lang.Object, java.lang.String) */ @Override public Object postProcessAfterInitialization(final Object arg0, final 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(final Object arg0, final String arg1) throws BeansException { return arg0; } /* * (non-Javadoc) * * @see * org.springframework.context.ApplicationContextAware#setApplicationContext(org * .springframework. context.ApplicationContext) */ @Override public void setApplicationContext(final ApplicationContext arg0) throws BeansException { this.context = arg0; } private void internalThreadPoolTaskExecutor(final Map executers) { for (final ThreadPoolTaskExecutor executor : executers.values()) { executor.shutdown(); log.debug("Executer {} with active {} work has killed", executor.getThreadNamePrefix(), executor.getActiveCount()); } } // Not required at the moment private void internalThreadPoolTaskScheduler( final Map schedulers) { log.trace("Stopping #{} task-schedulers", schedulers.size()); } private void internalIDestroyableObject(final Map objectsToDestroy) { if (objectsToDestroy != null) { final Iterator> interator = objectsToDestroy.entrySet().iterator(); while (interator.hasNext()) { final Entry object = interator.next(); try { object.getValue().fullyDestroy(); log.debug("Object with ID: {} is destroyed", object.getKey()); } catch (final Exception e) { log.warn("Destroing object with ID: {} FAILED!", object.getKey(), null, e); } } } } }