SystemPropertiesRuntime.java
1/*******************************************************************************
2 * Copyright (c) 2009, 2010 Mountainminds GmbH & Co. KG and others
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 * $Id: $
12 *******************************************************************************/
13package org.jacoco.core.runtime;
14
15import java.util.Map;
16
17import org.jacoco.core.instr.GeneratorConstants;
18import org.objectweb.asm.MethodVisitor;
19import org.objectweb.asm.Opcodes;
20
21/**
22 * This {@link IRuntime} implementation makes the execution data available
23 * through a special entry of the type {@link Map} in the
24 * {@link System#getProperties()} hash table. The advantage is, that the
25 * instrumented classes do not get dependencies to other classes than the JRE
26 * library itself.
27 *
28 * This runtime may cause problems in environments with security restrictions,
29 * in applications that replace the system properties or in applications that
30 * fail if non-String values are placed in the system properties.
31 *
32 * @author Marc R. Hoffmann
33 * @version $Revision: $
34 */
35public class SystemPropertiesRuntime extends AbstractRuntime {
36
37 private static final String KEYPREFIX = "jacoco-";
38
39 private final String key;
40
41 private final Map<Long, boolean[]> dataAccess = new MapAdapter(store);
42
43 /**
44 * Creates a new runtime.
45 */
46 public SystemPropertiesRuntime() {
47 this.key = KEYPREFIX + hashCode();
48 }
49
50 public int generateDataAccessor(final long classid, final MethodVisitor mv) {
51
52 mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System",
53 "getProperties", "()Ljava/util/Properties;");
54
55 // Stack[0]: Ljava/util/Properties;
56
57 mv.visitLdcInsn(key);
58
59 // Stack[1]: Ljava/lang/String;
60 // Stack[0]: Ljava/util/Properties;
61
62 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/Properties",
63 "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
64
65 // Stack[0]: Ljava/lang/Object;
66
67 mv.visitTypeInsn(Opcodes.CHECKCAST, "java/util/Map");
68
69 // Stack[0]: Ljava/util/Map;
70
71 mv.visitLdcInsn(Long.valueOf(classid));
72
73 // Stack[2]: J
74 // Stack[1]: .
75 // Stack[0]: Ljava/util/Map;
76
77 mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf",
78 "(J)Ljava/lang/Long;");
79
80 // Stack[1]: Ljava/lang/Long;
81 // Stack[0]: Ljava/util/Map;
82
83 mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Map", "get",
84 "(Ljava/lang/Object;)Ljava/lang/Object;");
85
86 // Stack[0]: Ljava/lang/Object;
87
88 mv.visitTypeInsn(Opcodes.CHECKCAST, GeneratorConstants.PROBEDATA_TYPE
89 .getInternalName());
90
91 // Stack[0]: [Z
92
93 return 3; // Maximum local stack size is 3
94 }
95
96 public void startup() {
97 System.getProperties().put(key, dataAccess);
98 }
99
100 public void shutdown() {
101 System.getProperties().remove(key);
102 }
103
104}