JacocoAgent.java

    1/*******************************************************************************
    2 * Copyright (c) 2009, 2010 Mountainminds GmbH & Co. KG and Contributors
    3 * All rights reserved. This program and the accompanying materials
    4 * are made available under the terms of the Eclipse Public License v1.0
    5 * which accompanies this distribution, and is available at
    6 * http://www.eclipse.org/legal/epl-v10.html
    7 *
    8 * Contributors:
    9 *    Marc R. Hoffmann - initial API and implementation
   10 *    
   11 * $Id: $
   12 *******************************************************************************/
   13package org.jacoco.agent.rt;
   14
   15import java.io.BufferedOutputStream;
   16import java.io.File;
   17import java.io.FileOutputStream;
   18import java.io.IOException;
   19import java.io.OutputStream;
   20import java.lang.instrument.Instrumentation;
   21
   22import org.jacoco.core.data.ExecutionDataWriter;
   23import org.jacoco.core.runtime.AgentOptions;
   24import org.jacoco.core.runtime.IRuntime;
   25import org.jacoco.core.runtime.ModifiedSystemClassRuntime;
   26
   27/**
   28 * The agent which is referred as the <code>Premain-Class</code>.
   29 * 
   30 * @author Marc R. Hoffmann
   31 * @version $Revision: $
   32 */
   33public class JacocoAgent {
   34
   35    private final AgentOptions options;
   36
   37    private IRuntime runtime;
   38
   39    /**
   40     * Creates a new agent with the given agent options.
   41     * 
   42     * @param options
   43     *            agent options
   44     */
   45    public JacocoAgent(AgentOptions options) {
   46        this.options = options;
   47    }
   48
   49    /**
   50     * Creates a new agent with the given agent options string.
   51     * 
   52     * @param options
   53     *            agent options as text string
   54     */
   55    public JacocoAgent(String options) {
   56        this(new AgentOptions(options));
   57    }
   58
   59    /**
   60     * Initializes this agent.
   61     * 
   62     * @param inst
   63     *            instrumentation services
   64     * @throws Exception
   65     *             internal startup problem
   66     */
   67    public void init(final Instrumentation inst) throws Exception {
   68        runtime = createRuntime(inst);
   69        runtime.startup();
   70        inst.addTransformer(new CoverageTransformer(runtime, options));
   71    }
   72
   73    /**
   74     * Creates the specific coverage runtime implementation.
   75     * 
   76     * @param inst
   77     *            instrumentation services
   78     * @return coverage runtime instance
   79     * @throws Exception
   80     *             creation problem
   81     */
   82    protected IRuntime createRuntime(final Instrumentation inst)
   83            throws Exception {
   84        return ModifiedSystemClassRuntime.createFor(inst, "java/sql/Types");
   85    }
   86
   87    /**
   88     * Shutdown the agent again.
   89     */
   90    public void shutdown() {
   91        writeExecutionData();
   92    }
   93
   94    /**
   95     * Writes the collected execution data to the specified file.
   96     */
   97    protected void writeExecutionData() {
   98        try {
   99            File execFile = new File(options.getDestfile()).getAbsoluteFile();
  100            File folder = execFile.getParentFile();
  101            if (folder != null) {
  102                folder.mkdirs();
  103            }
  104            OutputStream output = new BufferedOutputStream(
  105                    new FileOutputStream(execFile, options.getAppend()));
  106            ExecutionDataWriter writer = new ExecutionDataWriter(output);
  107            writer.writeHeader();
  108            runtime.collect(writer, false);
  109            output.close();
  110        } catch (IOException e) {
  111            e.printStackTrace();
  112        }
  113    }
  114
  115    /**
  116     * This method is called by the JVM to initialize Java agents.
  117     * 
  118     * @param options
  119     *            agent options
  120     * @param inst
  121     *            intrumentation callback provided by the JVM
  122     */
  123    public static void premain(final String options, final Instrumentation inst)
  124            throws Exception {
  125        final JacocoAgent agent = new JacocoAgent(options);
  126        agent.init(inst);
  127
  128        Runtime.getRuntime().addShutdownHook(new Thread() {
  129            @Override
  130            public void run() {
  131                agent.shutdown();
  132            }
  133        });
  134    }
  135
  136}