CoverageTransformer.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;
   14
   15import java.lang.instrument.ClassFileTransformer;
   16import java.lang.instrument.IllegalClassFormatException;
   17import java.security.ProtectionDomain;
   18
   19import org.jacoco.core.instr.Instrumenter;
   20import org.jacoco.core.runtime.AgentOptions;
   21import org.jacoco.core.runtime.IRuntime;
   22import org.jacoco.core.runtime.WildcardMatcher;
   23
   24/**
   25 * Class file transformer to instrument classes for code coverage analysis.
   26 * 
   27 * @author Marc R. Hoffmann
   28 * @version $Revision: $
   29 */
   30public class CoverageTransformer implements ClassFileTransformer {
   31
   32    private final Instrumenter instrumenter;
   33
   34    private final WildcardMatcher includes;
   35
   36    private final WildcardMatcher excludes;
   37
   38    private final WildcardMatcher exclClassloader;
   39
   40    public CoverageTransformer(IRuntime runtime, AgentOptions options) {
   41        this.instrumenter = new Instrumenter(runtime);
   42        // Class names will be reported in VM notation:
   43        includes = new WildcardMatcher(options.getIncludes().replace('.', '/'));
   44        excludes = new WildcardMatcher(options.getExcludes().replace('.', '/'));
   45        exclClassloader = new WildcardMatcher(options.getExclClassloader());
   46    }
   47
   48    public byte[] transform(ClassLoader loader, String classname,
   49            Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
   50            byte[] classfileBuffer) throws IllegalClassFormatException {
   51
   52        if (!filter(loader, classname)) {
   53            return null;
   54        }
   55
   56        try {
   57            return instrumenter.instrument(classfileBuffer);
   58        } catch (Throwable t) {
   59            t.printStackTrace();
   60            return null;
   61        }
   62    }
   63
   64    /**
   65     * Checks whether this class should be instrumented.
   66     * 
   67     * @param loader
   68     *            loader for the class
   69     * @return <code>true</code> if the class should be instrumented
   70     */
   71    protected boolean filter(ClassLoader loader, String classname) {
   72        // Don't instrument classes of the bootstrap loader:
   73        return loader != null &&
   74
   75        !exclClassloader.matches(loader.getClass().getName()) &&
   76
   77        includes.matches(classname) &&
   78
   79        !excludes.matches(classname);
   80    }
   81}