Instrumenter.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.core.instr;
   14
   15import java.io.IOException;
   16import java.io.InputStream;
   17
   18import org.jacoco.core.runtime.IRuntime;
   19import org.objectweb.asm.ClassReader;
   20import org.objectweb.asm.ClassVisitor;
   21import org.objectweb.asm.ClassWriter;
   22
   23/**
   24 * Several APIs to instrument Java class definitions for coverage tracing.
   25 * 
   26 * @author Marc R. Hoffmann
   27 * @version $Revision: $
   28 */
   29public class Instrumenter {
   30
   31    private final IRuntime runtime;
   32
   33    /**
   34     * Creates a new instance based on the given runtime.
   35     * 
   36     * @param runtime
   37     *            runtime used by the instrumented classes
   38     */
   39    public Instrumenter(final IRuntime runtime) {
   40        this.runtime = runtime;
   41    }
   42
   43    /**
   44     * Creates a ASM adapter for a class with the given id.
   45     * 
   46     * @param classid
   47     *            id of the class calculated with {@link CRC64}
   48     * @param cv
   49     *            next class visitor in the chain
   50     * @return new visitor to write class definition to
   51     */
   52    public ClassVisitor createInstrumentingVisitor(final long classid,
   53            final ClassVisitor cv) {
   54        return new ClassInstrumenter(classid, runtime, cv);
   55    }
   56
   57    /**
   58     * Creates a instrumented version of the given class if possible.
   59     * 
   60     * @param reader
   61     *            definition of the class as ASM reader
   62     * @return instrumented definition or <code>null</code>
   63     * 
   64     */
   65    public byte[] instrument(final ClassReader reader) {
   66        final ClassWriter writer = new ClassWriter(reader, 0);
   67        final ClassVisitor visitor = createInstrumentingVisitor(CRC64
   68                .checksum(reader.b), writer);
   69        reader.accept(visitor, ClassReader.EXPAND_FRAMES);
   70        return writer.toByteArray();
   71    }
   72
   73    /**
   74     * Creates a instrumented version of the given class if possible.
   75     * 
   76     * @param buffer
   77     *            definition of the class
   78     * @return instrumented definition or <code>null</code>
   79     * 
   80     */
   81    public byte[] instrument(final byte[] buffer) {
   82        return instrument(new ClassReader(buffer));
   83    }
   84
   85    /**
   86     * Creates a instrumented version of the given class if possible.
   87     * 
   88     * @param input
   89     *            stream to read class definition from
   90     * @return instrumented definition or <code>null</code>
   91     * @throws IOException
   92     *             if reading data from the stream fails
   93     * 
   94     */
   95    public byte[] instrument(final InputStream input) throws IOException {
   96        return instrument(new ClassReader(input));
   97    }
   98
   99}