AgentOptions.java revision 578947ead80e839a698736693a6c8bf724f5eaab
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 static java.lang.String.format; 16 17import java.io.File; 18import java.util.Arrays; 19import java.util.Collection; 20import java.util.HashMap; 21import java.util.Map; 22 23/** 24 * Utility to create and parse options for the runtime agent. Options are 25 * represented as a string in the following format: 26 * 27 * <pre> 28 * key1=value1,key2=value2,key3=value3 29 * </pre> 30 * 31 * @author Marc R. Hoffmann 32 * @version $Revision: $ 33 */ 34public class AgentOptions { 35 36 /** 37 * Specifies the output file for execution data. Default is 38 * <code>jacoco.exec</code> in the working directory. 39 */ 40 public static final String DESTFILE = "destfile"; 41 42 /** 43 * Specifies whether execution data should be appended to the output file. 44 * Default is <code>true</code>. 45 */ 46 public static final String APPEND = "append"; 47 48 /** 49 * Wildcard expression for class names that should be included for code 50 * coverage. Default is <code>*</code> (all classes included). 51 * 52 * @see WildcardMatcher 53 */ 54 public static final String INCLUDES = "includes"; 55 56 /** 57 * Wildcard expression for class names that should be excluded from code 58 * coverage. Default is the empty string (no exclusions). 59 * 60 * @see WildcardMatcher 61 */ 62 public static final String EXCLUDES = "excludes"; 63 64 /** 65 * Wildcard expression for class loaders names for classes that should be 66 * excluded from code coverage. This means all classes loaded by a class 67 * loader which full qualified name matches this expression will be ignored 68 * for code coverage regardless of all other filtering settings. Default is 69 * <code>sun.reflect.DelegatingClassLoader</code>. 70 * 71 * @see WildcardMatcher 72 */ 73 public static final String EXCLCLASSLOADER = "exclclassloader"; 74 75 private static final Collection<String> VALID_OPTIONS = Arrays.asList( 76 DESTFILE, APPEND, INCLUDES, EXCLUDES, EXCLCLASSLOADER); 77 78 private final Map<String, String> options; 79 80 /** 81 * New instance with all values set to default. 82 */ 83 public AgentOptions() { 84 this.options = new HashMap<String, String>(); 85 } 86 87 /** 88 * New instance parsed from the given option string. 89 * 90 * @param optionstr 91 * string to parse or <code>null</code> 92 */ 93 public AgentOptions(final String optionstr) { 94 this(); 95 if (optionstr != null && optionstr.length() > 0) { 96 for (final String entry : optionstr.split(",")) { 97 final int pos = entry.indexOf('='); 98 if (pos == -1) { 99 throw new IllegalArgumentException(format( 100 "Invalid agent option syntax \"%s\".", optionstr)); 101 } 102 final String key = entry.substring(0, pos); 103 if (!VALID_OPTIONS.contains(key)) { 104 throw new IllegalArgumentException(format( 105 "Unknown agent option \"%s\".", key)); 106 } 107 options.put(key, entry.substring(pos + 1)); 108 } 109 } 110 } 111 112 /** 113 * Returns the output file location. 114 * 115 * @return output file location 116 */ 117 public String getDestfile() { 118 final String destfile = options.get(DESTFILE); 119 return destfile == null ? "jacoco.exec" : destfile; 120 } 121 122 /** 123 * Sets the output file location. 124 * 125 * @param destfile 126 * output file location 127 */ 128 public void setDestfile(final String destfile) { 129 setOption(DESTFILE, destfile); 130 } 131 132 /** 133 * Returns whether the output should be appended to an existing file. 134 * 135 * @return <code>true</code>, when the output should be appended 136 */ 137 public boolean getAppend() { 138 final String value = options.get(APPEND); 139 return value == null ? true : Boolean.parseBoolean(value); 140 } 141 142 /** 143 * Sets whether the output should be appended to an existing file. 144 * 145 * @param append 146 * <code>true</code>, when the output should be appended 147 */ 148 public void setAppend(final boolean append) { 149 setOption(APPEND, String.valueOf(append)); 150 } 151 152 /** 153 * Returns the wildcard expression for classes to include. 154 * 155 * @return wildcard expression for classes to include 156 * @see WildcardMatcher 157 */ 158 public String getIncludes() { 159 final String value = options.get(INCLUDES); 160 return value == null ? "*" : value; 161 } 162 163 /** 164 * Sets the wildcard expression for classes to include. 165 * 166 * @param includes 167 * wildcard expression for classes to include 168 * @see WildcardMatcher 169 */ 170 public void setIncludes(final String includes) { 171 setOption(INCLUDES, includes); 172 } 173 174 /** 175 * Returns the wildcard expression for classes to exclude. 176 * 177 * @return wildcard expression for classes to exclude 178 * @see WildcardMatcher 179 */ 180 public String getExcludes() { 181 final String value = options.get(EXCLUDES); 182 return value == null ? "" : value; 183 } 184 185 /** 186 * Sets the wildcard expression for classes to exclude. 187 * 188 * @param excludes 189 * wildcard expression for classes to exclude 190 * @see WildcardMatcher 191 */ 192 public void setExcludes(final String excludes) { 193 setOption(EXCLUDES, excludes); 194 } 195 196 /** 197 * Returns the wildcard expression for excluded class loaders. 198 * 199 * @return expression for excluded class loaders 200 * @see WildcardMatcher 201 */ 202 public String getExclClassloader() { 203 final String value = options.get(EXCLCLASSLOADER); 204 return value == null ? "sun.reflect.DelegatingClassLoader" : value; 205 } 206 207 /** 208 * Sets the wildcard expression for excluded class loaders. 209 * 210 * @param expression 211 * expression for excluded class loaders 212 * @see WildcardMatcher 213 */ 214 public void setExclClassloader(final String expression) { 215 setOption(EXCLCLASSLOADER, expression); 216 } 217 218 private void setOption(final String key, final String value) { 219 if (value.contains(",")) { 220 throw new IllegalArgumentException(format( 221 "Invalid character in option argument \"%s\"", value)); 222 } 223 options.put(key, value); 224 } 225 226 /** 227 * Generate required JVM argument string based on current configuration and 228 * supplied agent jar location 229 * 230 * @param agentJarFile 231 * location of the JaCoCo Agent Jar 232 * @return Argument to pass to create new VM with coverage enabled 233 */ 234 public String getVMArgument(final File agentJarFile) { 235 return format("-javaagent:%s=%s", agentJarFile, this); 236 } 237 238 /** 239 * Creates a string representation that can be passed to the agent via the 240 * command line. Might be the empty string, if no options are set. 241 */ 242 @Override 243 public String toString() { 244 final StringBuilder sb = new StringBuilder(); 245 for (final String key : VALID_OPTIONS) { 246 final String value = options.get(key); 247 if (value != null) { 248 if (sb.length() > 0) { 249 sb.append(','); 250 } 251 sb.append(key).append('=').append(value); 252 } 253 } 254 return sb.toString(); 255 } 256 257} 258