• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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