/*
* Copyright 2008-2013, ETH Zürich, Samuel Welten, Michael Kuhn, Tobias Langner,
* Sandro Affentranger, Lukas Bossard, Michael Grob, Rahul Jain,
* Dominic Langenegger, Sonia Mayor Alonso, Roger Odermatt, Tobias Schlueter,
* Yannick Stucki, Sebastian Wendland, Samuel Zehnder, Samuel Zihlmann,
* Samuel Zweifel
*
* This file is part of Jukefox.
*
* Jukefox is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or any later version. Jukefox is
* distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Jukefox. If not, see <http://www.gnu.org/licenses/>.
*/
package ch.ethz.dcg.jukefox.commons.utils;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import ch.ethz.dcg.jukefox.manager.ModelSettingsManager;
public class Log {
public enum LogLevel {
VERBOSE(2), DEBUG(3), INFO(4), WARN(5), ERROR(6), ASSERT(7);
private final int value;
LogLevel(int value) {
this.value = value;
}
public final int value() {
return value;
}
public static final LogLevel byValue(int value) {
switch (value) {
case 2:
return LogLevel.VERBOSE;
case 3:
return LogLevel.DEBUG;
case 4:
return LogLevel.INFO;
case 5:
return LogLevel.WARN;
case 6:
return LogLevel.ERROR;
case 7:
return LogLevel.ASSERT;
default:
return LogLevel.VERBOSE;
}
}
}
private static long lastLogFileCheckTime = 0;
public static final int LOG_FILE_CHECK_INTERVALL = 1000 * 60 * 60; // Millisecods
public static final int MAX_LOG_FILE_LENGTH = 150 * 1000; // Size in bytes
private static final String TAG = Log.class.getSimpleName();
public static int currentLogFileNr = getCurrentLogFileNr();
private static String logFileBasePath = null;
private static ModelSettingsManager modelSettingsManager = null;
private static ILogPrinter logPrinter = null;
// don't change this value. It is changed as soon
private static boolean logToFile = false;
private static SimpleDateFormat format = new SimpleDateFormat("dd.MM.yy hh:mm:ss");
private static LogLevel logLevel = LogLevel.VERBOSE;
public static void createLogPrinter(ILogPrinter logPrinter) {
Log.logPrinter = logPrinter;
}
public static void setLogLevel(LogLevel logLevel) {
Log.logLevel = logLevel;
}
public static void setModelSettingsManager(ModelSettingsManager modelSettingsManager) {
Log.modelSettingsManager = modelSettingsManager;
logToFile = modelSettingsManager.isLogFileEnabled();
}
public static void setLogFileBasePath(String path) {
logFileBasePath = path;
}
private static void createDefaultLogPrinter() {
createLogPrinter(new SystemOutLogPrinter());
}
public static void setLogToFile(boolean logToFile) {
Log.logToFile = logToFile;
}
private static int getCurrentLogFileNr() {
if (modelSettingsManager == null) {
return 1;
}
return modelSettingsManager.getCurrentLogFileNumber();
}
private static String getCurrentTimeFormatted() {
long time = System.currentTimeMillis();
return format.format(new Date(time)) + "; " + time;
}
public static void d(String tag, String msg) {
if (logPrinter == null) {
createDefaultLogPrinter();
}
if (msg == null) {
return;
}
if (logToFile || logLevel.value() <= LogLevel.DEBUG.value()) {
logPrinter.printDebug(tag, msg);
}
if (logToFile) {
writeToLogFile(getCurrentTimeFormatted() + "; D; " + tag, msg);
}
}
public static void v(String tag, String msg) {
if (logPrinter == null) {
createDefaultLogPrinter();
}
if (msg == null) {
return;
}
// android.util.Log.v(TAG, "logToFile: " + logToFile + ", LOG_LEVEL: " +
// LOG_LEVEL + ", verbose-level: " + android.util.Log.VERBOSE);
if (logToFile || logLevel.value() <= LogLevel.VERBOSE.value()) {
logPrinter.printVerbose(tag, msg);
}
if (logToFile) {
writeToLogFile(getCurrentTimeFormatted() + "; V; " + tag, msg);
}
}
public static void w(String tag, String msg) {
if (logPrinter == null) {
createDefaultLogPrinter();
}
if (msg == null) {
return;
}
if (logToFile || logLevel.value() <= LogLevel.WARN.value()) {
logPrinter.printWarning(tag, msg);
}
if (logToFile) {
writeToLogFile(getCurrentTimeFormatted() + "; W; " + tag, msg);
}
}
public static void w(String tag, Exception e) {
if (logPrinter == null) {
createDefaultLogPrinter();
}
if (e == null) {
return;
}
if (logToFile || logLevel.value() <= LogLevel.WARN.value()) {
logPrinter.printWarning(tag, getStackTraceString(e));
}
if (logToFile) {
writeToLogFile(getCurrentTimeFormatted() + "; W; " + tag, e);
}
}
public static void w(String tag, Throwable e) {
if (logPrinter == null) {
createDefaultLogPrinter();
}
if (e == null) {
return;
}
if (logToFile || logLevel.value() <= LogLevel.WARN.value()) {
logPrinter.printWarning(tag, getStackTraceString(e));
}
if (logToFile) {
writeToLogFile(getCurrentTimeFormatted() + "; W; " + tag, e);
}
}
public static void w(String tag, Error e) {
if (logPrinter == null) {
createDefaultLogPrinter();
}
if (e == null) {
return;
}
if (logToFile || logLevel.value() <= LogLevel.WARN.value()) {
logPrinter.printWarning(tag, getStackTraceString(e));
}
if (logToFile) {
writeToLogFile(getCurrentTimeFormatted() + "; W; " + tag, e);
}
}
public static void e(String tag, String msg) {
if (logPrinter == null) {
createDefaultLogPrinter();
}
if (msg == null) {
return;
}
if (logToFile || logLevel.value() <= LogLevel.ERROR.value()) {
logPrinter.printError(tag, msg);
}
if (logToFile) {
writeToLogFile(getCurrentTimeFormatted() + "; E; " + tag, msg);
}
}
public static void i(String tag, String msg) {
if (logPrinter == null) {
createDefaultLogPrinter();
}
if (msg == null) {
return;
}
if (logToFile || logLevel.value() <= LogLevel.INFO.value()) {
logPrinter.printInfo(tag, msg);
}
if (logToFile) {
writeToLogFile(getCurrentTimeFormatted() + "; I; " + tag, msg);
}
}
public static void wtf(String tag, Exception e) {
if (logPrinter == null) {
createDefaultLogPrinter();
}
// TODO: send back to server?
if (e == null) {
return;
}
if (logToFile || logLevel.value() <= LogLevel.ERROR.value()) {
logPrinter.printAssert(tag, getStackTraceString(e));
}
if (logToFile) {
writeToLogFile(getCurrentTimeFormatted() + "; WTF; " + tag, e);
}
}
public static void writeExceptionToErrorFile(String tag, String msg, Exception e) {
DataOutputStream dout = null;
try {
File f = getLogFile(currentLogFileNr);
// Check if we have a valid log file path
if (f == null) {
return;
}
dout = getOutputStream(f);
dout.writeBytes(tag + "; ");
dout.writeBytes("msg: " + msg + "\n");
for (StackTraceElement el : e.getStackTrace()) {
dout.writeBytes(el.getFileName() + "(" + el.getClassName() + "." + el.getMethodName() + " (): "
+ el.getLineNumber() + ")");
}
PrintStream pr = new PrintStream(dout);
e.printStackTrace(pr);
} catch (Exception e2) {
System.out.println("Jukefox Error Log: " + "\n" + getStackTraceString(e2));
} finally {
try {
if (dout != null) {
dout.close();
}
} catch (Exception e3) {
System.out.println("Jukefox Error Log: " + "\n" + getStackTraceString(e3));
}
}
}
private static void writeToLogFile(String tag, String msg) {
DataOutputStream dout = null;
try {
File f = getLogFile(currentLogFileNr);
// Check if we have a valid log file path
if (f == null) {
return;
}
dout = getOutputStream(f);
dout.writeBytes(tag + "; ");
dout.writeBytes(msg + "\n");
} catch (Exception e2) {
System.out.println("Jukefox LogCat: " + "\n" + getStackTraceString(e2));
} finally {
try {
if (dout != null) {
dout.close();
}
if (System.currentTimeMillis() - lastLogFileCheckTime > LOG_FILE_CHECK_INTERVALL) {
checkLogFile();
}
} catch (Exception e3) {
Log.w("Jukefox LogCat", e3);
}
;
}
}
// private static void writeToLogFile(String tag, Exception e) {
// DataOutputStream dout = null;
// try {
// dout = getOutputStream(getLogFileName());
// dout.writeBytes(tag + "\n");
// dout.writeBytes("msg: " + e.getMessage() + "\n");
// PrintStream pr = new PrintStream(dout);
// e.printStackTrace(pr);
// } catch (Exception e2) {
// android.util.Log.w("Jukefox LogCat", e2);
// } finally {
// try {
// if (dout != null) {
// dout.close();
// }
// if (System.currentTimeMillis() - lastLogFileCheckTime >
// LOG_FILE_CHECK_INTERVALL) {
// checkLogFile();
// }
// } catch (Exception e3) {
// android.util.Log.w("Jukefox LogCat", e3);
// }
// ;
// }
// }
//
// private static void writeToLogFile(String tag, Error e) {
// DataOutputStream dout = null;
// try {
// dout = getOutputStream(getLogFileName());
// dout.writeBytes(tag + "\n");
// dout.writeBytes("msg: " + e.getMessage() + "\n");
// PrintStream pr = new PrintStream(dout);
// e.printStackTrace(pr);
// } catch (Exception e2) {
// android.util.Log.w("Jukefox LogCat", e2);
// } finally {
// try {
// if (dout != null) {
// dout.close();
// }
// if (System.currentTimeMillis() - lastLogFileCheckTime >
// LOG_FILE_CHECK_INTERVALL) {
// checkLogFile();
// }
// } catch (Exception e3) {
// android.util.Log.w("Jukefox LogCat", e3);
// }
// }
// }
private static void writeToLogFile(String tag, Throwable e) {
DataOutputStream dout = null;
try {
File f = getLogFile(currentLogFileNr);
// Check if we have a valid log file path
if (f == null) {
return;
}
dout = getOutputStream(f);
dout.writeBytes(tag + "; ");
dout.writeBytes("msg: " + e.getMessage() + "\n");
PrintStream pr = new PrintStream(dout);
e.printStackTrace(pr);
} catch (Exception e2) {
System.out.println("Jukefox LogCat: " + "\n" + getStackTraceString(e2));
} finally {
try {
if (dout != null) {
dout.close();
}
if (System.currentTimeMillis() - lastLogFileCheckTime > LOG_FILE_CHECK_INTERVALL) {
checkLogFile();
}
} catch (Exception e3) {
System.out.println("Jukefox LogCat: " + "\n" + getStackTraceString(e3));
}
;
}
}
private synchronized static void checkLogFile() {
lastLogFileCheckTime = System.currentTimeMillis();
File f = getLogFile(currentLogFileNr);
if (f == null) {
return;
}
if (f.length() > MAX_LOG_FILE_LENGTH) {
int nextLogFileNr = currentLogFileNr == 1 ? 2 : 1;
// FIXME: neu im Directorymanager machen!
File f2 = getLogFile(nextLogFileNr);
if (f2 != null) {
if (!f2.delete()) {
Log.w(TAG, "Could not delete Log file!: " + f2.getAbsolutePath());
}
}
Log.setCurrentLogFileNumber(nextLogFileNr);
// FIXME: neu im Directorymanager machen!
createNewLogFile(getLogFile(nextLogFileNr));
}
}
private static void createNewLogFile(File file) {
writeToLogFile("Log", "Start time: " + System.currentTimeMillis());
String settings = "";
if (modelSettingsManager != null) {
settings = modelSettingsManager.getLogString();
}
try {
// writeToLogFile(TAG, "Jukefox version: " +
// AndroidUtils.getVersionName());
// writeToLogFile(TAG, "Android version: " +
// AndroidUtils.getAndroidVersionName());
// writeToLogFile(TAG, "Phone model: " + AndroidUtils.getModel());
writeToLogFile(TAG, settings);
} catch (Throwable t) {
Log.w(TAG, t);
}
}
private static DataOutputStream getOutputStream(File logCat) throws FileNotFoundException {
DataOutputStream dout;
FileOutputStream fout = new FileOutputStream(logCat, true);
dout = new DataOutputStream(fout);
return dout;
}
private static File getLogFile(int nr) {
// FIXME: neu im Directorymanager machen!
if (logFileBasePath == null) {
return null;
}
return new File(logFileBasePath + nr + ".txt");
}
private static void setCurrentLogFileNumber(int newLogFileNumber) {
currentLogFileNr = newLogFileNumber;
if (modelSettingsManager == null) {
return;
}
modelSettingsManager.setCurrentLogFileNumber(currentLogFileNr);
}
public static void printStackTrace(String tag, StackTraceElement[] stackTrace) {
if (modelSettingsManager == null || !modelSettingsManager.isLogFileEnabled()) {
return;
}
StringBuilder sb = new StringBuilder();
for (StackTraceElement el : stackTrace) {
sb.append("--- " + el.getFileName() + "(" + el.getClassName() + "." + el.getMethodName() + " (): "
+ el.getLineNumber() + ")\n");
}
Log.v(tag, sb.toString());
}
private static String getStackTraceString(Throwable tr) {
if (tr == null) {
return "";
}
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
tr.printStackTrace(pw);
return sw.toString();
}
}