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