1e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov/******************************************************************************* 2398ee59bebad6835dab57b60157eff16d511709eMarc R. Hoffmann * Copyright (c) 2009, 2015 Mountainminds GmbH & Co. KG and Contributors 3e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * All rights reserved. This program and the accompanying materials 4e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * are made available under the terms of the Eclipse Public License v1.0 5e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * which accompanies this distribution, and is available at 6e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * http://www.eclipse.org/legal/epl-v10.html 7e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 8e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Contributors: 9e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Marc R. Hoffmann - initial API and implementation 10e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 11e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov *******************************************************************************/ 12e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovpackage org.jacoco.core.test; 13e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 14e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport java.io.ByteArrayOutputStream; 15e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport java.io.IOException; 16e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport java.io.InputStream; 179d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmannimport java.util.HashMap; 189d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmannimport java.util.Map; 19e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 20e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov/** 21e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Loads a single class from a byte array. 22e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */ 23e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovpublic class TargetLoader extends ClassLoader { 24e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 259d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmann private final Map<String, byte[]> classes; 26e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 279d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmann public TargetLoader() { 289d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmann super(TargetLoader.class.getClassLoader()); 299d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmann this.classes = new HashMap<String, byte[]>(); 309d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmann } 31e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 329d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmann public Class<?> add(final String name, final byte[] bytes) { 339d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmann this.classes.put(name, bytes); 349d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmann return load(name); 359d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmann } 36e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 379d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmann public Class<?> add(final Class<?> name, final byte[] bytes) { 389d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmann return add(name.getName(), bytes); 39e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 40e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 419d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmann public Class<?> add(final Class<?> source) throws IOException { 429d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmann return add(source.getName(), getClassDataAsBytes(source)); 43e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 44e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 45e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov private Class<?> load(final String sourcename) { 46e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov try { 47e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov return loadClass(sourcename); 48e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } catch (ClassNotFoundException e) { 49e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov // must not happen 50e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov throw new RuntimeException(e); 51e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 52e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 53e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 54e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public static InputStream getClassData(Class<?> clazz) { 55e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov final String resource = "/" + clazz.getName().replace('.', '/') 56e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov + ".class"; 57e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov return clazz.getResourceAsStream(resource); 58e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 59e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 60e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public static byte[] getClassDataAsBytes(Class<?> clazz) throws IOException { 61e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov InputStream in = getClassData(clazz); 62e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov ByteArrayOutputStream out = new ByteArrayOutputStream(); 63e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov byte[] buffer = new byte[0x100]; 64e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov int len; 65e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov while ((len = in.read(buffer)) != -1) { 66e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov out.write(buffer, 0, len); 67e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 68e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov in.close(); 69e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov return out.toByteArray(); 70e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 71e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 72e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov @Override 73e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov protected synchronized Class<?> loadClass(String name, boolean resolve) 74e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov throws ClassNotFoundException { 759d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmann final byte[] bytes = classes.get(name); 769d79259f33e7117a4bf4ec1db2848e9429455325Marc R. Hoffmann if (bytes != null) { 77e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov Class<?> c = defineClass(name, bytes, 0, bytes.length); 78e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov if (resolve) { 79e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov resolveClass(c); 80e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 81e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov return c; 82e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 83e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov return super.loadClass(name, resolve); 84e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 85e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 86e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov} 87