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