1 /**
2 * Copyright (c) 2004-2011 QOS.ch
3 * All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 */
25 package org.slf4j.agent;
26
27 import java.io.ByteArrayInputStream;
28 import java.io.IOException;
29 import java.lang.instrument.Instrumentation;
30 import java.util.Date;
31 import java.util.Properties;
32
33 import org.slf4j.instrumentation.LogTransformer;
34
35 /**
36 * Entry point for slf4j-ext when used as a Java agent.
37 *
38 */
39 public class AgentPremain {
40
41 /**
42 * JavaAgent premain entry point as specified in the MANIFEST.MF file. See
43 * {@link http
44 * ://java.sun.com/javase/6/docs/api/java/lang/instrument/package-
45 * summary.html} for details.
46 *
47 * @param agentArgument
48 * string provided after "=" up to first space
49 * @param instrumentation
50 * instrumentation environment provided by the JVM
51 */
52 public static void premain(String agentArgument,
53 Instrumentation instrumentation) {
54
55 // We cannot do sanity checks for slf4j here as the jars loaded
56 // by the application are not visible here.
57
58 LogTransformer.Builder builder = new LogTransformer.Builder();
59 builder = builder.addEntryExit(true);
60
61 if (agentArgument != null) {
62 Properties args = parseArguments(agentArgument, ",");
63
64 if (args.containsKey(AgentOptions.VERBOSE)) {
65 builder = builder.verbose(true);
66 }
67
68 if (args.containsKey(AgentOptions.TIME)) {
69 printStartStopTimes();
70 }
71
72 if (args.containsKey(AgentOptions.IGNORE)) {
73 String ignore = args.getProperty(AgentOptions.IGNORE);
74 builder = builder.ignore(ignore.split(":"));
75 }
76
77 if (args.containsKey(AgentOptions.LEVEL)) {
78 builder = builder.level(args.getProperty(AgentOptions.LEVEL));
79 }
80 }
81
82 instrumentation.addTransformer(builder.build());
83 }
84
85 /**
86 * Consider the argument string to be a property file (by converting the
87 * splitter character to line feeds), and then reading it like any other
88 * property file.
89 *
90 *
91 * @param agentArgument
92 * string given by instrumentation framework
93 * @param separator
94 * String to convert to line feeds
95 * @return argument converted to properties
96 */
97 private static Properties parseArguments(String agentArgument,
98 String separator) {
99 Properties p = new Properties();
100 try {
101 String argumentAsLines = agentArgument.replaceAll(separator, "\n");
102 p.load(new ByteArrayInputStream(argumentAsLines.getBytes()));
103 } catch (IOException e) {
104 String s = "Could not load arguments as properties";
105 throw new RuntimeException(s, e);
106 }
107 return p;
108 }
109
110 /**
111 * Print the start message to System.err with the time NOW, and register a
112 * shutdown hook which will print the stop message to System.err with the
113 * time then and the number of milliseconds passed since.
114 *
115 */
116 private static void printStartStopTimes() {
117 final long start = System.currentTimeMillis();
118
119 System.err.println("Start at " + new Date());
120
121 Thread hook = new Thread() {
122 @Override
123 public void run() {
124 long timePassed = System.currentTimeMillis() - start;
125 System.err.println("Stop at " + new Date()
126 + ", execution time = " + timePassed + " ms");
127 }
128 };
129 Runtime.getRuntime().addShutdownHook(hook);
130 }
131 }