AgentOptions.java
1/*******************************************************************************
2 * Copyright (c) 2009, 2010 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 * $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}