package roboguice.util; import java.util.Locale; import com.google.inject.Inject; import android.app.Application; import android.content.pm.ApplicationInfo; import android.util.Log; public class LnImpl implements LnInterface { protected int minimumLogLevel = Log.VERBOSE; protected String packageName = ""; protected String tag = ""; public LnImpl() { // do nothing, used by Ln before injection is set up } @Inject public LnImpl(Application context) { try { packageName = context.getPackageName(); final int flags = context.getPackageManager().getApplicationInfo(packageName, 0).flags; minimumLogLevel = (flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0 ? Log.VERBOSE : Log.INFO; tag = packageName.toUpperCase(Locale.US); Ln.d("Configuring Logging, minimum log level is %s", Ln.logLevelToString(minimumLogLevel) ); } catch( Exception e ) { try { Log.e(packageName, "Error configuring logger", e); } catch( RuntimeException f ) { // NOPMD - Legal empty catch block // HACK ignore Stub! errors in mock objects during testing } } } @Override public int v(Throwable t) { return getLoggingLevel() <= Log.VERBOSE ? println(Log.VERBOSE, Log.getStackTraceString(t)) : 0; } @Override public int v(Object s1, Object... args) { if( getLoggingLevel()> Log.VERBOSE ) return 0; final String s = Strings.toString(s1); final String message = formatArgs(s, args); return println(Log.VERBOSE, message); } @Override public int v(Throwable throwable, Object s1, Object[] args) { if( getLoggingLevel()> Log.VERBOSE ) return 0; final String s = Strings.toString(s1); final String message = formatArgs(s, args) + '\n' + Log.getStackTraceString(throwable); return println(Log.VERBOSE, message); } @Override public int d(Throwable t) { return getLoggingLevel()<= Log.DEBUG ? println(Log.DEBUG, Log.getStackTraceString(t)) : 0; } @Override public int d(Object s1, Object... args) { if( getLoggingLevel()> Log.DEBUG ) return 0; final String s = Strings.toString(s1); final String message = formatArgs(s, args); return println(Log.DEBUG, message); } @Override public int d(Throwable throwable, Object s1, Object... args) { if( getLoggingLevel()> Log.DEBUG ) return 0; final String s = Strings.toString(s1); final String message = formatArgs(s, args) + '\n' + Log.getStackTraceString(throwable); return println(Log.DEBUG, message); } @Override public int i(Throwable t) { return getLoggingLevel()<= Log.INFO ? println(Log.INFO, Log.getStackTraceString(t)) : 0; } @Override public int i(Throwable throwable, Object s1, Object... args) { if( getLoggingLevel()> Log.INFO ) return 0; final String s = Strings.toString(s1); final String message = formatArgs(s, args) + '\n' + Log.getStackTraceString(throwable); return println(Log.INFO, message); } @Override public int i(Object s1, Object... args) { if( getLoggingLevel()> Log.INFO ) return 0; final String s = Strings.toString(s1); final String message = formatArgs(s, args); return println(Log.INFO, message); } @Override public int w(Throwable t) { return getLoggingLevel()<= Log.WARN ? println(Log.WARN, Log.getStackTraceString(t)) : 0; } @Override public int w(Throwable throwable, Object s1, Object... args) { if( getLoggingLevel()> Log.WARN ) return 0; final String s = Strings.toString(s1); final String message = formatArgs(s, args) + '\n' + Log.getStackTraceString(throwable); return println(Log.WARN, message); } @Override public int w(Object s1, Object... args) { if( getLoggingLevel()> Log.WARN ) return 0; final String s = Strings.toString(s1); final String message = formatArgs(s, args); return println(Log.WARN, message); } @Override public int e(Throwable t) { return getLoggingLevel()<= Log.ERROR ? println(Log.ERROR, Log.getStackTraceString(t)) : 0; } @Override public int e(Throwable throwable, Object s1, Object... args) { if( getLoggingLevel()> Log.ERROR ) return 0; final String s = Strings.toString(s1); final String message = formatArgs(s, args) + '\n' + Log.getStackTraceString(throwable); return println(Log.ERROR, message); } @Override public int e(Object s1, Object... args) { if( getLoggingLevel()> Log.ERROR ) return 0; final String s = Strings.toString(s1); final String message = formatArgs(s, args); return println(Log.ERROR, message); } @Override public boolean isDebugEnabled() { return getLoggingLevel()<= Log.DEBUG; } @Override public boolean isVerboseEnabled() { return getLoggingLevel()<= Log.VERBOSE; } @Override public String logLevelToString(int loglevel) { switch( loglevel ) { case Log.VERBOSE: return "VERBOSE"; case Log.DEBUG: return "DEBUG"; case Log.INFO: return "INFO"; case Log.WARN: return "WARN"; case Log.ERROR: return "ERROR"; case Log.ASSERT: return "ASSERT"; default: return "UNKNOWN"; } } @Override public int getLoggingLevel() { return minimumLogLevel; } @Override public void setLoggingLevel(int level) { minimumLogLevel = level; } public int println(int priority, String msg ) { return Log.println(priority, getTag(), processMessage(msg)); } protected String processMessage(String msg) { if( getLoggingLevel() <= Log.DEBUG ) msg = String.format("%s %s", Thread.currentThread().getName(), msg); return msg; } protected String getTag() { final int skipDepth = 6; // skip 6 stackframes to find the location where this was called if( getLoggingLevel() <= Log.DEBUG ) { final StackTraceElement trace = Thread.currentThread().getStackTrace()[skipDepth]; return tag + "/" + trace.getFileName() + ":" + trace.getLineNumber(); } return tag; } //protected for testing. protected String formatArgs(final String s, Object... args) { //this is a bit tricky : if args is null, it is passed to formatting //(and yes this can still break depending on conversion of the formatter, see String.format) //else if there is no args, we return the message as-is, otherwise we pass args to formatting normally. if( args != null && args.length == 0 ) { return s; } else { return String.format(s,args); } } }