1
2
3
4
5
6
7
8
9 package jline.internal;
10
11 import java.util.ArrayList;
12 import java.util.List;
13
14 import static jline.internal.Preconditions.checkNotNull;
15
16
17
18
19
20
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
36 if (!enabled) {
37 Log.debug("Shutdown-hook is disabled; not installing: ", task);
38 return task;
39 }
40
41
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
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
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
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
92 if (!enabled || hook == null) {
93 return;
94 }
95
96
97 tasks.remove(task);
98
99
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
114 Log.debug("Failed to remove shutdown-hook", e);
115 }
116 catch (IllegalStateException e) {
117
118 }
119 }
120
121
122
123
124 public static interface Task
125 {
126 void run() throws Exception;
127 }
128 }