package jane.core;
import java.io.IOException;
import java.util.ArrayList;
/**
* 全局唯一的退出处理管理器
*/
public final class ExitManager
{
private static final ArrayList<Runnable> _shutdownUserCallbacks = new ArrayList<>(); // 退出时的用户回调列表
private static final ArrayList<Runnable> _shutdownSystemCallbacks = new ArrayList<>(); // 退出时的系统回调列表
static
{
Runtime.getRuntime().addShutdownHook(new Thread("ExitHook")
{
@Override
public void run()
{
try
{
Log.log.info("ExitManager: shutdown begin");
for(Runnable r : _shutdownUserCallbacks)
{
try
{
r.run();
}
catch(Throwable e)
{
Log.log.error("ExitManager: user callback exception:", e);
}
}
_shutdownUserCallbacks.clear();
for(Runnable r : _shutdownSystemCallbacks)
{
try
{
r.run();
}
catch(Throwable e)
{
Log.log.error("ExitManager: system callback exception:", e);
}
}
_shutdownSystemCallbacks.clear();
}
catch(Throwable e)
{
Log.log.error("ExitManager: fatal exception:", e);
}
finally
{
Log.shutdown();
}
}
});
}
/**
* 获取进程退出前的回调列表(shutdown之前可修改)
* <p>
* 在关闭数据库前按顺序调用,每次回调的异常会记录日志并忽略
*/
public static ArrayList<Runnable> getShutdownUserCallbacks()
{
return _shutdownUserCallbacks;
}
static ArrayList<Runnable> getShutdownSystemCallbacks()
{
return _shutdownSystemCallbacks;
}
/**
* 线程挂起并一直读标准输入. 遇到一行标准输入以"!@#$"开头则退出程序
* <p>
* 适合在Eclipse等IDE运行环境下正常退出而不是强制结束进程
*/
public static void waitStdInToExit() throws IOException
{
for(byte[] inbuf = new byte[4];;)
{
int n;
IOException ex = null;
try
{
n = System.in.read(inbuf);
}
catch(IOException e)
{
n = -1;
ex = e;
}
if(n < 0)
{
System.err.println("!!!STDIN TRIGGER DISABLED!!! (" + n + (ex != null ? ", " + ex.getMessage() : "") + ')');
return;
}
if(n == 4 && inbuf[0] == '!' && inbuf[1] == '@' && inbuf[2] == '#' && inbuf[3] == '$')
{
System.err.println("!!!STDIN TRIGGERED EXIT!!!");
System.exit(1);
}
System.in.skip(Integer.MAX_VALUE); // 尽可能忽略行后的内容. 但传入Long.MAX_VALUE可能导致IOException
}
}
private ExitManager()
{
}
}