/**
* BlueCove - Java library for Bluetooth
* Copyright (C) 2006-2009 Vlad Skarzhevskyy
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @author vlads
* @version $Id$
*/
package com.intel.bluetooth;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.Vector;
/**
* BlueCove log system.
*
* If enabled "-Dbluecove.debug=true" System.out.println would be used for debug. Alternatively if log4j is available in
* classpath Bluecove log would be redirected to log4j and can be enable using log4j configuration.
*
* The methods of this class would be removed automaticaly because they are empty if debugCompiledOut = true. This class
* itself will disappear from bytecode after obfuscation by proguard in this case. Change to create mini jar.
*
*/
public abstract class DebugLog {
private static final boolean debugCompiledOut = false;
public final static int DEBUG = 1;
public final static int ERROR = 4;
private static boolean debugEnabled = false;
private static boolean initialized = false;
private static boolean debugInternalEnabled = false;
private static final String FQCN = DebugLog.class.getName();
private static final Vector fqcnSet = new Vector();
private static boolean java13 = false;
private static Vector loggerAppenders = new Vector();
/**
* Different log system can be injected in BlueCove using DebugLog.addAppender(customLoggerAppender)
*
*/
public static interface LoggerAppender {
public void appendLog(int level, String message, Throwable throwable);
}
public static interface LoggerAppenderExt extends LoggerAppender {
public boolean isLogEnabled(int level);
}
static {
fqcnSet.addElement(FQCN);
}
private DebugLog() {
}
private synchronized static void initialize() {
if (initialized) {
return;
}
initialized = true;
debugEnabled = BlueCoveImpl.getConfigProperty(BlueCoveConfigProperties.PROPERTY_DEBUG, false);
if (debugEnabled && debugCompiledOut) {
debugEnabled = false;
System.err.println("BlueCove debug functions have been Compiled Out");
}
boolean useStdOut = BlueCoveImpl.getConfigProperty(BlueCoveConfigProperties.PROPERTY_DEBUG_STDOUT, true);
debugInternalEnabled = useStdOut && debugEnabled;
boolean useLog4j = BlueCoveImpl.getConfigProperty(BlueCoveConfigProperties.PROPERTY_DEBUG_LOG4J, true);
if (useLog4j) {
try {
LoggerAppenderExt log4jAppender = (LoggerAppenderExt) Class.forName(
"com.intel.bluetooth.DebugLog4jAppender").newInstance();
System.out.println("BlueCove log redirected to log4j");
addAppender(log4jAppender);
if (log4jAppender.isLogEnabled(DEBUG)) {
debugEnabled = true || debugEnabled;
}
} catch (Throwable e) {
}
}
}
public static boolean isDebugEnabled() {
if (!initialized) {
initialize();
}
return debugEnabled;
}
public static void setDebugEnabled(boolean debugEnabled) {
if (!initialized) {
initialize();
}
if (debugEnabled && debugCompiledOut) {
debugEnabled = false;
System.err.println("BlueCove debug functions have been Compiled Out");
} else {
BlueCoveImpl.instance().enableNativeDebug(debugEnabled);
DebugLog.debugEnabled = debugEnabled;
DebugLog.debugInternalEnabled = DebugLog.debugEnabled;
}
}
public static void debug(String message) {
if (!debugCompiledOut && isDebugEnabled()) {
log(message, null, null);
printLocation();
callAppenders(DEBUG, message, null);
}
}
public static void debug(String message, String v) {
if (!debugCompiledOut && isDebugEnabled()) {
log(message, " ", v);
printLocation();
callAppenders(DEBUG, message + " " + v, null);
}
}
public static void debug(String message, Throwable t) {
if (!debugCompiledOut && isDebugEnabled()) {
log(message, " ", t.toString());
printLocation();
// I have the reson not to make this as function.
if (!UtilsJavaSE.javaSECompiledOut) {
if (!UtilsJavaSE.ibmJ9midp) {
t.printStackTrace(System.out);
} else if (debugInternalEnabled) {
t.printStackTrace();
}
} else {
t.printStackTrace();
}
callAppenders(DEBUG, message, t);
}
}
public static void debug(String message, Object obj) {
if (!debugCompiledOut && isDebugEnabled()) {
log(message, " ", obj.toString());
printLocation();
callAppenders(DEBUG, message + " " + obj.toString(), null);
}
}
public static void debug(String message, String v, String v2) {
if (!debugCompiledOut && isDebugEnabled()) {
log(message, " ", v + " " + v2);
printLocation();
callAppenders(DEBUG, message + " " + v + " " + v2, null);
}
}
public static void debug(String message, long v) {
if (!debugCompiledOut && isDebugEnabled()) {
log(message, " ", Long.toString(v));
printLocation();
callAppenders(DEBUG, message + " " + Long.toString(v), null);
}
}
public static void debug0x(String message, long v) {
if (!debugCompiledOut && isDebugEnabled()) {
log(message, " 0x", Utils.toHexString(v));
printLocation();
callAppenders(DEBUG, message + " 0x" + Utils.toHexString(v), null);
}
}
public static void debug0x(String message, String s, long v) {
if (!debugCompiledOut && isDebugEnabled()) {
log(message, " " + s + " 0x", Utils.toHexString(v));
printLocation();
callAppenders(DEBUG, message + " " + s + " 0x" + Utils.toHexString(v), null);
}
}
public static void debug(String message, boolean v) {
if (!debugCompiledOut && isDebugEnabled()) {
log(message, " ", String.valueOf(v));
printLocation();
callAppenders(DEBUG, message + " " + v, null);
}
}
public static void debug(String message, byte[] data) {
debug(message, data, 0, (data == null) ? 0 : data.length);
}
public static void debug(String message, byte[] data, int off, int len) {
if (!debugCompiledOut && isDebugEnabled()) {
StringBuffer buf = new StringBuffer();
if (data == null) {
buf.append(" null byte[]");
} else {
buf.append(" [");
for (int i = off; i < off + len; i++) {
if (i != off) {
buf.append(", ");
}
buf.append((new Byte(data[i])).toString());
}
buf.append("]");
if (len > 4) {
buf.append(" ").append(len);
}
}
log(message, buf.toString(), null);
printLocation();
callAppenders(DEBUG, message + buf.toString(), null);
}
}
public static void debug(String message, int[] data) {
debug(message, data, 0, (data == null) ? 0 : data.length);
}
public static void debug(String message, int[] data, int off, int len) {
if (!debugCompiledOut && isDebugEnabled()) {
StringBuffer buf = new StringBuffer();
if (data == null) {
buf.append(" null int[]");
} else {
buf.append(" [");
for (int i = off; i < off + len; i++) {
if (i != off) {
buf.append(", ");
}
buf.append(Integer.toString(data[i]));
}
buf.append("]");
if (len > 4) {
buf.append(" ").append(len);
}
}
log(message, buf.toString(), null);
printLocation();
callAppenders(DEBUG, message + buf.toString(), null);
}
}
public static void nativeDebugCallback(String fileName, int lineN, String message) {
try {
if ((fileName != null) && fileName.startsWith(".\\")) {
fileName = fileName.substring(2);
}
DebugLog.debugNative(fileName + ":" + lineN, message);
} catch (Throwable e) {
try {
System.out.println("Error when calling debug " + e);
} catch (Throwable e2) {
// We don't want any Exception propagate to Native Code.
}
}
}
public static void debugNative(String location, String message) {
if (!debugCompiledOut && isDebugEnabled()) {
log(message, "\n\t ", location);
callAppenders(DEBUG, message, null);
}
}
public static void error(String message) {
if (!debugCompiledOut && isDebugEnabled()) {
log("error ", message, null);
printLocation();
callAppenders(ERROR, message, null);
}
}
public static void error(String message, long v) {
if (!debugCompiledOut && isDebugEnabled()) {
log("error ", message, " " + v);
printLocation();
callAppenders(ERROR, message + " " + v, null);
}
}
public static void error(String message, String v) {
if (!debugCompiledOut && isDebugEnabled()) {
log("error ", message, " " + v);
printLocation();
callAppenders(ERROR, message + " " + v, null);
}
}
public static void error(String message, Throwable t) {
if (!debugCompiledOut && isDebugEnabled()) {
log("error ", message, " " + t);
printLocation();
// I have the reson not to make this as function.
if (!UtilsJavaSE.javaSECompiledOut) {
if (!UtilsJavaSE.ibmJ9midp) {
t.printStackTrace(System.out);
} else if (debugInternalEnabled) {
t.printStackTrace();
}
} else {
t.printStackTrace();
}
callAppenders(ERROR, message, t);
}
}
public static void fatal(String message) {
log("error ", message, null);
printLocation();
callAppenders(ERROR, message, null);
}
public static void fatal(String message, Throwable t) {
log("error ", message, " " + t);
printLocation();
// I have the reson not to make this as function.
if (!UtilsJavaSE.javaSECompiledOut) {
if (!UtilsJavaSE.ibmJ9midp) {
t.printStackTrace(System.out);
} else if (debugInternalEnabled) {
t.printStackTrace();
}
} else {
t.printStackTrace();
}
callAppenders(ERROR, message, t);
}
private static void callAppenders(int level, String message, Throwable throwable) {
for (Enumeration iter = loggerAppenders.elements(); iter.hasMoreElements();) {
LoggerAppender a = (LoggerAppender) iter.nextElement();
a.appendLog(level, message, throwable);
}
}
public static void addAppender(LoggerAppender newAppender) {
loggerAppenders.addElement(newAppender);
}
public static void removeAppender(LoggerAppender newAppender) {
loggerAppenders.removeElement(newAppender);
}
private static String d00(int i) {
if (i > 9) {
return String.valueOf(i);
} else {
return "0" + String.valueOf(i);
}
}
private static String d000(int i) {
if (i > 99) {
return String.valueOf(i);
} else if (i > 9) {
return "0" + String.valueOf(i);
} else {
return "00" + String.valueOf(i);
}
}
private static void log(String message, String va1, String va2) {
if (!debugInternalEnabled) {
return;
}
try {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date(System.currentTimeMillis()));
StringBuffer sb;
sb = new StringBuffer();
sb.append(d00(calendar.get(Calendar.HOUR_OF_DAY))).append(":");
sb.append(d00(calendar.get(Calendar.MINUTE))).append(":");
sb.append(d00(calendar.get(Calendar.SECOND))).append(".");
sb.append(d000(calendar.get(Calendar.MILLISECOND))).append(" ");
sb.append(message);
if (va1 != null) {
sb.append(va1);
}
if (va2 != null) {
sb.append(va2);
}
System.out.println(sb.toString());
} catch (Throwable ignore) {
}
}
private static void printLocation() {
if (java13 || !debugInternalEnabled) {
return;
}
try {
UtilsJavaSE.StackTraceLocation ste = UtilsJavaSE.getLocation(fqcnSet);
if (ste != null) {
System.out.println("\t " + formatLocation(ste));
}
} catch (Throwable e) {
java13 = true;
}
}
private static String formatLocation(UtilsJavaSE.StackTraceLocation ste) {
if (ste == null) {
return "";
}
// Make Line# clickable in eclipse
return ste.className + "." + ste.methodName + "(" + ste.fileName + ":" + ste.lineNumber + ")";
}
}