52040496371e17e1b18550382a7a5720840a9762
[jabaws.git] / engine / compbio / engine / local / _TrackingExecutor.java
1 /* Copyright (c) 2009 Peter Troshin\r
2  *  \r
3  *  JAva Bioinformatics Analysis Web Services (JABAWS) @version: 1.0     \r
4  * \r
5  *  This library is free software; you can redistribute it and/or modify it under the terms of the\r
6  *  Apache License version 2 as published by the Apache Software Foundation\r
7  * \r
8  *  This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r
9  *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Apache \r
10  *  License for more details.\r
11  * \r
12  *  A copy of the license is in apache_license.txt. It is also available here:\r
13  * @see: http://www.apache.org/licenses/LICENSE-2.0.txt\r
14  * \r
15  * Any republication or derived work distributed in source code form\r
16  * must include this copyright and license notice.\r
17  */\r
18 package compbio.engine.local;\r
19 \r
20 import java.util.ArrayList;\r
21 import java.util.HashSet;\r
22 import java.util.List;\r
23 import java.util.Set;\r
24 import java.util.concurrent.AbstractExecutorService;\r
25 import java.util.concurrent.Callable;\r
26 import java.util.concurrent.ExecutorService;\r
27 import java.util.concurrent.Future;\r
28 import java.util.concurrent.TimeUnit;\r
29 \r
30 /**\r
31  * This executor extends standard Java ExecutorService by adding the method to\r
32  * obtain all Runnables which were running and did not complete upon executor\r
33  * termination. For this to work properly Runnables must propagate an\r
34  * Interruption exceptions, not swallow them, which a good Runnable should do\r
35  * anyway.\r
36  * \r
37  * TODO it may be better to persists task from different place\r
38  * \r
39  * @author pvtroshin\r
40  * @Date October 2009\r
41  */\r
42 public class _TrackingExecutor extends AbstractExecutorService {\r
43 \r
44         private final ExecutorService executor;\r
45 \r
46         public _TrackingExecutor(ExecutorService executor) {\r
47                 this.executor = executor;\r
48         }\r
49 \r
50         private final Set<Runnable> cancelledRunnableTasksAtShutdown = new HashSet<Runnable>();\r
51         private final Set<Callable<?>> cancelledCallableTasksAtShutdown = new HashSet<Callable<?>>();\r
52 \r
53         public List getCancelledTasks() {\r
54                 if (!executor.isTerminated()) {\r
55                         throw new IllegalStateException(\r
56                                         "Executor must be terminated before running this method!");\r
57                 }\r
58                 ArrayList tasks = new ArrayList(cancelledCallableTasksAtShutdown);\r
59                 tasks.addAll(cancelledRunnableTasksAtShutdown);\r
60                 return tasks;\r
61         }\r
62 \r
63         @Override\r
64         public void execute(final Runnable runnable) {\r
65                 executor.execute(new Runnable() {\r
66                         @Override\r
67                         public void run() {\r
68                                 try {\r
69                                         runnable.run();\r
70                                 } finally {\r
71                                         if (isShutdown() && Thread.currentThread().isInterrupted()) {\r
72                                                 cancelledRunnableTasksAtShutdown.add(runnable);\r
73                                         }\r
74                                 }\r
75                         }\r
76                 });\r
77         }\r
78 \r
79         @Override\r
80         public <T> Future<T> submit(final Callable<T> task) {\r
81                 return executor.submit(new Callable<T>() {\r
82                         @Override\r
83                         public T call() throws Exception {\r
84                                 try {\r
85                                         return task.call();\r
86                                 } finally {\r
87                                         if (isShutdown() && Thread.currentThread().isInterrupted()) {\r
88                                                 cancelledCallableTasksAtShutdown.add(task);\r
89                                         }\r
90                                 }\r
91                         }\r
92                 });\r
93         }\r
94 \r
95         @Override\r
96         public boolean awaitTermination(long timeout, TimeUnit unit)\r
97                         throws InterruptedException {\r
98                 return executor.awaitTermination(timeout, unit);\r
99         }\r
100 \r
101         @Override\r
102         public boolean isShutdown() {\r
103                 return executor.isShutdown();\r
104         }\r
105 \r
106         @Override\r
107         public boolean isTerminated() {\r
108                 return executor.isTerminated();\r
109         }\r
110 \r
111         @Override\r
112         public void shutdown() {\r
113                 executor.shutdown();\r
114         }\r
115 \r
116         @Override\r
117         public List<Runnable> shutdownNow() {\r
118                 return executor.shutdownNow();\r
119         }\r
120 \r
121 }\r