src/jdk.internal.le/share/classes/jdk/internal/jline/internal/ShutdownHooks.java
changeset 52974 ddbd9744a3d5
parent 52973 a659ccd1888d
parent 52961 d67b37917e82
child 52975 35e2bbea78b2
child 53179 760293737af0
equal deleted inserted replaced
52973:a659ccd1888d 52974:ddbd9744a3d5
     1 /*
       
     2  * Copyright (c) 2002-2016, the original author or authors.
       
     3  *
       
     4  * This software is distributable under the BSD license. See the terms of the
       
     5  * BSD license in the documentation provided with this software.
       
     6  *
       
     7  * http://www.opensource.org/licenses/bsd-license.php
       
     8  */
       
     9 package jdk.internal.jline.internal;
       
    10 
       
    11 import java.util.ArrayList;
       
    12 import java.util.List;
       
    13 
       
    14 import static jdk.internal.jline.internal.Preconditions.checkNotNull;
       
    15 
       
    16 /**
       
    17  * Manages the JLine shutdown-hook thread and tasks to execute on shutdown.
       
    18  *
       
    19  * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
       
    20  * @since 2.7
       
    21  */
       
    22 public class ShutdownHooks
       
    23 {
       
    24     public static final String JLINE_SHUTDOWNHOOK = "jline.shutdownhook";
       
    25 
       
    26     private static final boolean enabled = Configuration.getBoolean(JLINE_SHUTDOWNHOOK, true);
       
    27 
       
    28     private static final List<Task> tasks = new ArrayList<Task>();
       
    29 
       
    30     private static Thread hook;
       
    31 
       
    32     public static synchronized <T extends Task> T add(final T task) {
       
    33         checkNotNull(task);
       
    34 
       
    35         // If not enabled ignore
       
    36         if (!enabled) {
       
    37             Log.debug("Shutdown-hook is disabled; not installing: ", task);
       
    38             return task;
       
    39         }
       
    40 
       
    41         // Install the hook thread if needed
       
    42         if (hook == null) {
       
    43             hook = addHook(new Thread("JLine Shutdown Hook")
       
    44             {
       
    45                 @Override
       
    46                 public void run() {
       
    47                     runTasks();
       
    48                 }
       
    49             });
       
    50         }
       
    51 
       
    52         // Track the task
       
    53         Log.debug("Adding shutdown-hook task: ", task);
       
    54         tasks.add(task);
       
    55 
       
    56         return task;
       
    57     }
       
    58 
       
    59     private static synchronized void runTasks() {
       
    60         Log.debug("Running all shutdown-hook tasks");
       
    61 
       
    62         // Iterate through copy of tasks list
       
    63         for (Task task : tasks.toArray(new Task[tasks.size()])) {
       
    64             Log.debug("Running task: ", task);
       
    65             try {
       
    66                 task.run();
       
    67             }
       
    68             catch (Throwable e) {
       
    69                 Log.warn("Task failed", e);
       
    70             }
       
    71         }
       
    72 
       
    73         tasks.clear();
       
    74     }
       
    75 
       
    76     private static Thread addHook(final Thread thread) {
       
    77         Log.debug("Registering shutdown-hook: ", thread);
       
    78         try {
       
    79             Runtime.getRuntime().addShutdownHook(thread);
       
    80         }
       
    81         catch (AbstractMethodError e) {
       
    82             // JDK 1.3+ only method. Bummer.
       
    83             Log.debug("Failed to register shutdown-hook", e);
       
    84         }
       
    85         return thread;
       
    86     }
       
    87 
       
    88     public static synchronized void remove(final Task task) {
       
    89         checkNotNull(task);
       
    90 
       
    91         // ignore if not enabled or hook never installed
       
    92         if (!enabled || hook == null) {
       
    93             return;
       
    94         }
       
    95 
       
    96         // Drop the task
       
    97         tasks.remove(task);
       
    98 
       
    99         // If there are no more tasks, then remove the hook thread
       
   100         if (tasks.isEmpty()) {
       
   101             removeHook(hook);
       
   102             hook = null;
       
   103         }
       
   104     }
       
   105 
       
   106     private static void removeHook(final Thread thread) {
       
   107         Log.debug("Removing shutdown-hook: ", thread);
       
   108 
       
   109         try {
       
   110             Runtime.getRuntime().removeShutdownHook(thread);
       
   111         }
       
   112         catch (AbstractMethodError e) {
       
   113             // JDK 1.3+ only method. Bummer.
       
   114             Log.debug("Failed to remove shutdown-hook", e);
       
   115         }
       
   116         catch (IllegalStateException e) {
       
   117             // The VM is shutting down, not a big deal; ignore
       
   118         }
       
   119     }
       
   120 
       
   121     /**
       
   122      * Essentially a {@link Runnable} which allows running to throw an exception.
       
   123      */
       
   124     public static interface Task
       
   125     {
       
   126         void run() throws Exception;
       
   127     }
       
   128 }