1 /*******************************************************************************
2  * Copyright (c) 2009, 2015 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  *******************************************************************************/
12 package org.jacoco.core.test;
13 
14 import java.io.ByteArrayOutputStream;
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.util.HashMap;
18 import java.util.Map;
19 
20 /**
21  * Loads a single class from a byte array.
22  */
23 public class TargetLoader extends ClassLoader {
24 
25 	private final Map<String, byte[]> classes;
26 
TargetLoader()27 	public TargetLoader() {
28 		super(TargetLoader.class.getClassLoader());
29 		this.classes = new HashMap<String, byte[]>();
30 	}
31 
add(final String name, final byte[] bytes)32 	public Class<?> add(final String name, final byte[] bytes) {
33 		this.classes.put(name, bytes);
34 		return load(name);
35 	}
36 
add(final Class<?> name, final byte[] bytes)37 	public Class<?> add(final Class<?> name, final byte[] bytes) {
38 		return add(name.getName(), bytes);
39 	}
40 
add(final Class<?> source)41 	public Class<?> add(final Class<?> source) throws IOException {
42 		return add(source.getName(), getClassDataAsBytes(source));
43 	}
44 
load(final String sourcename)45 	private Class<?> load(final String sourcename) {
46 		try {
47 			return loadClass(sourcename);
48 		} catch (ClassNotFoundException e) {
49 			// must not happen
50 			throw new RuntimeException(e);
51 		}
52 	}
53 
getClassData(Class<?> clazz)54 	public static InputStream getClassData(Class<?> clazz) {
55 		final String resource = "/" + clazz.getName().replace('.', '/')
56 				+ ".class";
57 		return clazz.getResourceAsStream(resource);
58 	}
59 
getClassDataAsBytes(Class<?> clazz)60 	public static byte[] getClassDataAsBytes(Class<?> clazz) throws IOException {
61 		InputStream in = getClassData(clazz);
62 		ByteArrayOutputStream out = new ByteArrayOutputStream();
63 		byte[] buffer = new byte[0x100];
64 		int len;
65 		while ((len = in.read(buffer)) != -1) {
66 			out.write(buffer, 0, len);
67 		}
68 		in.close();
69 		return out.toByteArray();
70 	}
71 
72 	@Override
loadClass(String name, boolean resolve)73 	protected synchronized Class<?> loadClass(String name, boolean resolve)
74 			throws ClassNotFoundException {
75 		final byte[] bytes = classes.get(name);
76 		if (bytes != null) {
77 			Class<?> c = defineClass(name, bytes, 0, bytes.length);
78 			if (resolve) {
79 				resolveClass(c);
80 			}
81 			return c;
82 		}
83 		return super.loadClass(name, resolve);
84 	}
85 
86 }
87