001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
019 */
020 package org.sonar.plugins.jacoco;
021
022 import org.apache.commons.lang.StringUtils;
023 import org.jacoco.core.runtime.AgentOptions;
024 import org.sonar.api.BatchExtension;
025 import org.sonar.api.Properties;
026 import org.sonar.api.Property;
027 import org.sonar.api.config.Settings;
028
029 @Properties({
030 @Property(
031 key = JacocoConfiguration.REPORT_PATH_PROPERTY,
032 name = "File with execution data",
033 defaultValue = JacocoConfiguration.REPORT_PATH_DEFAULT_VALUE,
034 description = "Path (absolute or relative) to the file with execution data.",
035 global = false,
036 module = true,
037 project = true
038 ),
039 @Property(
040 key = JacocoConfiguration.INCLUDES_PROPERTY,
041 name = "Includes",
042 description = "A list of class names that should be included in execution analysis." +
043 " The list entries are separated by a colon (:) and may use wildcard characters (* and ?)." +
044 " Except for performance optimization or technical corner cases this option is normally not required.",
045 global = true,
046 project = true,
047 module = true
048 ),
049 @Property(
050 key = JacocoConfiguration.EXCLUDES_PROPERTY,
051 name = "Excludes",
052 defaultValue = JacocoConfiguration.EXCLUDES_DEFAULT_VALUE,
053 description = "A list of class names that should be excluded from execution analysis." +
054 " The list entries are separated by a colon (:) and may use wildcard characters (* and ?)." +
055 " Except for performance optimization or technical corner cases this option is normally not required.",
056 global = true,
057 project = true,
058 module = true
059 ),
060 @Property(
061 key = JacocoConfiguration.EXCLCLASSLOADER_PROPERTY,
062 name = "Excluded class loaders",
063 description = "A list of class loader names that should be excluded from execution analysis." +
064 " The list entries are separated by a colon (:) and may use wildcard characters (* and ?)." +
065 " This option might be required in case of special frameworks that conflict with JaCoCo code" +
066 " instrumentation, in particular class loaders that do not have access to the Java runtime classes.",
067 global = true,
068 project = true,
069 module = true
070 ),
071 @Property(
072 key = JacocoConfiguration.IT_REPORT_PATH_PROPERTY,
073 name = "File with execution data for integration tests",
074 defaultValue = JacocoConfiguration.IT_REPORT_PATH_DEFAULT_VALUE,
075 description = "Path (absolute or relative) to the file with execution data.",
076 global = false,
077 module = true,
078 project = true
079 ),
080 @Property(
081 key = JacocoConfiguration.ANT_TARGETS_PROPERTY,
082 name = "Ant targets",
083 defaultValue = JacocoConfiguration.ANT_TARGETS_DEFAULT_VALUE,
084 description = "Comma separated list of Ant targets for execution of tests.",
085 global = true,
086 module = true,
087 project = true
088 )})
089 public class JacocoConfiguration implements BatchExtension {
090
091 public static final String REPORT_PATH_PROPERTY = "sonar.jacoco.reportPath";
092 public static final String REPORT_PATH_DEFAULT_VALUE = "target/jacoco.exec";
093 public static final String IT_REPORT_PATH_PROPERTY = "sonar.jacoco.itReportPath";
094 public static final String IT_REPORT_PATH_DEFAULT_VALUE = "";
095 public static final String INCLUDES_PROPERTY = "sonar.jacoco.includes";
096 public static final String EXCLUDES_PROPERTY = "sonar.jacoco.excludes";
097
098 /**
099 * Hibernate uses Javassist to modify entity classes and without exclusion of such classes from JaCoCo exception might be thrown:
100 * <pre>
101 * Javassist Enhancement failed: org.sonar.api.profiles.Alert
102 * java.lang.VerifyError: (class: org/sonar/api/profiles/Alert_$$_javassist_3, method: <clinit> signature: ()V) Illegal local variable number
103 * </pre>
104 */
105 public static final String EXCLUDES_DEFAULT_VALUE = "*_javassist_*";
106 public static final String EXCLCLASSLOADER_PROPERTY = "sonar.jacoco.exclclassloader";
107 public static final String ANT_TARGETS_PROPERTY = "sonar.jacoco.antTargets";
108 public static final String ANT_TARGETS_DEFAULT_VALUE = "";
109
110 private Settings settings;
111 private JaCoCoAgentDownloader downloader;
112
113 public JacocoConfiguration(Settings settings, JaCoCoAgentDownloader downloader) {
114 this.settings = settings;
115 this.downloader = downloader;
116 }
117
118 public String getReportPath() {
119 return settings.getString(REPORT_PATH_PROPERTY);
120 }
121
122 public String getItReportPath() {
123 return settings.getString(IT_REPORT_PATH_PROPERTY);
124 }
125
126 public String getJvmArgument() {
127 AgentOptions options = new AgentOptions();
128 options.setDestfile(getReportPath());
129 String includes = settings.getString(INCLUDES_PROPERTY);
130 if (StringUtils.isNotBlank(includes)) {
131 options.setIncludes(includes);
132 }
133 String excludes = settings.getString(EXCLUDES_PROPERTY);
134 if (StringUtils.isNotBlank(excludes)) {
135 options.setExcludes(excludes);
136 }
137 String exclclassloader = settings.getString(EXCLCLASSLOADER_PROPERTY);
138 if (StringUtils.isNotBlank(exclclassloader)) {
139 options.setExclClassloader(exclclassloader);
140 }
141 return options.getVMArgument(downloader.getAgentJarFile());
142 }
143
144 public String[] getAntTargets() {
145 return settings.getStringArray(ANT_TARGETS_PROPERTY);
146 }
147
148 public String getExcludes() {
149 return settings.getString(EXCLUDES_PROPERTY);
150 }
151
152 }