View Javadoc

1   /**
2    *  BlueCove - Java library for Bluetooth
3    *  Copyright (C) 2006-2008 Vlad Skarzhevskyy
4    *
5    *  Licensed to the Apache Software Foundation (ASF) under one
6    *  or more contributor license agreements.  See the NOTICE file
7    *  distributed with this work for additional information
8    *  regarding copyright ownership.  The ASF licenses this file
9    *  to you under the Apache License, Version 2.0 (the
10   *  "License"); you may not use this file except in compliance
11   *  with the License.  You may obtain a copy of the License at
12   *
13   *    http://www.apache.org/licenses/LICENSE-2.0
14   *
15   *  Unless required by applicable law or agreed to in writing,
16   *  software distributed under the License is distributed on an
17   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18   *  KIND, either express or implied.  See the License for the
19   *  specific language governing permissions and limitations
20   *  under the License.
21   *
22   *  @author vlads
23   *  @version $Id: DebugLog.java 2505 2008-12-05 20:11:25Z skarzhevskyy $
24   */
25  package com.intel.bluetooth;
26  
27  import java.util.Calendar;
28  import java.util.Date;
29  import java.util.Enumeration;
30  import java.util.Vector;
31  
32  /**
33   * BlueCove log system.
34   * 
35   * If enabled "-Dbluecove.debug=true" System.out.println would be used for debug. Alternatively if log4j is available in
36   * classpath Bluecove log would be redirected to log4j and can be enable using log4j configuration.
37   * 
38   * The methods of this class would be removed automaticaly because they are empty if debugCompiledOut = true. This class
39   * itself will disappear from bytecode after obfuscation by proguard in this case. Change to create mini jar.
40   * 
41   */
42  public abstract class DebugLog {
43  
44  	private static final boolean debugCompiledOut = false;
45  
46  	public final static int DEBUG = 1;
47  
48  	public final static int ERROR = 4;
49  
50  	private static boolean debugEnabled = false;
51  
52  	private static boolean initialized = false;
53  
54  	private static boolean debugInternalEnabled = false;
55  
56  	private static final String FQCN = DebugLog.class.getName();
57  
58  	private static final Vector fqcnSet = new Vector();
59  
60  	private static boolean java13 = false;
61  
62  	private static Vector loggerAppenders = new Vector();
63  
64  	/**
65  	 * Different log system can be injected in BlueCove using DebugLog.addAppender(customLoggerAppender)
66  	 * 
67  	 */
68  	public static interface LoggerAppender {
69  		public void appendLog(int level, String message, Throwable throwable);
70  	}
71  
72  	public static interface LoggerAppenderExt extends LoggerAppender {
73  		public boolean isLogEnabled(int level);
74  	}
75  
76  	static {
77  		fqcnSet.addElement(FQCN);
78  	}
79  
80  	private DebugLog() {
81  
82  	}
83  
84  	private synchronized static void initialize() {
85  		if (initialized) {
86  			return;
87  		}
88  		initialized = true;
89  		debugEnabled = BlueCoveImpl.getConfigProperty(BlueCoveConfigProperties.PROPERTY_DEBUG, false);
90  		if (debugEnabled && debugCompiledOut) {
91  			debugEnabled = false;
92  			System.err.println("BlueCove debug functions have been Compiled Out");
93  		}
94  		boolean useStdOut = BlueCoveImpl.getConfigProperty(BlueCoveConfigProperties.PROPERTY_DEBUG_STDOUT, true);
95  		debugInternalEnabled = useStdOut && debugEnabled;
96  		boolean useLog4j = BlueCoveImpl.getConfigProperty(BlueCoveConfigProperties.PROPERTY_DEBUG_LOG4J, true);
97  		if (useLog4j) {
98  			try {
99  				LoggerAppenderExt log4jAppender = (LoggerAppenderExt) Class.forName(
100 						"com.intel.bluetooth.DebugLog4jAppender").newInstance();
101 				System.out.println("BlueCove log redirected to log4j");
102 				addAppender(log4jAppender);
103 				if (log4jAppender.isLogEnabled(DEBUG)) {
104 					debugEnabled = true || debugEnabled;
105 				}
106 			} catch (Throwable e) {
107 			}
108 		}
109 	}
110 
111 	public static boolean isDebugEnabled() {
112 		if (!initialized) {
113 			initialize();
114 		}
115 		return debugEnabled;
116 	}
117 
118 	public static void setDebugEnabled(boolean debugEnabled) {
119 		if (!initialized) {
120 			initialize();
121 		}
122 		if (debugEnabled && debugCompiledOut) {
123 			debugEnabled = false;
124 			System.err.println("BlueCove debug functions have been Compiled Out");
125 		} else {
126 			BlueCoveImpl.instance().enableNativeDebug(debugEnabled);
127 			DebugLog.debugEnabled = debugEnabled;
128 			DebugLog.debugInternalEnabled = DebugLog.debugEnabled;
129 		}
130 	}
131 
132 	public static void debug(String message) {
133 		if (!debugCompiledOut && isDebugEnabled()) {
134 			log(message, null, null);
135 			printLocation();
136 			callAppenders(DEBUG, message, null);
137 		}
138 	}
139 
140 	public static void debug(String message, String v) {
141 		if (!debugCompiledOut && isDebugEnabled()) {
142 			log(message, " ", v);
143 			printLocation();
144 			callAppenders(DEBUG, message + " " + v, null);
145 		}
146 	}
147 
148 	public static void debug(String message, Throwable t) {
149 		if (!debugCompiledOut && isDebugEnabled()) {
150 			log(message, " ", t.toString());
151 			printLocation();
152 			// I have the reson not to make this as function.
153 			if (!UtilsJavaSE.javaSECompiledOut) {
154 				if (!UtilsJavaSE.ibmJ9midp) {
155 					t.printStackTrace(System.out);
156 				} else if (debugInternalEnabled) {
157 					t.printStackTrace();
158 				}
159 			} else {
160 				t.printStackTrace();
161 			}
162 			callAppenders(DEBUG, message, t);
163 		}
164 	}
165 
166 	public static void debug(String message, Object obj) {
167 		if (!debugCompiledOut && isDebugEnabled()) {
168 			log(message, " ", obj.toString());
169 			printLocation();
170 			callAppenders(DEBUG, message + " " + obj.toString(), null);
171 		}
172 	}
173 
174 	public static void debug(String message, String v, String v2) {
175 		if (!debugCompiledOut && isDebugEnabled()) {
176 			log(message, " ", v + " " + v2);
177 			printLocation();
178 			callAppenders(DEBUG, message + " " + v + " " + v2, null);
179 		}
180 	}
181 
182 	public static void debug(String message, long v) {
183 		if (!debugCompiledOut && isDebugEnabled()) {
184 			log(message, " ", Long.toString(v));
185 			printLocation();
186 			callAppenders(DEBUG, message + " " + Long.toString(v), null);
187 		}
188 	}
189 
190 	public static void debug0x(String message, long v) {
191 		if (!debugCompiledOut && isDebugEnabled()) {
192 			log(message, " 0x", Utils.toHexString(v));
193 			printLocation();
194 			callAppenders(DEBUG, message + " 0x" + Utils.toHexString(v), null);
195 		}
196 	}
197 
198 	public static void debug0x(String message, String s, long v) {
199 		if (!debugCompiledOut && isDebugEnabled()) {
200 			log(message, " " + s + " 0x", Utils.toHexString(v));
201 			printLocation();
202 			callAppenders(DEBUG, message + " " + s + " 0x" + Utils.toHexString(v), null);
203 		}
204 	}
205 
206 	public static void debug(String message, boolean v) {
207 		if (!debugCompiledOut && isDebugEnabled()) {
208 			log(message, " ", String.valueOf(v));
209 			printLocation();
210 			callAppenders(DEBUG, message + " " + v, null);
211 		}
212 	}
213 
214 	public static void debug(String message, byte[] data) {
215 		debug(message, data, 0, (data == null) ? 0 : data.length);
216 	}
217 
218 	public static void debug(String message, byte[] data, int off, int len) {
219 		if (!debugCompiledOut && isDebugEnabled()) {
220 			StringBuffer buf = new StringBuffer();
221 			if (data == null) {
222 				buf.append(" null byte[]");
223 			} else {
224 				buf.append(" [");
225 				for (int i = off; i < off + len; i++) {
226 					if (i != off) {
227 						buf.append(", ");
228 					}
229 					buf.append((new Byte(data[i])).toString());
230 				}
231 				buf.append("]");
232 				if (len > 4) {
233 					buf.append(" ").append(len);
234 				}
235 			}
236 			log(message, buf.toString(), null);
237 			printLocation();
238 			callAppenders(DEBUG, message + buf.toString(), null);
239 		}
240 	}
241 
242 	public static void debug(String message, int[] data) {
243 		debug(message, data, 0, (data == null) ? 0 : data.length);
244 	}
245 
246 	public static void debug(String message, int[] data, int off, int len) {
247 		if (!debugCompiledOut && isDebugEnabled()) {
248 			StringBuffer buf = new StringBuffer();
249 			if (data == null) {
250 				buf.append(" null int[]");
251 			} else {
252 				buf.append(" [");
253 				for (int i = off; i < off + len; i++) {
254 					if (i != off) {
255 						buf.append(", ");
256 					}
257 					buf.append(Integer.toString(data[i]));
258 				}
259 				buf.append("]");
260 				if (len > 4) {
261 					buf.append(" ").append(len);
262 				}
263 			}
264 			log(message, buf.toString(), null);
265 			printLocation();
266 			callAppenders(DEBUG, message + buf.toString(), null);
267 		}
268 	}
269 
270 	public static void nativeDebugCallback(String fileName, int lineN, String message) {
271 		try {
272 			if ((fileName != null) && fileName.startsWith(".\\")) {
273 				fileName = fileName.substring(2);
274 			}
275 			DebugLog.debugNative(fileName + ":" + lineN, message);
276 		} catch (Throwable e) {
277 			try {
278 				System.out.println("Error when calling debug " + e);
279 			} catch (Throwable e2) {
280 				// We don't want any Exception propagate to Native Code.
281 			}
282 		}
283 	}
284 
285 	public static void debugNative(String location, String message) {
286 		if (!debugCompiledOut && isDebugEnabled()) {
287 			log(message, "\n\t  ", location);
288 			callAppenders(DEBUG, message, null);
289 		}
290 	}
291 
292 	public static void error(String message) {
293 		if (!debugCompiledOut && isDebugEnabled()) {
294 			log("error ", message, null);
295 			printLocation();
296 			callAppenders(ERROR, message, null);
297 		}
298 	}
299 
300 	public static void error(String message, long v) {
301 		if (!debugCompiledOut && isDebugEnabled()) {
302 			log("error ", message, " " + v);
303 			printLocation();
304 			callAppenders(ERROR, message + " " + v, null);
305 		}
306 	}
307 
308 	public static void error(String message, String v) {
309 		if (!debugCompiledOut && isDebugEnabled()) {
310 			log("error ", message, " " + v);
311 			printLocation();
312 			callAppenders(ERROR, message + " " + v, null);
313 		}
314 	}
315 
316 	public static void error(String message, Throwable t) {
317 		if (!debugCompiledOut && isDebugEnabled()) {
318 			log("error ", message, " " + t);
319 			printLocation();
320 			// I have the reson not to make this as function.
321 			if (!UtilsJavaSE.javaSECompiledOut) {
322 				if (!UtilsJavaSE.ibmJ9midp) {
323 					t.printStackTrace(System.out);
324 				} else if (debugInternalEnabled) {
325 					t.printStackTrace();
326 				}
327 			} else {
328 				t.printStackTrace();
329 			}
330 
331 			callAppenders(ERROR, message, t);
332 		}
333 	}
334 
335 	public static void fatal(String message) {
336 		log("error ", message, null);
337 		printLocation();
338 		callAppenders(ERROR, message, null);
339 	}
340 
341 	public static void fatal(String message, Throwable t) {
342 		log("error ", message, " " + t);
343 		printLocation();
344 		// I have the reson not to make this as function.
345 		if (!UtilsJavaSE.javaSECompiledOut) {
346 			if (!UtilsJavaSE.ibmJ9midp) {
347 				t.printStackTrace(System.out);
348 			} else if (debugInternalEnabled) {
349 				t.printStackTrace();
350 			}
351 		} else {
352 			t.printStackTrace();
353 		}
354 
355 		callAppenders(ERROR, message, t);
356 	}
357 
358 	private static void callAppenders(int level, String message, Throwable throwable) {
359 		for (Enumeration iter = loggerAppenders.elements(); iter.hasMoreElements();) {
360 			LoggerAppender a = (LoggerAppender) iter.nextElement();
361 			a.appendLog(level, message, throwable);
362 		}
363 	}
364 
365 	public static void addAppender(LoggerAppender newAppender) {
366 		loggerAppenders.addElement(newAppender);
367 	}
368 
369 	public static void removeAppender(LoggerAppender newAppender) {
370 		loggerAppenders.removeElement(newAppender);
371 	}
372 
373 	private static String d00(int i) {
374 		if (i > 9) {
375 			return String.valueOf(i);
376 		} else {
377 			return "0" + String.valueOf(i);
378 		}
379 	}
380 
381 	private static String d000(int i) {
382 		if (i > 99) {
383 			return String.valueOf(i);
384 		} else if (i > 9) {
385 			return "0" + String.valueOf(i);
386 		} else {
387 			return "00" + String.valueOf(i);
388 		}
389 	}
390 
391 	private static void log(String message, String va1, String va2) {
392 		if (!debugInternalEnabled) {
393 			return;
394 		}
395 		try {
396 			Calendar calendar = Calendar.getInstance();
397 			calendar.setTime(new Date(System.currentTimeMillis()));
398 
399 			StringBuffer sb;
400 			sb = new StringBuffer();
401 			sb.append(d00(calendar.get(Calendar.HOUR_OF_DAY))).append(":");
402 			sb.append(d00(calendar.get(Calendar.MINUTE))).append(":");
403 			sb.append(d00(calendar.get(Calendar.SECOND))).append(".");
404 			sb.append(d000(calendar.get(Calendar.MILLISECOND))).append(" ");
405 
406 			sb.append(message);
407 			if (va1 != null) {
408 				sb.append(va1);
409 			}
410 			if (va2 != null) {
411 				sb.append(va2);
412 			}
413 
414 			System.out.println(sb.toString());
415 		} catch (Throwable ignore) {
416 		}
417 	}
418 
419 	private static void printLocation() {
420 		if (java13 || !debugInternalEnabled) {
421 			return;
422 		}
423 		try {
424 			UtilsJavaSE.StackTraceLocation ste = UtilsJavaSE.getLocation(fqcnSet);
425 			if (ste != null) {
426 				System.out.println("\t  " + formatLocation(ste));
427 			}
428 		} catch (Throwable e) {
429 			java13 = true;
430 		}
431 	}
432 
433 	private static String formatLocation(UtilsJavaSE.StackTraceLocation ste) {
434 		if (ste == null) {
435 			return "";
436 		}
437 		// Make Line# clickable in eclipse
438 		return ste.className + "." + ste.methodName + "(" + ste.fileName + ":" + ste.lineNumber + ")";
439 	}
440 
441 }