JacocoAgent.java

    1/*******************************************************************************
    2 * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others
    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.LoggerRuntime;
   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 agentArgs
   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 callback
   64     */
   65    public void init(final Instrumentation inst) {
   66        runtime = createRuntime();
   67        runtime.startup();
   68        inst.addTransformer(new CoverageTransformer(runtime, options));
   69    }
   70
   71    /**
   72     * Creates the specific coverage runtime implementation.
   73     * 
   74     * @return coverage runtime instance
   75     */
   76    protected IRuntime createRuntime() {
   77        return new LoggerRuntime();
   78    }
   79
   80    /**
   81     * Shutdown the agent again.
   82     */
   83    public void shutdown() {
   84        writeExecutionData();
   85    }
   86
   87    /**
   88     * Writes the collected execution data to the specified file.
   89     * 
   90     * @param runtime
   91     *            runtime containing the execution data
   92     */
   93    protected void writeExecutionData() {
   94        try {
   95            File execFile = new File(options.getFile()).getAbsoluteFile();
   96            File folder = execFile.getParentFile();
   97            if (folder != null) {
   98                folder.mkdirs();
   99            }
  100            OutputStream output = new BufferedOutputStream(
  101                    new FileOutputStream(execFile, options.getMerge()));
  102            ExecutionDataWriter writer = new ExecutionDataWriter(output);
  103            writer.writeHeader();
  104            runtime.collect(writer, false);
  105            output.close();
  106        } catch (IOException e) {
  107            e.printStackTrace();
  108        }
  109    }
  110
  111    /**
  112     * This method is called by the JVM to initialize Java agents.
  113     * 
  114     * @param options
  115     *            agent options
  116     * @param inst
  117     *            intrumentation callback provided by the JVM
  118     */
  119    public static void premain(final String options, final Instrumentation inst) {
  120        final JacocoAgent agent = new JacocoAgent(options);
  121        agent.init(inst);
  122
  123        Runtime.getRuntime().addShutdownHook(new Thread() {
  124            @Override
  125            public void run() {
  126                agent.shutdown();
  127            }
  128        });
  129    }
  130
  131}