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.rt;
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}