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.tools.ant.*; 023 import org.sonar.api.batch.CoverageExtension; 024 import org.sonar.api.batch.Initializer; 025 import org.sonar.api.batch.SupportedEnvironment; 026 import org.sonar.api.resources.Project; 027 028 import java.util.Map; 029 030 @SupportedEnvironment("ant") 031 public class JacocoAntInitializer extends Initializer implements CoverageExtension { 032 033 private final TaskEnhancer[] taskEnhancers = new TaskEnhancer[] { new JavaLikeTaskEnhancer("java"), new JavaLikeTaskEnhancer("junit"), new TestngTaskEnhancer() }; 034 035 private org.apache.tools.ant.Project antProject; 036 private JacocoConfiguration configuration; 037 038 public JacocoAntInitializer(org.apache.tools.ant.Project antProject, JacocoConfiguration configuration) { 039 this.antProject = antProject; 040 this.configuration = configuration; 041 } 042 043 @Override 044 public boolean shouldExecuteOnProject(org.sonar.api.resources.Project project) { 045 return project.getAnalysisType().equals(Project.AnalysisType.DYNAMIC); 046 } 047 048 @Override 049 public void execute(org.sonar.api.resources.Project project) { 050 Map<String, Target> hastable = antProject.getTargets(); 051 String jvmArg = configuration.getJvmArgument(); 052 String[] names = configuration.getAntTargets(); 053 for (String name : names) { 054 Target target = hastable.get(name); 055 if (target == null) { 056 JaCoCoUtils.LOG.warn("Target '{}' not found", name); 057 } else { 058 // Enhance target 059 for (Task task : target.getTasks()) { 060 for (TaskEnhancer enhancer : taskEnhancers) { 061 if (enhancer.supportsTask(task)) { 062 enhancer.enhanceTask(task, jvmArg); 063 } 064 } 065 } 066 // Execute target 067 target.performTasks(); 068 } 069 } 070 } 071 072 private static class TestngTaskEnhancer extends TaskEnhancer { 073 @Override 074 public boolean supportsTask(Task task) { 075 return "testng".equals(task.getTaskName()); 076 } 077 } 078 079 /** 080 * Basic task enhancer that can handle all 'java like' tasks. That is, tasks 081 * that have a top level fork attribute and nested jvmargs elements 082 */ 083 private static class JavaLikeTaskEnhancer extends TaskEnhancer { 084 private String taskName; 085 086 public JavaLikeTaskEnhancer(String taskName) { 087 this.taskName = taskName; 088 } 089 090 public boolean supportsTask(final Task task) { 091 return taskName.equals(task.getTaskName()); 092 } 093 094 @Override 095 public void enhanceTask(final Task task, final String jvmArg) { 096 final RuntimeConfigurable configurableWrapper = task.getRuntimeConfigurableWrapper(); 097 098 final String forkValue = (String) configurableWrapper.getAttributeMap().get("fork"); 099 100 if (forkValue == null || !org.apache.tools.ant.Project.toBoolean(forkValue)) { 101 throw new BuildException("Coverage can only be applied on a forked VM"); 102 } 103 104 super.enhanceTask(task, jvmArg); 105 } 106 107 } 108 109 private abstract static class TaskEnhancer { 110 /** 111 * @param task Task instance to enhance 112 * @return <code>true</code> if this enhancer is capable of enhancing the requested task 113 */ 114 public abstract boolean supportsTask(Task task); 115 116 /** 117 * Attempt to enhance the supplied task with coverage information. This 118 * operation may fail if the task is being executed in the current VM 119 * 120 * @param task Task instance to enhance (usually an {@link UnknownElement}) 121 * @param jvmArg 122 * @throws BuildException Thrown if this enhancer can handle this type of task, but this instance can not be enhanced for some reason. 123 */ 124 public void enhanceTask(Task task, String jvmArg) { 125 addJvmArg((UnknownElement) task, jvmArg); 126 } 127 128 public void addJvmArg(final UnknownElement task, final String jvmArg) { 129 final UnknownElement el = new UnknownElement("jvmarg"); 130 el.setTaskName("jvmarg"); 131 el.setQName("jvmarg"); 132 133 final RuntimeConfigurable runtimeConfigurableWrapper = el.getRuntimeConfigurableWrapper(); 134 runtimeConfigurableWrapper.setAttribute("value", jvmArg); 135 136 task.getRuntimeConfigurableWrapper().addChild(runtimeConfigurableWrapper); 137 138 task.addChild(el); 139 } 140 } 141 142 }