/* This file is part of Cyclos (www.cyclos.org). A project of the Social Trade Organisation (www.socialtrade.org). Cyclos is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Cyclos is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cyclos; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package nl.strohalm.cyclos.utils; import java.io.Closeable; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import nl.strohalm.cyclos.utils.query.IteratorList; import org.hibernate.Hibernate; /** * Helper class for data iterators * * @author luis */ public class DataIteratorHelper { private static final ThreadLocal<Map<Iterator<?>, Boolean>> OPEN_ITERATORS = new ThreadLocal<Map<Iterator<?>, Boolean>>(); /** * Closes a data iterator. Internally invokes Hibernate.close(), but exists to avoid clients having to rely on hibernate */ public static void close(final Iterator<?> iterator) { close(iterator, true); } /** * Closes the given {@link IteratorList}'s underlying iterator, by invoking {@link #close(Iterator)} */ public static void close(final IteratorList<?> iteratorList) { close(iteratorList.getIterator(), true); } /** * Invokes {@link #close(Iterator)} with the list iterator, handling {@link IteratorList}s by using {@link IteratorList#getIterator()} */ public static void close(final List<?> list) { Iterator<?> iterator; if (list instanceof IteratorList<?>) { iterator = ((IteratorList<?>) list).getIterator(); } else { iterator = list.iterator(); } close(iterator); } /** * Closes all open iterators in this thread */ public static void closeOpenIterators() { final Map<Iterator<?>, Boolean> iterators = OPEN_ITERATORS.get(); if (iterators == null) { return; } for (final Iterator<?> iterator : iterators.keySet()) { close(iterator, false); } iterators.clear(); OPEN_ITERATORS.remove(); } /** * Returns whether there is at least one open iterator which requires an open connection */ public static boolean hasOpenIteratorsRequiringOpenConnection() { final Map<Iterator<?>, Boolean> iterators = OPEN_ITERATORS.get(); if (iterators != null) { for (final Boolean requiresOpenConnection : iterators.values()) { if (Boolean.TRUE.equals(requiresOpenConnection)) { return true; } } } return false; } /** * Registers an open iterator for this thread, so that in future, it may be forcefully closed to avoid open data iterators */ public static void registerOpen(final Iterator<?> iterator, final boolean requiresOpenConnection) { if (iterator == null) { return; } Map<Iterator<?>, Boolean> iterators = OPEN_ITERATORS.get(); if (iterators == null) { iterators = new HashMap<Iterator<?>, Boolean>(); OPEN_ITERATORS.set(iterators); } iterators.put(iterator, requiresOpenConnection); } private static void close(final Iterator<?> iterator, final boolean remove) { if (iterator instanceof Closeable) { // Is an index reader. Invoke the close() method final Closeable closeable = (Closeable) iterator; try { closeable.close(); } catch (final Exception e) { // Silently ignore } } else { // Close the iterator with Hibernate try { Hibernate.close(iterator); } catch (final Exception e) { // Silently ignore } } // Remove the iterator from the thread-bound set if (remove) { final Map<Iterator<?>, Boolean> iterators = OPEN_ITERATORS.get(); if (iterators != null) { iterators.remove(iterator); } } } }