You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by st...@apache.org on 2008/06/05 16:51:13 UTC

svn commit: r663634 - /jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/TransientFileFactory.java

Author: stefan
Date: Thu Jun  5 07:51:12 2008
New Revision: 663634

URL: http://svn.apache.org/viewvc?rev=663634&view=rev
Log:
JCR-1636: Make shutdown hooks in TransientFileFactory removable

Modified:
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/TransientFileFactory.java

Modified: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/TransientFileFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/TransientFileFactory.java?rev=663634&r1=663633&r2=663634&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/TransientFileFactory.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/TransientFileFactory.java Thu Jun  5 07:51:12 2008
@@ -59,6 +59,11 @@
     private final Thread reaper;
 
     /**
+     * Shutdown hook which removes all files awaiting deletion
+     */
+    private static Thread shutdownHook = null;
+
+    /**
      * Returns the singleton <code>TransientFileFactory</code> instance.
      */
     public static TransientFileFactory getInstance() {
@@ -81,20 +86,12 @@
         reaper.start();
         // register shutdownhook for final cleaning up
         try {
-            Runtime.getRuntime().addShutdownHook(new Thread() {
+            shutdownHook = new Thread() {
                 public void run() {
-                    // synchronize on the list before iterating over it in order
-                    // to avoid ConcurrentModificationException (JCR-549)
-                    // @see java.lang.util.Collections.synchronizedList(java.util.List)
-                    synchronized(trackedRefs) {
-                        for (Iterator it = trackedRefs.iterator(); it.hasNext();) {
-                            MoribundFileReference fileRef = (MoribundFileReference) it.next();
-                            fileRef.delete();
-                        }
-
-                    }
+                    doShutdown();
                 }
-            });
+            };
+            Runtime.getRuntime().addShutdownHook(shutdownHook);
         } catch (IllegalStateException e) {
             // can't register shutdownhook because
             // jvm shutdown sequence has already begun,
@@ -126,6 +123,49 @@
         return f;
     }
 
+    /**
+     * Shuts this factory down removing all temp files and removes shutdown hook.
+     * <p/>
+     * <b>Warning!!!</b>
+     * <p/>
+     * This should be called by a web-application <b><i>IF</b></i> it is unloaded
+     * <b><i>AND IF</i></b> jackrabbit-jcr-commons.jar had been loaded by
+     * the webapp classloader. This must be called after all repositories had
+     * been stopped, so use with great care!
+     * <p/>
+     * See http://issues.apache.org/jira/browse/JCR-1636 for details.
+     */
+    public static void shutdown() {
+        getInstance().doShutdown();
+    }
+
+    /**
+     * Actually shuts factory down removing all temp files. This happens when
+     * VM shutdown hook works or when explicitly requested.
+     * Shutdown hook is removed.
+     */
+    private synchronized void doShutdown() {
+        // synchronize on the list before iterating over it in order
+        // to avoid ConcurrentModificationException (JCR-549)
+        // @see java.lang.util.Collections.synchronizedList(java.util.List)
+        synchronized(trackedRefs) {
+            for (Iterator it = trackedRefs.iterator(); it.hasNext();) {
+                MoribundFileReference fileRef = (MoribundFileReference) it.next();
+                fileRef.delete();
+            }
+
+        }
+        if (shutdownHook != null) {
+            try {
+                Runtime.getRuntime().removeShutdownHook(shutdownHook);
+            } catch (IllegalStateException e) {
+                // can't unregister shutdownhook because
+                // jvm shutdown sequence has already begun,
+                // silently ignore... 
+            }
+        }
+    }
+
     //--------------------------------------------------------< inner classes >
     /**
      * The reaper thread that will remove the files that are ready for deletion.