MicroLogger.java

package org.microspace.util;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

/**
* Provide varargs functionality for org.apache.log4j.Logger,
* so that lightweight logging is possible and toString
* is called only when the object is logged.
* 
* @author Gaspar Sinai at microspace.org
* @version 2011-01-29
*/
public class MicroLogger {

   private Logger log;

   private static UniqueIdSeed seed = new UniqueIdSeed();

   public MicroLogger (Logger log) {
       this.log = log;
       if(seed == null){
           seed = new UniqueIdSeed();
       }
       // This lets you specify %X{PID} 
       MDC.put("PID", "" + seed.getProcessId());
   }
   
   public MicroLogger (Class<?> clazz) {
   	this(LoggerFactory.getLogger(clazz));
   }

   public Logger getLogger () {
       return log;
   }

   public void trace(String msg, Object... args) {
       if (log == null || msg == null || !log.isTraceEnabled()) {
           return;
       }
       log.trace(parse(msg, args));
   }

   public void debug(String msg, Object... args) {
       if (log == null || msg == null || !log.isDebugEnabled()) {
           return;
       }
       log.debug(parse(msg, args));
   }

   public void info(String msg, Object... args) {
       if (log == null || msg == null || !log.isInfoEnabled()) {
           return;
       }
       log.info(parse(msg, args));
   }

   public void warn(String msg, Throwable e, Object... args) {
       if (log == null || msg == null || !log.isWarnEnabled()) {
           return;
       }
       if (e != null) {
           log.warn(parse(msg, args), e);
       } else {
           log.warn(parse(msg, args));
       }
   }

   public void error(String msg, Throwable e, Object... args) {
       if (log == null || msg == null || !log.isErrorEnabled()) {
           return;
       }
       if (e != null) {
           log.error(parse(msg, args), e);
       } else {
           log.error(parse(msg, args));
       }
   }


   private enum State { START, DOLLAR, NUMBER }

   /**
    * Parse string to print.
    * <pre>
    * parse ("Second arg=$1 first is $0", 1, 2); 
    * </pre>
    * @param msg is like $0 $2 or $* $* escaped $$
    * @param args is the matching objects to print.
    * @return the parsed String.
    */
   public static String parse(String msg, Object... args) {
       if (msg == null) {
           return "";
       }
       StringBuilder sb = new StringBuilder();
       int index = 0;
       int autoIndex = 0;
       State state = State.START;
         
       for (int i = 0; i < msg.length(); i++) {
           char c = msg.charAt (i);
           switch (state) {
           case START:
               if (c == '$') {
                   state = State.DOLLAR;
                   index = 0;
               } else {
                   sb.append (c);
               }
               break;
           case DOLLAR:
               if (c == '$') {
                   sb.append (c);
                   state = State.START;
                   break;
               } 
               if (c == '*') {
                   index = autoIndex++;
                   state = State.START;
                   sb.append (printArgs (index, args));
                   break;
               }
               /*FALLTHROUGH*/
           case NUMBER:
               if (c >= '0' && c <= '9') {
                   index = index * 10 + (c - '0');
                   state = State.NUMBER;
               } 
               if (c < '0' || c > '9' || i+1 == msg.length()) {
                   if (state == State.NUMBER) {
                       state = State.START;
                       sb.append (printArgs (index, args));
                       if (c >= '0' && c <= '9') break;
                   }
                   if (c == '$') {
                       state = State.DOLLAR;
                       index = 0;
                   } else {
                       sb.append (c);
                       state = State.START;
                   }
               }
           }
       }
       return sb.toString();
   }

   private static String printArgs (int index, Object... args) {
       if (args == null) return "arg-error";
       if (args.length <= index) return "array-error";
       if (args[index] == null) return "null";
       StringBuffer sb = new StringBuffer();
       if (args[index].getClass().isArray()) {
           Object[] ao = (Object[]) args[index];
           sb.append ('{');
           for (Object o : ao) {
               sb.append (" [" + o + "] ");
           }
           sb.append ('}');
       } else {
           sb.append ("" + args[index]);
       }
       return sb.toString();
   }
}