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 }