Index: src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java (revision 777387) +++ src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java (working copy) @@ -34,6 +34,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import javax.jcr.Item; import javax.jcr.Node; @@ -84,9 +85,12 @@ private final IterablePersistenceManager[] pmList; private final Session[] sessionList; + private final SessionListener sessionListener; private boolean persistenceManagerScan; + private AtomicBoolean closed = new AtomicBoolean(); + // TODO It should be possible to stop and restart a garbage collection scan. /** @@ -96,23 +100,42 @@ * * @param list the persistence managers */ - public GarbageCollector(final SessionImpl session, IterablePersistenceManager[] list, final Session[] sessionList) { + public GarbageCollector(SessionImpl session, IterablePersistenceManager[] list, Session[] sessionList) { RepositoryImpl rep = (RepositoryImpl) session.getRepository(); store = rep.getDataStore(); this.pmList = list; this.persistenceManagerScan = list != null; this.sessionList = sessionList; - - // log out each session as soon as the main session logs out - session.addListener(new SessionListener() { + + // Auto-close if the main session logs out + this.sessionListener = new SessionListener() { public void loggedOut(SessionImpl session) { - for (Session s: sessionList) { - s.logout(); - } } public void loggingOut(SessionImpl session) { + close(); + } + }; + session.addListener(this.sessionListener); + } + + /** + * Cleanup resources used internally by this instance + */ + public void close() { + if (!closed.getAndSet(true)) { + for (Session s: sessionList) { + s.logout(); } - }); + } + } + + /** + * Auto-close in case the application didn't call it explicitly + */ + @Override + protected void finalize() throws Throwable { + close(); + super.finalize(); } /**