Instrumenter.java revision 1b885c7bc666c215c3947ad4d12099273a5f533f
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 $qualified.bundle.version$
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}
100