package com.rainteen.framework.util.io;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;
/**
* 重定向 System.err/System.out 流的类定义
*
* @author rainteen
* @version 1.0
*/
@SuppressWarnings("all")
public class RedirectOutErr {
private static Map instanceMap = new HashMap();
/**
* 同步锁
*/
private static Boolean locked = new Boolean(false);
private File logFile = null;
private File logFileError = null;
private File logFileOut = null;
private ThreadLocal err = new ThreadLocal();
private ThreadLocal out = new ThreadLocal();
/**
* 构造重定向类对象 将System.err/System.out重定向到同一个日志文件中
* 注:因System.err/System.out是不同线程的I/O操作,不建议重定向到同一个日志中.
*
* @param logFile
* System.err/System.out重定向文件
* @throws FileNotFoundException
*/
// @SuppressWarnings("unchecked")
private RedirectOutErr(final File logFile) {
if (logFile == null) {
throw new IllegalArgumentException("日志文件不能为空.");
}
this.logFile = logFile;
try {
if (!this.logFile.exists()) {
this.logFile.createNewFile();
} else {
if (this.logFile.isDirectory()) {
this.logFile.delete();
this.logFile.createNewFile();
}
}
this.out.set(new PrintStream(new BufferedOutputStream(
new FileOutputStream(this.logFile))));
this.err.set(new PrintStream(new BufferedOutputStream(
new FileOutputStream(this.logFile))));
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
throw new RuntimeException(fnfe.getMessage());
} catch (IOException ioe) {
ioe.printStackTrace();
throw new RuntimeException(ioe.getMessage());
}
}
/**
* 将System.err重定向到 logFileError 文件, 将System.out重定向到 logFileOut 文件
*
* @param logFileError
* System.err重定向文件,错误日志
* @param logFileOut
* System.out重定向文件,输出日志
*/
// @SuppressWarnings("unchecked")
private RedirectOutErr(final File logFileError, final File logFileOut) {
if (logFileError == null && logFileOut == null) {
throw new IllegalArgumentException("日志文件必须指定至少一个.");
}
try {
if (logFileOut != null) {
this.logFileOut = logFileOut;
if (!this.logFileOut.exists())
this.logFileOut.createNewFile();
else if (this.logFileOut.exists()
&& this.logFileOut.isDirectory()) {
this.logFileOut.delete();
this.logFileOut.createNewFile();
}
this.out.set(new PrintStream(new BufferedOutputStream(
new FileOutputStream(this.logFileOut))));
}
if (logFileError != null) {
this.logFileError = logFileError;
if (!this.logFileError.exists())
this.logFileError.createNewFile();
else if (this.logFileError.exists()
&& this.logFileError.isDirectory()) {
this.logFileError.delete();
this.logFileError.createNewFile();
}
this.err.set(new PrintStream(new BufferedOutputStream(
new FileOutputStream(this.logFileError))));
}
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
throw new RuntimeException(fnfe.getMessage());
} catch (IOException ioe) {
ioe.printStackTrace();
throw new RuntimeException(ioe.getMessage());
}
}
/**
* 多例模式工厂方法 获取一个实例 将 System.err/System.out 都定向到该 logFile 文件
* 注:因System.err/System.out是不同线程的I/O操作,不建议重定向到同一个日志中.
*
* @param logFile
* System.err/System.out的重定向文件
* @return
*/
public synchronized static RedirectOutErr getInstance(final File logFile) {
if (logFile == null)
throw new IllegalArgumentException("参数logFile不能为空.");
String logPath = logFile.toString();
RedirectOutErr redirectOutErr = (RedirectOutErr) RedirectOutErr.instanceMap
.get("Both:" + logPath);
if (redirectOutErr == null) {
redirectOutErr = new RedirectOutErr(logFile);
RedirectOutErr.instanceMap.put("Both:" + logPath, redirectOutErr);
}
return redirectOutErr;
}
/**
* 多例模式工厂方法 以 System.err 重定向文件logFileError, System.out 的重定向文件 logFileOut实例化
*
* @param logFileError
* System.err 的重定向文件
* @param logFileOut
* System.out 的重定向文件
* @return
*/
public synchronized static RedirectOutErr getInstance(
final File logFileError, final File logFileOut) {
if (logFileError == null && logFileOut == null)
throw new IllegalArgumentException(
"参数 logFileError|logFileOut 不能全为空.");
String logError = "";
String logOut = "";
if (logFileError != null)
logError = logFileError.toString();
if (logFileOut != null)
logOut = logFileOut.toString();
RedirectOutErr redirectOutErr = (RedirectOutErr) RedirectOutErr.instanceMap
.get("Err:" + logError + "|Out:" + logOut);
if (redirectOutErr == null) {
redirectOutErr = new RedirectOutErr(logFileError, logFileOut);
RedirectOutErr.instanceMap.put(
"Err:" + logError + "|Out:" + logOut, redirectOutErr);
}
return redirectOutErr;
}
public boolean isLocked() {
return locked.booleanValue();
}
/**
* 此处的 synchronized 非常重要,否则会导致死锁
*/
public synchronized void lock() {
this.locked = new Boolean(true);
// locked.set(true);
}
/**
* 此处的 synchronized 非常重要,否则会导致死锁
*/
public synchronized void unlock() {
this.locked = new Boolean(false);
}
/**
* 析构
*/
protected void finalize() throws Throwable {
if (this.out.get() != null)
((PrintStream) this.out.get()).close();
if (this.err.get() != null)
((PrintStream) this.err.get()).close();
this.out = null;
this.err = null;
RedirectOutErr.instanceMap.clear();
RedirectOutErr.instanceMap = null;
this.logFile = null;
this.logFileOut = null;
this.logFileError = null;
super.finalize();
}
/**
* 用于销毁所有实例
*/
public void destory() {
if (this.out.get() != null)
((PrintStream) this.out.get()).close();
if (this.err.get() != null)
((PrintStream) this.err.get()).close();
this.out = null;
this.err = null;
RedirectOutErr.instanceMap.clear();
RedirectOutErr.instanceMap = null;
this.logFile = null;
this.logFileOut = null;
this.logFileError = null;
System.gc();
}
/**
* 开启重定向, 只有已经为实例指定了对应文件的情况下才有效.
*/
public RedirectOutErr onRedirect() {
synchronized (this.locked) {
while (true) {
try {
if (!this.isLocked()) {
this.lock();
if (this.err.get() != null)
System.setErr(((PrintStream) this.err.get()));
this.unlock();
this.locked.notify();
break;
} else {
this.locked.wait();
}
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
while (true) {
try {
if (!this.isLocked()) {
this.lock();
if (this.out.get() != null) {
System.setOut(((PrintStream) this.out.get()));
}
this.unlock();
this.locked.notify();
break;
} else {
this.locked.wait();
}
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
return this;
}
/**
* 关闭重定向, 恢复System.err/System.out的原有行为特性
*/
public RedirectOutErr offRedirect() {
synchronized (this.locked) {
while (true) {
try {
if (!this.isLocked()) {
FileOutputStream fdErr = new FileOutputStream(
FileDescriptor.err);
this.lock();
// synchronized (this.locked) {
System.setErr(new PrintStream(new BufferedOutputStream(
fdErr, 128), true));
// }
this.unlock();
this.locked.notify();
break;
} else {
this.locked.wait();
}
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
while (true) {
try {
if (!this.isLocked()) {
FileOutputStream fdOut = new FileOutputStream(
FileDescriptor.out);
this.lock();
// synchronized (this.locked) {
System.setOut(new PrintStream(new BufferedOutputStream(
fdOut, 128), true));
// }
this.unlock();
this.locked.notify();
break;
} else {
this.locked.wait();
}
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
return this;
}
/**
* 开启System.out的重定向
*/
public RedirectOutErr onRedirectOut() {
if (this.out.get() == null)
throw new IllegalStateException("没有为System.out指定重定向文件");
synchronized (this.locked) {
while (true) {
try {
if (!this.isLocked()) {
this.lock();
System.setOut(((PrintStream) this.out.get()));
this.unlock();
this.locked.notify();
break;
} else {
this.locked.wait();
}
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
return this;
}
/**
* 关闭System.out的重定向
*/
public RedirectOutErr offRedirectOut() {
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
synchronized (this.locked) {
while (true) {
try {
if (!this.isLocked()) {
this.lock();
System.setOut(new PrintStream(new BufferedOutputStream(
fdOut, 128), true));
this.unlock();
this.locked.notify();
break;
} else {
this.locked.wait();
}
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
return this;
}
/**
* 开启System.err的重定向
*/
public RedirectOutErr onRedirectError() {
if (this.err.get() == null)
throw new IllegalStateException("没有为System.err指定重定向文件");
synchronized (this.locked) {
while (true) {
try {
if (!this.isLocked()) {
this.lock();
System.setErr(((PrintStream) this.err.get()));
this.unlock();
this.locked.notify();
break;
} else {
this.locked.wait();
}
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
return this;
}
/**
* 关闭System.err的重定向
*/
public RedirectOutErr offRedirectError() {
FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
synchronized (this.locked) {
while (true) {
try {
if (!this.isLocked()) {
this.lock();
System.setErr(new PrintStream(new BufferedOutputStream(
fdErr, 128), true));
this.unlock();
this.locked.notify();
break;
} else {
this.locked.wait();
}
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
return this;
}
public static void main(String[] args) {
}
}