1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package net.sourceforge.acelogger.execution;
16
17 import java.lang.Thread.UncaughtExceptionHandler;
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.concurrent.atomic.AtomicBoolean;
21
22 import net.sourceforge.acelogger.GenericLogger;
23 import net.sourceforge.acelogger.Logger;
24 import net.sourceforge.acelogger.appender.Appender;
25 import net.sourceforge.acelogger.appender.SystemErrAppender;
26 import net.sourceforge.acelogger.constants.LevelFilterConstants;
27 import net.sourceforge.acelogger.execution.manager.ExecutorManager;
28 import net.sourceforge.acelogger.execution.manager.PooledExecutorManager;
29 import net.sourceforge.acelogger.execution.manager.QueuedExecutorManager;
30 import net.sourceforge.acelogger.execution.task.MonitorableTask;
31 import net.sourceforge.acelogger.execution.task.NotifiableTask;
32 import net.sourceforge.acelogger.factory.ExecutorManagerFactory;
33 import net.sourceforge.acelogger.factory.LoggerFactory;
34 import net.sourceforge.acelogger.formatter.Formatter;
35 import net.sourceforge.acelogger.formatter.SimpleFormatter;
36 import net.sourceforge.acelogger.level.filter.LevelFilter;
37 import net.sourceforge.acelogger.location.gatherer.FullLocationGatherer;
38 import net.sourceforge.acelogger.location.gatherer.LocationGatherer;
39 import net.sourceforge.acelogger.location.resolver.InternalCodeFrameResolver;
40
41
42
43
44
45
46
47
48
49 public final class LogController {
50
51 private static final int DEFAULT_POOL_SIZE = 3;
52
53 private static final long SETUP_TIMEOUT = 10000;
54
55 private static final long TERMINATION_TIMEOUT = 10000;
56
57 private static final LogController INSTANCE = new LogController();
58
59 private List<Runnable> commandsBeforeShutdown;
60
61 private ExecutorManager backgroundExecutor;
62
63 private ExecutorManager shutdownExecutor;
64
65 private Logger internalLogger;
66
67 private AtomicBoolean initialized;
68
69 private AtomicBoolean waitingBootstrap;
70
71 private Thread shutdownHook = new Thread(new Runnable() {
72 public void run() {
73 internalLogger = new InternalLogger();
74 shutdownExecutor.executeAll(commandsBeforeShutdown);
75 shutdownExecutor.orderProperShutdown();
76 shutdownExecutor.awaitTermination(TERMINATION_TIMEOUT);
77 boolean terminatedAllTasks = ExecutorManagerFactory.doProperExecutorManagersShutdown();
78 if (!terminatedAllTasks) {
79 try {
80 terminatedAllTasks = ExecutorManagerFactory
81 .awaitExecutorManagersShutdown(TERMINATION_TIMEOUT);
82 } catch (TerminationException e) {
83 e.printStackTrace(System.err);
84 }
85 if (!terminatedAllTasks) {
86
87 }
88 }
89 backgroundExecutor.orderProperShutdown();
90 backgroundExecutor.awaitTermination(TERMINATION_TIMEOUT);
91 }
92 });
93
94 private MonitorableTask finalizeBootstrap = new MonitorableTask(new Runnable() {
95 public void run() {
96 try {
97 submitBackgroundTask(new Runnable() {
98 public void run() {
99 internalLogger = LoggerFactory.getLogger("net.sourceforge.acelogger");
100 initialized.set(true);
101 }
102 });
103 } catch (Exception e) {
104
105 shutdownHook.start();
106 }
107 }
108 });
109
110 private Runnable setup = new NotifiableTask(new Runnable() {
111 public void run() {
112 LoggerFactory.registerLogger(internalLogger);
113 internalLogger.info("LogControlle.setupComplete");
114 }
115 }, finalizeBootstrap);
116
117 private LogController() {
118 internalLogger = new InternalLogger();
119 Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionLogger.getInstance());
120 Runtime.getRuntime().addShutdownHook(shutdownHook);
121 backgroundExecutor = new QueuedExecutorManager("background");
122 shutdownExecutor = new PooledExecutorManager("commandsBeforeShutdown", DEFAULT_POOL_SIZE);
123 commandsBeforeShutdown = new ArrayList<Runnable>();
124 initialized = new AtomicBoolean(false);
125 waitingBootstrap = new AtomicBoolean(true);
126 backgroundExecutor.execute(setup);
127 }
128
129 public static void submitBackgroundTask(Runnable command) {
130 INSTANCE.backgroundExecutor.execute(command);
131 }
132
133 public static void submitBackgroundTask(final Runnable command, final ExecutorManager executor) {
134 final Runnable process = new Runnable() {
135 public void run() {
136 executor.execute(command);
137 }
138 };
139 submitBackgroundTask(process);
140 }
141
142 public static void submitShutdownTask(Runnable command) {
143 INSTANCE.commandsBeforeShutdown.add(command);
144 }
145
146 public static void submitShutdownTask(final Runnable command, final ExecutorManager executor) {
147 final Runnable process = new Runnable() {
148 public void run() {
149 executor.execute(command);
150 }
151 };
152 submitShutdownTask(process);
153 }
154
155 public static void ensureInitialization() {
156 if (!INSTANCE.initialized.get() && INSTANCE.waitingBootstrap.get()) {
157 try {
158 if (INSTANCE.waitingBootstrap.compareAndSet(true, false)) {
159 INSTANCE.finalizeBootstrap.awaitTermination(SETUP_TIMEOUT);
160 }
161 } catch (final InterruptedException e) {
162 INSTANCE.internalLogger.fatal("Could not initialize after {0} ms", SETUP_TIMEOUT);
163 }
164 }
165 }
166
167 public static Logger getInternalLogger() {
168 return INSTANCE.internalLogger;
169 }
170
171 }