SystemPropertiesRuntime.java revision 402370f12bbe40b6438e06b788c6a4273c6294fd
1/******************************************************************************* 2 * Copyright (c) 2009 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.Arrays; 16import java.util.Collections; 17import java.util.HashMap; 18import java.util.Map; 19 20import org.jacoco.core.data.IExecutionDataVisitor; 21import org.jacoco.core.instr.GeneratorConstants; 22import org.objectweb.asm.Opcodes; 23import org.objectweb.asm.commons.GeneratorAdapter; 24 25/** 26 * This {@link IRuntime} implementation places the coverage data in the 27 * {@link System#getProperties()} hash table. The advantage is, that the 28 * instrumented classes do not get dependencies to other classes than the JRE 29 * library itself. 30 * 31 * This runtime may cause problems in environments with security restrictions, 32 * in applications that replace the system properties or in applications that 33 * fail if non-String values are placed in the system properties. 34 * 35 * 36 * @author Marc R. Hoffmann 37 * @version $Revision: $ 38 */ 39public class SystemPropertiesRuntime implements IRuntime { 40 41 private static final String KEYPREFIX = "jacoco-"; 42 43 private final String key; 44 45 /** 46 * Creates a new runtime. 47 */ 48 public SystemPropertiesRuntime() { 49 this.key = KEYPREFIX + hashCode(); 50 } 51 52 // TODO: lokale Variable vermeiden (swap!) 53 public void generateRegistration(final long classId, 54 final GeneratorAdapter gen) { 55 56 // boolean[][] data = pop() 57 final int data = gen.newLocal(GeneratorConstants.DATAFIELD_TYPE); 58 gen.storeLocal(data); 59 60 // stack := System.getProperties() 61 gen.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", 62 "getProperties", "()Ljava/util/Properties;"); 63 64 // stack := stack.get(key) 65 gen.push(key); 66 gen.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/Properties", 67 "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); 68 gen.visitTypeInsn(Opcodes.CHECKCAST, "java/util/Map"); 69 70 // stack.put(classId, data) 71 gen.push(classId); 72 gen.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", 73 "(J)Ljava/lang/Long;"); 74 75 gen.loadLocal(data); 76 gen.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Map", "put", 77 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); 78 gen.pop(); 79 } 80 81 public void startup() { 82 final Map<Long, boolean[][]> dataMap = Collections 83 .synchronizedMap(new HashMap<Long, boolean[][]>()); 84 System.getProperties().put(key, dataMap); 85 } 86 87 @SuppressWarnings("unchecked") 88 private Map<Long, boolean[][]> getDataMap() { 89 final Object object = System.getProperties().get(key); 90 if (object == null) { 91 throw new IllegalStateException("Runtime not started."); 92 } 93 return (Map<Long, boolean[][]>) object; 94 } 95 96 public void collect(final IExecutionDataVisitor visitor, final boolean reset) { 97 final Map<Long, boolean[][]> dataMap = getDataMap(); 98 synchronized (dataMap) { 99 for (final Map.Entry<Long, boolean[][]> entry : dataMap.entrySet()) { 100 final long classId = entry.getKey().longValue(); 101 final boolean[][] blockData = entry.getValue(); 102 visitor.visitClassExecution(classId, blockData); 103 } 104 if (reset) { 105 reset(); 106 } 107 } 108 } 109 110 public void reset() { 111 final Map<Long, boolean[][]> dataMap = getDataMap(); 112 synchronized (dataMap) { 113 for (final boolean[][] data : dataMap.values()) { 114 for (final boolean[] arr : data) { 115 Arrays.fill(arr, false); 116 } 117 } 118 } 119 } 120 121 public void shutdown() { 122 System.getProperties().remove(key); 123 } 124 125} 126