[slf4j-dev] svn commit: r1214 - in slf4j/trunk/slf4j-ext/src/main/java/org/slf4j: agent instrumentation

ravn at slf4j.org ravn at slf4j.org
Sat Oct 25 16:16:41 CEST 2008


Author: ravn
Date: Sat Oct 25 16:16:41 2008
New Revision: 1214

Modified:
   slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentPremain.java
   slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/JavassistHelper.java
   slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/LogTransformer.java

Log:
now comforms to slf4j formatting

Modified: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentPremain.java
==============================================================================
--- slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentPremain.java	(original)
+++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentPremain.java	Sat Oct 25 16:16:41 2008
@@ -12,71 +12,81 @@
 
 public class AgentPremain {
 
-	private static final String START_MSG = "Start at {}";
-	private static final String STOP_MSG = "Stop at {}, execution time = {} ms";
-
-	public static void premain(String agentArgument,
-			Instrumentation instrumentation) {
-
-		System.err.println("THIS JAVAAGENT IS NOT RELEASED YET.  DO NOT USE IN PRODUCTION ENVIRONMENTS.");
-		LogTransformer.Builder builder = new LogTransformer.Builder();
-		builder = builder.addEntryExit(true);
-
-		if (agentArgument != null) {
-			Properties args = parseArguments(agentArgument);
-
-			if (args.containsKey("verbose")) {
-				builder = builder.verbose(true);
-			}
-
-			if (args.containsKey("time")) {
-				printStartStopTimes();
-			}
-
-			if (args.containsKey("ignore")) {
-				builder = builder.ignore(args.getProperty("ignore").split(","));
-			}
-			
-			if (args.containsKey("level")) {
-				builder = builder.level(args.getProperty("level"));
-			}
-
-			// ... more agent option handling here
-		}
-
-		instrumentation.addTransformer(builder.build());
-	}
-
-	private static Properties parseArguments(String agentArgument) {
-		Properties p = new Properties();
-		try {
-			byte[] bytes = agentArgument.replaceAll(";", "\n").getBytes();
-			p.load(new ByteArrayInputStream(bytes));
-		} catch (IOException e) {
-			throw new RuntimeException(
-					"Could not load arguments as properties", e);
-		}
-		return p;
-	}
-
-	/**
-	 * Print the start message with the time NOW, and register a shutdown hook
-	 * which will print the stop message with the time then and the number of
-	 * milliseconds passed since.
-	 * 
-	 */
-	private static void printStartStopTimes() {
-		final long start = System.currentTimeMillis();
-		System.err.println(format(START_MSG, new Date()));
-
-		Thread hook = new Thread() {
-			public void run() {
-				long timePassed = System.currentTimeMillis() - start;
-				String message = format(STOP_MSG, new Date(), timePassed);
-				System.err.println(message);
-			}
-		};
-		Runtime.getRuntime().addShutdownHook(hook);
-	}
+  private static final String START_MSG = "Start at {}";
+  private static final String STOP_MSG = "Stop at {}, execution time = {} ms";
 
+  /**
+   * JavaAgent premain entry point as specified in the MANIFEST.MF file. See
+   * {@link http://java.sun.com/javase/6/docs/api/java/lang/instrument/package-summary.html} for details.
+   * 
+   * @param agentArgument
+   *          string provided after "=" up to first space
+   * @param instrumentation
+   */
+  public static void premain(String agentArgument,
+      Instrumentation instrumentation) {
+
+    System.err.println("THIS JAVAAGENT IS NOT RELEASED YET.  "
+        + "DO NOT USE IN PRODUCTION ENVIRONMENTS.");
+
+    LogTransformer.Builder builder = new LogTransformer.Builder();
+    builder = builder.addEntryExit(true);
+
+    if (agentArgument != null) {
+      Properties args = parseArguments(agentArgument);
+
+      if (args.containsKey("verbose")) {
+        builder = builder.verbose(true);
+      }
+
+      if (args.containsKey("time")) {
+        printStartStopTimes();
+      }
+
+      if (args.containsKey("ignore")) {
+        builder = builder.ignore(args.getProperty("ignore").split(","));
+      }
+
+      if (args.containsKey("level")) {
+        builder = builder.level(args.getProperty("level"));
+      }
+
+      // ... more agent option handling here
+    }
+
+    instrumentation.addTransformer(builder.build());
+  }
+
+  private static Properties parseArguments(String agentArgument) {
+    Properties p = new Properties();
+    try {
+      byte[] bytes = agentArgument.replaceAll(";", "\n").getBytes();
+      p.load(new ByteArrayInputStream(bytes));
+    } catch (IOException e) {
+      String s = "Could not load arguments as properties";
+      throw new RuntimeException(s, e);
+    }
+    return p;
+  }
+
+  /**
+   * Print the start message with the time NOW, and register a shutdown hook
+   * which will print the stop message with the time then and the number of
+   * milliseconds passed since.
+   * 
+   */
+  private static void printStartStopTimes() {
+    final long start = System.currentTimeMillis();
+    System.err.println(format(START_MSG, new Date()));
+
+    Thread hook = new Thread() {
+      @Override
+      public void run() {
+        long timePassed = System.currentTimeMillis() - start;
+        String message = format(STOP_MSG, new Date(), timePassed);
+        System.err.println(message);
+      }
+    };
+    Runtime.getRuntime().addShutdownHook(hook);
+  }
 }
\ No newline at end of file

Modified: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/JavassistHelper.java
==============================================================================
--- slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/JavassistHelper.java	(original)
+++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/JavassistHelper.java	Sat Oct 25 16:16:41 2008
@@ -10,105 +10,103 @@
 
 public class JavassistHelper {
 
-	public static String returnValue(CtBehavior method)
-			throws NotFoundException {
+  public static String returnValue(CtBehavior method) throws NotFoundException {
 
-		String returnValue = "";
-		if (methodReturnsValue(method)) {
-			returnValue = " returns: \" + $_ + \"";
-		}
-		return returnValue;
-	}
-
-	private static boolean methodReturnsValue(CtBehavior method)
-			throws NotFoundException {
-
-		if (method instanceof CtMethod == false) {
-			return false;
-		}
-
-		CtClass returnType = ((CtMethod) method).getReturnType();
-		String returnTypeName = returnType.getName();
-
-		boolean isVoidMethod = "void".equals(returnTypeName);
-
-		boolean methodReturnsValue = isVoidMethod == false;
-		return methodReturnsValue;
-	}
-
-	public static String getSignature(CtBehavior method)
-			throws NotFoundException {
-
-		CtClass parameterTypes[] = method.getParameterTypes();
-
-		CodeAttribute codeAttribute = method.getMethodInfo().getCodeAttribute();
-
-		LocalVariableAttribute locals = null;
-
-		if (codeAttribute != null) {
-			locals = (LocalVariableAttribute) codeAttribute
-					.getAttribute("LocalVariableTable");
-		}
-
-		String methodName = method.getName();
-
-		StringBuffer sb = new StringBuffer(methodName + "(\" ");
-		for (int i = 0; i < parameterTypes.length; i++) {
-			if (i > 0) {
-				sb.append(" + \", \" ");
-			}
-
-			CtClass parameterType = parameterTypes[i];
-			boolean isArray = parameterType.isArray();
-			CtClass arrayOf = parameterType.getComponentType();
-			if (isArray) {
-				while (arrayOf.isArray()) {
-					arrayOf = arrayOf.getComponentType();
-				}
-			}
-
-			sb.append(" + \"");
-			sb.append(parameterNameFor(method, locals, i));
-			sb.append("\" + \"=");
-
-			// use Arrays.asList() to render array of objects.
-			if (isArray && !arrayOf.isPrimitive()) {
-				sb.append("\"+ java.util.Arrays.asList($" + (i + 1) + ")");
-			} else {
-				sb.append("\"+ $" + (i + 1));
-			}
-		}
-		sb.append("+\")");
-
-		String signature = sb.toString();
-		return signature;
-	}
-
-	static String parameterNameFor(CtBehavior method,
-			LocalVariableAttribute locals, int i) {
-		if (locals == null) {
-			return Integer.toString(i + 1);
-		}
-
-		int modifiers = method.getModifiers();
-
-		int j = i;
-
-		if (Modifier.isSynchronized(modifiers)) {
-			// skip object to synchronize upon.
-			j++;
-			// System.err.println("Synchronized");
-		}
-		if (Modifier.isStatic(modifiers) == false) {
-			// skip "this"
-			j++;
-			// System.err.println("Instance");
-		}
-		String variableName = locals.variableName(j);
-		if (variableName.equals("this")) {
-			System.err.println("this returned as a parameter name for "
-					+ method.getName() + ", names are probably shifted.");
-		}
-		return variableName;
-	}
+    String returnValue = "";
+    if (methodReturnsValue(method)) {
+      returnValue = " returns: \" + $_ + \".";
+    }
+    return returnValue;
+  }
+
+  private static boolean methodReturnsValue(CtBehavior method)
+      throws NotFoundException {
+
+    if (method instanceof CtMethod == false) {
+      return false;
+    }
+
+    CtClass returnType = ((CtMethod) method).getReturnType();
+    String returnTypeName = returnType.getName();
+
+    boolean isVoidMethod = "void".equals(returnTypeName);
+
+    boolean methodReturnsValue = isVoidMethod == false;
+    return methodReturnsValue;
+  }
+
+  public static String getSignature(CtBehavior method) throws NotFoundException {
+
+    CtClass parameterTypes[] = method.getParameterTypes();
+
+    CodeAttribute codeAttribute = method.getMethodInfo().getCodeAttribute();
+
+    LocalVariableAttribute locals = null;
+
+    if (codeAttribute != null) {
+      locals = (LocalVariableAttribute) codeAttribute
+          .getAttribute("LocalVariableTable");
+    }
+
+    String methodName = method.getName();
+
+    StringBuffer sb = new StringBuffer(methodName + "(\" ");
+    for (int i = 0; i < parameterTypes.length; i++) {
+      if (i > 0) {
+        sb.append(" + \", \" ");
+      }
+
+      CtClass parameterType = parameterTypes[i];
+      boolean isArray = parameterType.isArray();
+      CtClass arrayOf = parameterType.getComponentType();
+      if (isArray) {
+        while (arrayOf.isArray()) {
+          arrayOf = arrayOf.getComponentType();
+        }
+      }
+
+      sb.append(" + \"");
+      sb.append(parameterNameFor(method, locals, i));
+      sb.append("\" + \"=");
+
+      // use Arrays.asList() to render array of objects.
+      if (isArray && !arrayOf.isPrimitive()) {
+        sb.append("\"+ java.util.Arrays.asList($" + (i + 1) + ")");
+      } else {
+        sb.append("\"+ $" + (i + 1));
+      }
+    }
+    sb.append("+\")");
+
+    String signature = sb.toString();
+    return signature;
+  }
+
+  static String parameterNameFor(CtBehavior method,
+      LocalVariableAttribute locals, int i) {
+    if (locals == null) {
+      return Integer.toString(i + 1);
+    }
+
+    int modifiers = method.getModifiers();
+
+    int j = i;
+
+    if (Modifier.isSynchronized(modifiers)) {
+      // skip object to synchronize upon.
+      j++;
+      // System.err.println("Synchronized");
+    }
+    if (Modifier.isStatic(modifiers) == false) {
+      // skip "this"
+      j++;
+      // System.err.println("Instance");
+    }
+    String variableName = locals.variableName(j);
+    if (variableName.equals("this")) {
+      System.err.println("this returned as a parameter name for "
+          + method.getName() + " index " + j + ", names are probably shifted.");
+    }
+    return variableName;
+  }
 }

Modified: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/LogTransformer.java
==============================================================================
--- slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/LogTransformer.java	(original)
+++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/LogTransformer.java	Sat Oct 25 16:16:41 2008
@@ -25,213 +25,212 @@
  */
 public class LogTransformer implements ClassFileTransformer {
 
-	// http://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.html
-	public static class Builder {
+  // http://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.html
+  public static class Builder {
 
-		/**
-		 * Build and return the LogTransformer corresponding to the options set
-		 * in this Builder.
-		 * 
-		 * @return
-		 */
-		public LogTransformer build() {
-			if (verbose) {
-				System.err.println("Creating LogTransformer");
-			}
-			return new LogTransformer(this);
-		}
-
-		boolean addEntryExit;
-
-		/**
-		 * Should each method log entry (with parameters) and exit (with
-		 * parameters and returnvalue)?
-		 * 
-		 * @param b
-		 *            value of flag
-		 * @return
-		 */
-		public Builder addEntryExit(boolean b) {
-			addEntryExit = b;
-			return this;
-		}
-
-		boolean addVariableAssignment;
-
-		private Builder addVariableAssignment(boolean b) {
-			System.err.println("cannot currently log variable assignments.");
-			addVariableAssignment = b;
-			return this;
-		}
-
-		boolean verbose;
-
-		/**
-		 * Should LogTransformer be verbose in what it does? This currently list
-		 * the names of the classes being processed.
-		 * 
-		 * @param b
-		 * @return
-		 */
-		public Builder verbose(boolean b) {
-			verbose = b;
-			return this;
-		}
-
-		String[] ignore = { "sun/", "java/", "javax/", "org/slf4j/",
-				"ch/qos/logback/", "org/apache/log4j/", "apple/", "com/sun/"};
-
-		public Builder ignore(String[] strings) {
-			this.ignore = strings;
-			return this;
-		}
-
-		private String level = "info";
-
-		public Builder level(String level) {
-			level = level.toLowerCase();
-			if (level.equals("info") || level.equals("debug")
-					|| level.equals("trace")) {
-				this.level = level;
-			} else {
-				if (verbose) {
-					System.err.println("level not info/debug/trace : " + level);
-				}
-			}
-			return this;
-		}
-	}
-
-	private String level;
-	private String levelEnabled;
-
-	private LogTransformer(Builder builder) {
-		this.addEntryExit = builder.addEntryExit;
-		this.addVariableAssignment = builder.addVariableAssignment;
-		this.verbose = builder.verbose;
-		this.ignore = builder.ignore;
-		this.level = builder.level;
-		this.levelEnabled = "is" + builder.level.substring(0, 1).toUpperCase()
-				+ builder.level.substring(1) + "Enabled";
-	}
-
-	private static final String _LOG = "_log";
-
-	private boolean addEntryExit;
-	private boolean addVariableAssignment;
-	private boolean verbose;
-	private String[] ignore;
-
-	public byte[] transform(ClassLoader loader, String className,
-			Class<?> clazz, ProtectionDomain domain, byte[] bytes) {
-
-		try {
-			return transform0(className, clazz, bytes);
-		} catch (Exception e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-			return bytes;
-		}
-	}
-
-	/**
-	 * transform0 sees if the className starts with any of the namespaces to
-	 * ignore, if so it is returned unchanged. Otherwise it is processed by
-	 * doClass(...)
-	 * 
-	 * @param className
-	 * @param clazz
-	 * @param bytes
-	 * @return
-	 */
-	private byte[] transform0(String className, Class<?> clazz, byte[] bytes) {
-		for (int i = 0; i < ignore.length; i++) {
-			if (className.startsWith(ignore[i])) {
-				return bytes;
-			}
-		}
-		if (verbose) {
-			System.err.println("Loggifying " + className);
-		}
-		return doClass(className, clazz, bytes);
-	}
-
-	/**
-	 * The transform(...) method calls doClass(...) if the class name does not
-	 * start with any of the prefixes it has been told to ignore.
-	 * 
-	 * doClass() first creates a class description from the byte codes. If it is
-	 * a class (i.e. not an interface) the methods defined have bodies, and a
-	 * static final logger object is added with the name of this class as an
-	 * argument, and each method then gets processed with doMethod(...) to have
-	 * logger calls added.
-	 * 
-	 * 
-	 * 
-	 * @param name
-	 *            class name (slashes separate, not dots)
-	 * @param clazz
-	 * @param b
-	 * @return
-	 */
-	private byte[] doClass(String name, Class<?> clazz, byte[] b) {
-		ClassPool pool = ClassPool.getDefault();
-		CtClass cl = null;
-		try {
-			cl = pool.makeClass(new ByteArrayInputStream(b));
-			if (cl.isInterface() == false) {
-
-				String pattern1 = "private static org.slf4j.Logger {};";
-				String loggerDefinition = format(pattern1, _LOG);
-				CtField field = CtField.make(loggerDefinition, cl);
-
-				String pattern2 = "org.slf4j.LoggerFactory.getLogger({}.class);";
-				String replace = name.replace('/', '.');
-				String getLogger = format(pattern2, replace);
-
-				cl.addField(field, getLogger);
-				System.out.println(getLogger);
-
-				CtBehavior[] methods = cl.getDeclaredBehaviors();
-				for (int i = 0; i < methods.length; i++) {
-					if (methods[i].isEmpty() == false) {
-						doMethod(methods[i]);
-					}
-				}
-				b = cl.toBytecode();
-			}
-		} catch (Exception e) {
-			String pattern = "Could not instrument {},  exception : {}";
-			System.err.println(format(pattern, name, e.getMessage()));
-			e.printStackTrace(System.err);
-		} finally {
-			if (cl != null) {
-				cl.detach();
-			}
-		}
-		return b;
-	}
-
-	private void doMethod(CtBehavior method) throws NotFoundException,
-			CannotCompileException {
-
-		String signature = JavassistHelper.getSignature(method);
-		String returnValue = JavassistHelper.returnValue(method);
-
-		if (addEntryExit) {
-			String messagePattern = "if ({}.{}()) {}.{}(\">> {}\");";
-			Object[] arg1 = new Object[] { _LOG, levelEnabled, _LOG, level,
-					signature };
-			String before = MessageFormatter.arrayFormat(messagePattern, arg1);
-			//System.out.println(before);
-			method.insertBefore(before);
-
-			String messagePattern2 = "if ({}.{}()) {}.{}(\"<< {}{}\");";
-			Object[] arg2 = new Object[] { _LOG, levelEnabled, _LOG, level,
-					signature, returnValue };
-			String after = MessageFormatter.arrayFormat(messagePattern2, arg2);
-			//System.out.println(after);
-			method.insertAfter(after);
-		}
-	}
+    /**
+     * Build and return the LogTransformer corresponding to the options set in
+     * this Builder.
+     * 
+     * @return
+     */
+    public LogTransformer build() {
+      if (verbose) {
+        System.err.println("Creating LogTransformer");
+      }
+      return new LogTransformer(this);
+    }
+
+    boolean addEntryExit;
+
+    /**
+     * Should each method log entry (with parameters) and exit (with parameters
+     * and returnvalue)?
+     * 
+     * @param b
+     *          value of flag
+     * @return
+     */
+    public Builder addEntryExit(boolean b) {
+      addEntryExit = b;
+      return this;
+    }
+
+    boolean addVariableAssignment;
+
+    private Builder addVariableAssignment(boolean b) {
+      System.err.println("cannot currently log variable assignments.");
+      addVariableAssignment = b;
+      return this;
+    }
+
+    boolean verbose;
+
+    /**
+     * Should LogTransformer be verbose in what it does? This currently list the
+     * names of the classes being processed.
+     * 
+     * @param b
+     * @return
+     */
+    public Builder verbose(boolean b) {
+      verbose = b;
+      return this;
+    }
+
+    String[] ignore = { "sun/", "java/", "javax/", "org/slf4j/",
+        "ch/qos/logback/", "org/apache/log4j/", "apple/", "com/sun/" };
+
+    public Builder ignore(String[] strings) {
+      this.ignore = strings;
+      return this;
+    }
+
+    private String level = "info";
+
+    public Builder level(String level) {
+      level = level.toLowerCase();
+      if (level.equals("info") || level.equals("debug")
+          || level.equals("trace")) {
+        this.level = level;
+      } else {
+        if (verbose) {
+          System.err.println("level not info/debug/trace : " + level);
+        }
+      }
+      return this;
+    }
+  }
+
+  private String level;
+  private String levelEnabled;
+
+  private LogTransformer(Builder builder) {
+    this.addEntryExit = builder.addEntryExit;
+    this.addVariableAssignment = builder.addVariableAssignment;
+    this.verbose = builder.verbose;
+    this.ignore = builder.ignore;
+    this.level = builder.level;
+    this.levelEnabled = "is" + builder.level.substring(0, 1).toUpperCase()
+        + builder.level.substring(1) + "Enabled";
+  }
+
+  private static final String _LOG = "_log";
+
+  private boolean addEntryExit;
+  private boolean addVariableAssignment;
+  private boolean verbose;
+  private String[] ignore;
+
+  public byte[] transform(ClassLoader loader, String className, Class<?> clazz,
+      ProtectionDomain domain, byte[] bytes) {
+
+    try {
+      return transform0(className, clazz, bytes);
+    } catch (Exception e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+      return bytes;
+    }
+  }
+
+  /**
+   * transform0 sees if the className starts with any of the namespaces to
+   * ignore, if so it is returned unchanged. Otherwise it is processed by
+   * doClass(...)
+   * 
+   * @param className
+   * @param clazz
+   * @param bytes
+   * @return
+   */
+  private byte[] transform0(String className, Class<?> clazz, byte[] bytes) {
+    for (int i = 0; i < ignore.length; i++) {
+      if (className.startsWith(ignore[i])) {
+        return bytes;
+      }
+    }
+    if (verbose) {
+      System.err.println("Loggifying " + className);
+    }
+    return doClass(className, clazz, bytes);
+  }
+
+  /**
+   * The transform(...) method calls doClass(...) if the class name does not
+   * start with any of the prefixes it has been told to ignore.
+   * 
+   * doClass() first creates a class description from the byte codes. If it is a
+   * class (i.e. not an interface) the methods defined have bodies, and a static
+   * final logger object is added with the name of this class as an argument,
+   * and each method then gets processed with doMethod(...) to have logger calls
+   * added.
+   * 
+   * 
+   * 
+   * @param name
+   *          class name (slashes separate, not dots)
+   * @param clazz
+   * @param b
+   * @return
+   */
+  private byte[] doClass(String name, Class<?> clazz, byte[] b) {
+    ClassPool pool = ClassPool.getDefault();
+    CtClass cl = null;
+    try {
+      cl = pool.makeClass(new ByteArrayInputStream(b));
+      if (cl.isInterface() == false) {
+
+        String pattern1 = "private static org.slf4j.Logger {};";
+        String loggerDefinition = format(pattern1, _LOG);
+        CtField field = CtField.make(loggerDefinition, cl);
+
+        String pattern2 = "org.slf4j.LoggerFactory.getLogger({}.class);";
+        String replace = name.replace('/', '.');
+        String getLogger = format(pattern2, replace);
+
+        cl.addField(field, getLogger);
+        // System.out.println(getLogger);
+
+        CtBehavior[] methods = cl.getDeclaredBehaviors();
+        for (int i = 0; i < methods.length; i++) {
+          if (methods[i].isEmpty() == false) {
+            doMethod(methods[i]);
+          }
+        }
+        b = cl.toBytecode();
+      }
+    } catch (Exception e) {
+      String pattern = "Could not instrument {},  exception : {}";
+      System.err.println(format(pattern, name, e.getMessage()));
+      e.printStackTrace(System.err);
+    } finally {
+      if (cl != null) {
+        cl.detach();
+      }
+    }
+    return b;
+  }
+
+  private void doMethod(CtBehavior method) throws NotFoundException,
+      CannotCompileException {
+
+    String signature = JavassistHelper.getSignature(method);
+    String returnValue = JavassistHelper.returnValue(method);
+
+    if (addEntryExit) {
+      String messagePattern = "if ({}.{}()) {}.{}(\">> {}\");";
+      Object[] arg1 = new Object[] { _LOG, levelEnabled, _LOG, level, signature };
+      String before = MessageFormatter.arrayFormat(messagePattern, arg1);
+      // System.out.println(before);
+      method.insertBefore(before);
+
+      String messagePattern2 = "if ({}.{}()) {}.{}(\"<< {}{}\");";
+      Object[] arg2 = new Object[] { _LOG, levelEnabled, _LOG, level,
+          signature, returnValue };
+      String after = MessageFormatter.arrayFormat(messagePattern2, arg2);
+      // System.out.println(after);
+      method.insertAfter(after);
+    }
+  }
 }
\ No newline at end of file



More information about the slf4j-dev mailing list