package ch.marcsladek.yajlf;
import java.awt.Desktop;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
class LogWriter implements Serializable {
private static final long serialVersionUID = 201209151752L;
private static final SimpleDateFormat dateFormat = new SimpleDateFormat(
"dd.MM.yy HH:mm:ss");
private static final String newLine = System.getProperty("line.separator");
private final String path;
private String stampMsg;
private String sep;
private boolean enabled, timestamp, prtToStdOut;
private ErrorLevel errLvl;
private transient PrintWriter pw;
private LogWriter(String path, boolean timestamp, boolean prtToStdOut, String stampMsg,
ErrorLevel errLvl) throws IOException {
this.path = path;
this.timestamp = timestamp;
this.prtToStdOut = prtToStdOut;
this.stampMsg = stampMsg;
this.errLvl = errLvl;
this.enabled = true;
this.sep = " - ";
this.reload();
}
/**
* @param path
* log file path - if is null, doesn't print to file
* @param timestamp
* adds timestamp to log entry
* @param prtToStdOut
* prints log message to stdout
* @param stampMsg
* adds this message to every log entry
* @param errLvl
* @return new instance of Log
* @throws IOException
* if file cannot be opened
*/
static LogWriter getInstance(String path, boolean timestamp, boolean prtToStdOut,
String stampMsg, ErrorLevel errLvl) throws IOException {
return new LogWriter(path, timestamp, prtToStdOut, stampMsg, errLvl);
}
/**
* @param path
* log file path - if is null, doesn't print to file
* @param errLvl
* @return new instance of Log
* @throws IOException
* if file cannot be opened
*/
static LogWriter getInstance(String path, ErrorLevel errLvl) throws IOException {
return new LogWriter(path, true, true, null, errLvl);
}
String getPath() {
return this.path;
}
synchronized String getStampMsg() {
return this.stampMsg;
}
synchronized boolean isEnabled() {
return this.enabled;
}
synchronized boolean doesTimeStamp() {
return this.timestamp;
}
synchronized boolean doesPrtToStdOut() {
return this.prtToStdOut;
}
boolean doesPrtToFile() {
return this.path == null;
}
synchronized ErrorLevel getErrorLevel() {
return this.errLvl;
}
synchronized void setStampMsg(String stampMsg) {
this.stampMsg = stampMsg;
}
synchronized void enable() {
this.enabled = true;
}
synchronized void disable() {
this.enabled = false;
}
synchronized void setTimeStamp(boolean timestamp) {
this.timestamp = timestamp;
}
synchronized void setPrtToStdOut(boolean prtToStdOut) {
this.prtToStdOut = prtToStdOut;
}
synchronized void setErrorLevel(ErrorLevel errLvl) {
this.errLvl = errLvl;
}
synchronized void setSeparator(String sep) {
this.sep = sep;
}
synchronized void reload() throws IOException {
this.close();
if (path != null) {
File file = new File(this.path);
if (file.getParentFile() != null) {
file.getParentFile().mkdirs();
}
this.pw = new PrintWriter(new FileWriter(file, true));
} else {
this.pw = null;
}
}
synchronized void close() {
if (pw != null) {
this.pw.close();
}
}
void trace(String msg) {
logToStd(msg, ErrorLevel.TRACE);
}
void trace(String msg, Throwable exc) {
logExc(msg, ErrorLevel.TRACE, exc);
}
void debug(String msg) {
logToStd(msg, ErrorLevel.DEBUG);
}
void debug(String msg, Throwable exc) {
logExc(msg, ErrorLevel.DEBUG, exc);
}
void info(String msg) {
logToStd(msg, ErrorLevel.INFO);
}
void info(String msg, Throwable exc) {
logExc(msg, ErrorLevel.INFO, exc);
}
void warn(String msg) {
logToStd(msg, ErrorLevel.WARN);
}
void warn(String msg, Throwable exc) {
logExc(msg, ErrorLevel.WARN, exc);
}
void error(String msg) {
logToErr(msg, ErrorLevel.ERROR);
}
void error(String msg, Throwable exc) {
logExc(msg, ErrorLevel.ERROR, exc);
}
void fatal(String msg) {
logToErr(msg, ErrorLevel.FATAL);
}
void fatal(String msg, Throwable exc) {
logExc(msg, ErrorLevel.FATAL, exc);
}
private void logToStd(String msg, ErrorLevel lvl) {
log(msg, lvl, false, null);
}
private void logToErr(String msg, ErrorLevel lvl) {
log(msg, lvl, true, null);
}
private void logExc(String msg, ErrorLevel lvl, Throwable exc) {
log(msg, lvl, true, exc);
}
private synchronized void log(String msg, ErrorLevel lvl, boolean prtToStdErr,
Throwable exc) {
if (doLog(msg, lvl)) {
String logEntry = buildLogEntry(msg, lvl, exc);
if (prtToStdOut) {
if (!prtToStdErr) {
System.out.print(logEntry);
} else {
System.err.print(logEntry);
}
}
if (pw != null) {
pw.write(logEntry);
pw.flush();
}
}
}
private boolean doLog(String msg, ErrorLevel lvl) {
return enabled && (msg.length() > 0) && lvl.isLvl(errLvl)
&& (prtToStdOut || (path != null));
}
private String buildLogEntry(String msg, ErrorLevel lvl, Throwable exc) {
StringBuilder sb = new StringBuilder();
if (timestamp) {
sb.append(dateFormat.format(new Date()));
sb.append(sep);
}
if ((stampMsg != null) && (!stampMsg.equals(""))) {
sb.append(stampMsg);
sb.append(sep);
}
if (lvl != null) {
sb.append(lvl);
sb.append(sep);
}
sb.append(msg);
sb.append(newLine);
if (exc != null) {
sb.append(buildStackTrace(exc));
}
return sb.toString();
}
private String buildStackTrace(Throwable exc) {
StringWriter sw = new StringWriter();
exc.printStackTrace(new PrintWriter(sw));
return sw.toString();
}
/**
* Opens the log in std file
*
* @return success to access Desktop.Action.OPEN
* @throws IOException
* @throws IllegalArgumentException
*/
boolean open() throws IOException, IllegalArgumentException {
if ((path != null) && Desktop.isDesktopSupported()) {
Desktop desktop = Desktop.getDesktop();
if (desktop.isSupported(Desktop.Action.OPEN)) {
desktop.open(new File(path));
return true;
}
}
return false;
}
@Override
public String toString() {
return "Log " + errLvl + ": " + path;
}
}