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 *******************************************************************************/
   12package org.jacoco.agent.rt;
   13
   14import java.lang.instrument.Instrumentation;
   15import java.net.InetAddress;
   16import java.net.UnknownHostException;
   17import java.util.Random;
   18
   19import org.jacoco.agent.rt.controller.IAgentController;
   20import org.jacoco.agent.rt.controller.LocalController;
   21import org.jacoco.agent.rt.controller.TcpClientController;
   22import org.jacoco.agent.rt.controller.TcpServerController;
   23import org.jacoco.core.runtime.AgentOptions;
   24import org.jacoco.core.runtime.IRuntime;
   25import org.jacoco.core.runtime.ModifiedSystemClassRuntime;
   26import org.jacoco.core.runtime.AgentOptions.OutputMode;
   27
   28/**
   29 * The agent which is referred as the <code>Premain-Class</code>.
   30 * 
   31 * @author Marc R. Hoffmann
   32 * @version 0.4.1.20101007204400
   33 */
   34public class JacocoAgent {
   35
   36    private final AgentOptions options;
   37
   38    private final IExceptionLogger logger;
   39
   40    private IRuntime runtime;
   41
   42    private IAgentController controller;
   43
   44    /**
   45     * Creates a new agent with the given agent options.
   46     * 
   47     * @param options
   48     *            agent options
   49     * @param logger
   50     *            logger used by this agent
   51     */
   52    public JacocoAgent(final AgentOptions options, final IExceptionLogger logger) {
   53        this.options = options;
   54        this.logger = logger;
   55    }
   56
   57    /**
   58     * Creates a new agent with the given agent options string.
   59     * 
   60     * @param options
   61     *            agent options as text string
   62     */
   63    public JacocoAgent(String options, IExceptionLogger logger) {
   64        this(new AgentOptions(options), logger);
   65    }
   66
   67    /**
   68     * Initializes this agent.
   69     * 
   70     * @param inst
   71     *            instrumentation services
   72     * @throws Exception
   73     *             internal startup problem
   74     */
   75    public void init(final Instrumentation inst) throws Exception {
   76        runtime = createRuntime(inst);
   77        String sessionId = options.getSessionId();
   78        if (sessionId == null) {
   79            sessionId = createSessionId();
   80        }
   81        runtime.setSessionId(sessionId);
   82        runtime.startup();
   83        inst.addTransformer(new CoverageTransformer(runtime, options, logger));
   84        controller = createAgentController();
   85        controller.startup(options, runtime);
   86    }
   87
   88    private IAgentController createAgentController() {
   89        OutputMode controllerType = options.getOutput();
   90        switch (controllerType) {
   91        case file:
   92            return new LocalController();
   93        case tcpserver:
   94            return new TcpServerController(logger);
   95        case tcpclient:
   96            return new TcpClientController(logger);
   97        default:
   98            throw new AssertionError(controllerType);
   99        }
  100    }
  101
  102    private String createSessionId() {
  103        String host;
  104        try {
  105            host = InetAddress.getLocalHost().getHostName();
  106        } catch (UnknownHostException e) {
  107            host = "unknownhost";
  108        }
  109        return host + "-" + Integer.toHexString(new Random().nextInt());
  110    }
  111
  112    /**
  113     * Creates the specific coverage runtime implementation.
  114     * 
  115     * @param inst
  116     *            instrumentation services
  117     * @return coverage runtime instance
  118     * @throws Exception
  119     *             creation problem
  120     */
  121    protected IRuntime createRuntime(final Instrumentation inst)
  122            throws Exception {
  123        return ModifiedSystemClassRuntime.createFor(inst, "java/sql/Types");
  124    }
  125
  126    /**
  127     * Shutdown the agent again.
  128     */
  129    public void shutdown() {
  130        try {
  131            if (options.getDumpOnExit()) {
  132                controller.writeExecutionData();
  133            }
  134            controller.shutdown();
  135        } catch (Exception e) {
  136            logger.logExeption(e);
  137        }
  138    }
  139
  140    /**
  141     * This method is called by the JVM to initialize Java agents.
  142     * 
  143     * @param options
  144     *            agent options
  145     * @param inst
  146     *            instrumentation callback provided by the JVM
  147     */
  148    public static void premain(final String options, final Instrumentation inst)
  149            throws Exception {
  150
  151        final JacocoAgent agent = new JacocoAgent(options,
  152                new IExceptionLogger() {
  153                    public void logExeption(Exception ex) {
  154                        ex.printStackTrace();
  155                    }
  156                });
  157
  158        agent.init(inst);
  159
  160        Runtime.getRuntime().addShutdownHook(new Thread() {
  161            @Override
  162            public void run() {
  163                agent.shutdown();
  164            }
  165        });
  166    }
  167
  168}