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 *******************************************************************************/
   12package org.jacoco.core.instr;
   13
   14import java.io.IOException;
   15import java.io.InputStream;
   16
   17import org.jacoco.core.runtime.IRuntime;
   18import org.objectweb.asm.ClassReader;
   19import org.objectweb.asm.ClassVisitor;
   20import org.objectweb.asm.ClassWriter;
   21
   22/**
   23 * Several APIs to instrument Java class definitions for coverage tracing.
   24 * 
   25 * @author Marc R. Hoffmann
   26 * @version 0.4.1.20101007204400
   27 */
   28public class Instrumenter {
   29
   30    private final IRuntime runtime;
   31
   32    /**
   33     * Creates a new instance based on the given runtime.
   34     * 
   35     * @param runtime
   36     *            runtime used by the instrumented classes
   37     */
   38    public Instrumenter(final IRuntime runtime) {
   39        this.runtime = runtime;
   40    }
   41
   42    /**
   43     * Creates a ASM adapter for a class with the given id.
   44     * 
   45     * @param classid
   46     *            id of the class calculated with {@link CRC64}
   47     * @param cv
   48     *            next class visitor in the chain
   49     * @return new visitor to write class definition to
   50     */
   51    public ClassVisitor createInstrumentingVisitor(final long classid,
   52            final ClassVisitor cv) {
   53        return new BlockClassAdapter(
   54                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}