1   package org.slf4j.agent;
2   
3   import java.io.ByteArrayInputStream;
4   import java.io.IOException;
5   import java.lang.instrument.Instrumentation;
6   import java.util.Date;
7   import java.util.Properties;
8   
9   import org.slf4j.instrumentation.LogTransformer;
10  
11  /**
12   * Entry point for slf4j-ext when used as a Java agent.
13   * 
14   */
15  public class AgentPremain {
16  
17  	/**
18  	 * JavaAgent premain entry point as specified in the MANIFEST.MF file. See
19  	 * {@link http
20  	 * ://java.sun.com/javase/6/docs/api/java/lang/instrument/package-
21  	 * summary.html} for details.
22  	 * 
23  	 * @param agentArgument
24  	 *            string provided after "=" up to first space
25  	 * @param instrumentation
26  	 *            instrumentation environment provided by the JVM
27  	 */
28  	public static void premain(String agentArgument,
29  			Instrumentation instrumentation) {
30  
31  		// We cannot do sanity checks for slf4j here as the jars loaded
32  		// by the application are not visible here.
33  
34  		LogTransformer.Builder builder = new LogTransformer.Builder();
35  		builder = builder.addEntryExit(true);
36  
37  		if (agentArgument != null) {
38  			Properties args = parseArguments(agentArgument, ",");
39  
40  			if (args.containsKey(AgentOptions.VERBOSE)) {
41  				builder = builder.verbose(true);
42  			}
43  
44  			if (args.containsKey(AgentOptions.TIME)) {
45  				printStartStopTimes();
46  			}
47  
48  			if (args.containsKey(AgentOptions.IGNORE)) {
49  				String ignore = args.getProperty(AgentOptions.IGNORE);
50  				builder = builder.ignore(ignore.split(":"));
51  			}
52  
53  			if (args.containsKey(AgentOptions.LEVEL)) {
54  				builder = builder.level(args.getProperty(AgentOptions.LEVEL));
55  			}
56  		}
57  
58  		instrumentation.addTransformer(builder.build());
59  	}
60  
61  	/**
62  	 * Consider the argument string to be a property file (by converting the
63  	 * splitter character to line feeds), and then reading it like any other
64  	 * property file.
65  	 * 
66  	 * 
67  	 * @param agentArgument
68  	 *            string given by instrumentation framework
69  	 * @param separator
70  	 *            String to convert to line feeds
71  	 * @return argument converted to properties
72  	 */
73  	private static Properties parseArguments(String agentArgument,
74  			String separator) {
75  		Properties p = new Properties();
76  		try {
77  			String argumentAsLines = agentArgument.replaceAll(separator, "\n");
78  			p.load(new ByteArrayInputStream(argumentAsLines.getBytes()));
79  		} catch (IOException e) {
80  			String s = "Could not load arguments as properties";
81  			throw new RuntimeException(s, e);
82  		}
83  		return p;
84  	}
85  
86  	/**
87  	 * Print the start message to System.err with the time NOW, and register a
88  	 * shutdown hook which will print the stop message to System.err with the
89  	 * time then and the number of milliseconds passed since.
90  	 * 
91  	 */
92  	private static void printStartStopTimes() {
93  		final long start = System.currentTimeMillis();
94  
95  		System.err.println("Start at " + new Date());
96  
97  		Thread hook = new Thread() {
98  			@Override
99  			public void run() {
100 				long timePassed = System.currentTimeMillis() - start;
101 				System.err.println("Stop at " + new Date()
102 						+ ", execution time = " + timePassed + " ms");
103 			}
104 		};
105 		Runtime.getRuntime().addShutdownHook(hook);
106 	}
107 }