Home | History | Annotate | Download | only in agent
      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, Instrumentation instrumentation) {
     53 
     54         // We cannot do sanity checks for slf4j here as the jars loaded
     55         // by the application are not visible here.
     56 
     57         LogTransformer.Builder builder = new LogTransformer.Builder();
     58         builder = builder.addEntryExit(true);
     59 
     60         if (agentArgument != null) {
     61             Properties args = parseArguments(agentArgument, ",");
     62 
     63             if (args.containsKey(AgentOptions.VERBOSE)) {
     64                 builder = builder.verbose(true);
     65             }
     66 
     67             if (args.containsKey(AgentOptions.TIME)) {
     68                 printStartStopTimes();
     69             }
     70 
     71             if (args.containsKey(AgentOptions.IGNORE)) {
     72                 String ignore = args.getProperty(AgentOptions.IGNORE);
     73                 builder = builder.ignore(ignore.split(":"));
     74             }
     75 
     76             if (args.containsKey(AgentOptions.LEVEL)) {
     77                 builder = builder.level(args.getProperty(AgentOptions.LEVEL));
     78             }
     79         }
     80 
     81         instrumentation.addTransformer(builder.build());
     82     }
     83 
     84     /**
     85      * Consider the argument string to be a property file (by converting the
     86      * splitter character to line feeds), and then reading it like any other
     87      * property file.
     88      *
     89      *
     90      * @param agentArgument
     91      *            string given by instrumentation framework
     92      * @param separator
     93      *            String to convert to line feeds
     94      * @return argument converted to properties
     95      */
     96     private static Properties parseArguments(String agentArgument, String separator) {
     97         Properties p = new Properties();
     98         try {
     99             String argumentAsLines = agentArgument.replaceAll(separator, "\n");
    100             p.load(new ByteArrayInputStream(argumentAsLines.getBytes()));
    101         } catch (IOException e) {
    102             String s = "Could not load arguments as properties";
    103             throw new RuntimeException(s, e);
    104         }
    105         return p;
    106     }
    107 
    108     /**
    109      * Print the start message to System.err with the time NOW, and register a
    110      * shutdown hook which will print the stop message to System.err with the
    111      * time then and the number of milliseconds passed since.
    112      *
    113      */
    114     private static void printStartStopTimes() {
    115         final long start = System.currentTimeMillis();
    116 
    117         System.err.println("Start at " + new Date());
    118 
    119         Thread hook = new Thread() {
    120             @Override
    121             public void run() {
    122                 long timePassed = System.currentTimeMillis() - start;
    123                 System.err.println("Stop at " + new Date() + ", execution time = " + timePassed + " ms");
    124             }
    125         };
    126         Runtime.getRuntime().addShutdownHook(hook);
    127     }
    128 }