17ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu/** 27ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * Copyright (c) 2004-2011 QOS.ch 37ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * All rights reserved. 47ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * 57ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * Permission is hereby granted, free of charge, to any person obtaining 67ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * a copy of this software and associated documentation files (the 77ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * "Software"), to deal in the Software without restriction, including 87ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * without limitation the rights to use, copy, modify, merge, publish, 97ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * distribute, sublicense, and/or sell copies of the Software, and to 107ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * permit persons to whom the Software is furnished to do so, subject to 117ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * the following conditions: 127ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * 137ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * The above copyright notice and this permission notice shall be 147ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * included in all copies or substantial portions of the Software. 157ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * 167ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 177ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 187ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 197ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 207ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 217ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 227ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 237ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * 247ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu */ 25cdfaeefef04d5b1500e897ecc75982a5316407e8Thorbjorn Ravn Andersenpackage org.slf4j.agent; 26cdfaeefef04d5b1500e897ecc75982a5316407e8Thorbjorn Ravn Andersen 271adb4e0c1aa8507a14e69f57cb61698f9b0e0859Thorbjorn Ravn Andersenimport java.io.ByteArrayInputStream; 281adb4e0c1aa8507a14e69f57cb61698f9b0e0859Thorbjorn Ravn Andersenimport java.io.IOException; 29cdfaeefef04d5b1500e897ecc75982a5316407e8Thorbjorn Ravn Andersenimport java.lang.instrument.Instrumentation; 30cdfaeefef04d5b1500e897ecc75982a5316407e8Thorbjorn Ravn Andersenimport java.util.Date; 311adb4e0c1aa8507a14e69f57cb61698f9b0e0859Thorbjorn Ravn Andersenimport java.util.Properties; 32cdfaeefef04d5b1500e897ecc75982a5316407e8Thorbjorn Ravn Andersen 33cdfaeefef04d5b1500e897ecc75982a5316407e8Thorbjorn Ravn Andersenimport org.slf4j.instrumentation.LogTransformer; 34cdfaeefef04d5b1500e897ecc75982a5316407e8Thorbjorn Ravn Andersen 35fdb2c137a1e0917a356fe61846c4c406fb99fc7fThorbjorn Ravn Andersen/** 36fdb2c137a1e0917a356fe61846c4c406fb99fc7fThorbjorn Ravn Andersen * Entry point for slf4j-ext when used as a Java agent. 37a579aaf9c32a01a29111be23170824e6b0f3912aThorbjorn Ravn Andersen * 38fdb2c137a1e0917a356fe61846c4c406fb99fc7fThorbjorn Ravn Andersen */ 39cdfaeefef04d5b1500e897ecc75982a5316407e8Thorbjorn Ravn Andersenpublic class AgentPremain { 40cdfaeefef04d5b1500e897ecc75982a5316407e8Thorbjorn Ravn Andersen 4131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu /** 4231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * JavaAgent premain entry point as specified in the MANIFEST.MF file. See 4331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * {@link http 4431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * ://java.sun.com/javase/6/docs/api/java/lang/instrument/package- 4531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * summary.html} for details. 4631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * 4731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * @param agentArgument 4831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * string provided after "=" up to first space 4931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * @param instrumentation 5031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * instrumentation environment provided by the JVM 5131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu */ 5231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu public static void premain(String agentArgument, Instrumentation instrumentation) { 5331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu 5431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu // We cannot do sanity checks for slf4j here as the jars loaded 5531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu // by the application are not visible here. 5631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu 5731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu LogTransformer.Builder builder = new LogTransformer.Builder(); 5831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu builder = builder.addEntryExit(true); 5931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu 6031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (agentArgument != null) { 6131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Properties args = parseArguments(agentArgument, ","); 6231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu 6331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (args.containsKey(AgentOptions.VERBOSE)) { 6431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu builder = builder.verbose(true); 6531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 6631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu 6731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (args.containsKey(AgentOptions.TIME)) { 6831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu printStartStopTimes(); 6931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 7031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu 7131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (args.containsKey(AgentOptions.IGNORE)) { 7231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu String ignore = args.getProperty(AgentOptions.IGNORE); 7331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu builder = builder.ignore(ignore.split(":")); 7431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 7531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu 7631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (args.containsKey(AgentOptions.LEVEL)) { 7731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu builder = builder.level(args.getProperty(AgentOptions.LEVEL)); 7831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 7931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 8031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu 8131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu instrumentation.addTransformer(builder.build()); 8231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 8331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu 8431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu /** 8531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * Consider the argument string to be a property file (by converting the 8631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * splitter character to line feeds), and then reading it like any other 8731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * property file. 8831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * 8931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * 9031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * @param agentArgument 9131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * string given by instrumentation framework 9231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * @param separator 9331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * String to convert to line feeds 9431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * @return argument converted to properties 9531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu */ 9631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu private static Properties parseArguments(String agentArgument, String separator) { 9731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Properties p = new Properties(); 9831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu try { 9931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu String argumentAsLines = agentArgument.replaceAll(separator, "\n"); 10031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu p.load(new ByteArrayInputStream(argumentAsLines.getBytes())); 10131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } catch (IOException e) { 10231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu String s = "Could not load arguments as properties"; 10331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu throw new RuntimeException(s, e); 10431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 10531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu return p; 10631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 10731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu 10831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu /** 10931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * Print the start message to System.err with the time NOW, and register a 11031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * shutdown hook which will print the stop message to System.err with the 11131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * time then and the number of milliseconds passed since. 11231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * 11331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu */ 11431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu private static void printStartStopTimes() { 11531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu final long start = System.currentTimeMillis(); 11631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu 11731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu System.err.println("Start at " + new Date()); 11831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu 11931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Thread hook = new Thread() { 12031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu @Override 12131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu public void run() { 12231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu long timePassed = System.currentTimeMillis() - start; 12331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu System.err.println("Stop at " + new Date() + ", execution time = " + timePassed + " ms"); 12431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 12531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu }; 12631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Runtime.getRuntime().addShutdownHook(hook); 12731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 128cdfaeefef04d5b1500e897ecc75982a5316407e8Thorbjorn Ravn Andersen}