1 /******************************************************************************* 2 * Copyright (c) 2009, 2018 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 * Evgeny Mandrikov - initial API and implementation 10 * 11 *******************************************************************************/ 12 package org.jacoco.core.test; 13 14 import java.io.IOException; 15 16 import org.jacoco.core.data.ExecutionDataStore; 17 import org.jacoco.core.data.SessionInfoStore; 18 import org.jacoco.core.instr.Instrumenter; 19 import org.jacoco.core.runtime.IRuntime; 20 import org.jacoco.core.runtime.RuntimeData; 21 import org.jacoco.core.runtime.SystemPropertiesRuntime; 22 23 /** 24 * Class loader which loads classes from another class loader and instruments 25 * them. 26 */ 27 public final class InstrumentingLoader extends ClassLoader { 28 29 private final IRuntime runtime; 30 private final String scope; 31 private final ClassLoader delegate; 32 33 private final RuntimeData data; 34 private final Instrumenter instrumenter; 35 36 public InstrumentingLoader(IRuntime runtime, String scope, 37 ClassLoader delegate) throws Exception { 38 this.runtime = runtime; 39 this.scope = scope; 40 this.delegate = delegate; 41 this.data = new RuntimeData(); 42 runtime.startup(data); 43 this.instrumenter = new Instrumenter(runtime); 44 } 45 46 public InstrumentingLoader(Class<?> target) throws Exception { 47 this(new SystemPropertiesRuntime(), target.getPackage().getName(), 48 target.getClassLoader()); 49 } 50 51 @Override 52 protected synchronized Class<?> loadClass(String name, boolean resolve) 53 throws ClassNotFoundException { 54 if (name.startsWith(scope)) { 55 final byte[] bytes; 56 try { 57 bytes = TargetLoader.getClassDataAsBytes(delegate, name); 58 } catch (IOException e) { 59 throw new ClassNotFoundException("Unable to load", e); 60 } 61 final byte[] instrumented; 62 try { 63 instrumented = instrumenter.instrument(bytes, name); 64 } catch (IOException e) { 65 throw new ClassNotFoundException("Unable to instrument", e); 66 } 67 final Class<?> c = defineClass(name, instrumented, 0, 68 instrumented.length); 69 if (resolve) { 70 resolveClass(c); 71 } 72 return c; 73 } 74 return super.loadClass(name, resolve); 75 } 76 77 public ExecutionDataStore collect() { 78 final ExecutionDataStore store = new ExecutionDataStore(); 79 data.collect(store, new SessionInfoStore(), false); 80 runtime.shutdown(); 81 return store; 82 } 83 84 } 85