View Javadoc

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 }