1 /******************************************************************************* 2 * Copyright (c) 2009, 2021 Mountainminds GmbH & Co. KG and Contributors 3 * This program and the accompanying materials are made available under 4 * the terms of the Eclipse Public License 2.0 which is available at 5 * http://www.eclipse.org/legal/epl-2.0 6 * 7 * SPDX-License-Identifier: EPL-2.0 8 * 9 * Contributors: 10 * Marc R. Hoffmann - initial API and implementation 11 * 12 *******************************************************************************/ 13 package org.jacoco.core.test; 14 15 import java.io.ByteArrayOutputStream; 16 import java.io.IOException; 17 import java.io.InputStream; 18 import java.util.HashMap; 19 import java.util.Map; 20 21 /** 22 * Loads given classes from a byte arrays. 23 */ 24 public class TargetLoader extends ClassLoader { 25 26 private final Map<String, byte[]> classes; 27 TargetLoader()28 public TargetLoader() { 29 super(TargetLoader.class.getClassLoader()); 30 this.classes = new HashMap<String, byte[]>(); 31 } 32 add(final String name, final byte[] bytes)33 public Class<?> add(final String name, final byte[] bytes) { 34 this.classes.put(name, bytes); 35 return load(name); 36 } 37 add(final Class<?> name, final byte[] bytes)38 public Class<?> add(final Class<?> name, final byte[] bytes) { 39 return add(name.getName(), bytes); 40 } 41 load(final String sourcename)42 private Class<?> load(final String sourcename) { 43 try { 44 return loadClass(sourcename); 45 } catch (ClassNotFoundException e) { 46 // must not happen 47 throw new RuntimeException(e); 48 } 49 } 50 getClassData(Class<?> clazz)51 public static InputStream getClassData(Class<?> clazz) { 52 return getClassData(clazz.getClassLoader(), clazz.getName()); 53 } 54 getClassData(ClassLoader loader, String name)55 public static InputStream getClassData(ClassLoader loader, String name) { 56 final String resource = name.replace('.', '/') + ".class"; 57 return loader.getResourceAsStream(resource); 58 } 59 getClassDataAsBytes(ClassLoader loader, String name)60 public static byte[] getClassDataAsBytes(ClassLoader loader, String name) 61 throws IOException { 62 return readBytes(getClassData(loader, name)); 63 } 64 getClassDataAsBytes(Class<?> clazz)65 public static byte[] getClassDataAsBytes(Class<?> clazz) 66 throws IOException { 67 return readBytes(getClassData(clazz)); 68 } 69 readBytes(InputStream in)70 private static byte[] readBytes(InputStream in) throws IOException { 71 ByteArrayOutputStream out = new ByteArrayOutputStream(); 72 byte[] buffer = new byte[0x100]; 73 int len; 74 while ((len = in.read(buffer)) != -1) { 75 out.write(buffer, 0, len); 76 } 77 in.close(); 78 return out.toByteArray(); 79 } 80 81 @Override loadClass(String name, boolean resolve)82 protected synchronized Class<?> loadClass(String name, boolean resolve) 83 throws ClassNotFoundException { 84 final byte[] bytes = classes.get(name); 85 if (bytes != null) { 86 Class<?> c = defineClass(name, bytes, 0, bytes.length); 87 if (resolve) { 88 resolveClass(c); 89 } 90 return c; 91 } 92 return super.loadClass(name, resolve); 93 } 94 95 } 96