/* Cleanups.java Purpose: Description: History: Fri Mar 12 11:55:59 TST 2010, Created by tomyeh Copyright (C) 2010 Potix Corporation. All Rights Reserved. */ package org.zkoss.util; import java.util.List; import java.util.LinkedList; import java.util.ArrayList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Utilities to clean up resources when the application is stopping. * Currently, when a ZK application is stopping, ZK will invoke {@link #cleanup}. * Thus you can register an implementation of {@link Cleanup} * to release the resources. * <p>Notice that this utility is introduced mainly to resolve * the memory lead issue if an application is hot re-deployed. * A typical example is to stop any pooled threads. * <h3>How to use:</h3> * <p>First, register the cleanup with {@link #add}.</p> * <p>Second, invoke {@link #cleanup} when necessary, such as when the application * is stopping</p>. * * @author tomyeh * @since 3.6.5 */ public class Cleanups { private static final Logger log = LoggerFactory.getLogger(Cleanups.class); private static final List<Cleanup> _cleanups = new LinkedList<Cleanup>(); /** Registers a cleanup. * @return true if it is added successfully, or false if the cleanup * has been registered before. */ public static boolean add(Cleanup cleanup) { if (cleanup == null) throw new IllegalArgumentException(); synchronized (_cleanups) { if (_cleanups.contains(cleanup)) return false; return _cleanups.add(cleanup); } } /** Un-registers a cleanup. * @return true if it is removed successfully, or false if not registered before. */ public static boolean remove(Cleanup cleanup) { synchronized (_cleanups) { return _cleanups.remove(cleanup); } } /** Invokes all cleanups registered with {@link #add}. */ public static void cleanup() { final List<Cleanup> cleanups; synchronized (_cleanups) { cleanups = new ArrayList<Cleanup>(_cleanups); } for (Cleanup cleanup: cleanups) { try { cleanup.cleanup(); } catch (Throwable ex) { log.error("Failed to invoke "+cleanup); } } } /** The interface to implement for each cleanup. * It is used with {@link Cleanups#add}. * @since 3.6.5 */ public static interface Cleanup { /** Cleanups the thread local variables. */ public void cleanup(); } }