import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.charset.Charset;
+import java.security.InvalidParameterException;
import java.util.Locale;
import java.util.Properties;
+
import javax.annotation.Nullable;
+
import org.sonar.home.cache.Logger;
import org.sonar.runner.batch.IsolatedLauncher;
import org.sonar.runner.impl.InternalProperties;
}
public static EmbeddedRunner create(final LogOutput logOutput) {
- Logger logger = new Logger() {
-
- @Override
- public void warn(String msg) {
- logOutput.log(msg, LogOutput.Level.WARN);
- }
-
- @Override
- public void info(String msg) {
- logOutput.log(msg, LogOutput.Level.INFO);
- }
-
- @Override
- public void error(String msg, Throwable t) {
- StringWriter errors = new StringWriter();
- t.printStackTrace(new PrintWriter(errors));
- logOutput.log(msg + "\n" + errors.toString(), LogOutput.Level.ERROR);
- }
-
- @Override
- public void error(String msg) {
- logOutput.log(msg, LogOutput.Level.ERROR);
- }
-
- @Override
- public void debug(String msg) {
- logOutput.log(msg, LogOutput.Level.DEBUG);
- }
- };
+ Logger logger = new LoggerAdapter(logOutput);
return new EmbeddedRunner(new IsolatedLauncherFactory(logger), logger, logOutput);
}
}
public void runAnalysis(Properties analysisProperties) {
+ runAnalysis(analysisProperties, null);
+ }
+
+ public void runAnalysis(Properties analysisProperties, @Nullable IssueListener issueListener) {
Properties copy = new Properties();
copy.putAll(analysisProperties);
initAnalysisProperties(copy);
Utils.writeProperties(dumpFile, copy);
logger.info("Simulation mode. Configuration written to " + dumpFile.getAbsolutePath());
} else {
- doExecute(copy);
+ doExecute(copy, issueListener);
}
}
}
}
- protected void doExecute(Properties analysisProperties) {
+ protected void doExecute(Properties analysisProperties, @Nullable IssueListener issueListener) {
if (VersionUtils.isAtLeast52(launcher.getVersion())) {
- launcher.execute(analysisProperties);
+ if (issueListener != null) {
+ launcher.execute(analysisProperties, new IssueListenerAdapter(issueListener));
+ } else {
+ launcher.execute(analysisProperties);
+ }
} else {
+ if (issueListener != null) {
+ throw new InvalidParameterException("Issue listeners not supported in current version: " + launcher.getVersion());
+ }
Properties prop = new Properties();
prop.putAll(globalProperties());
prop.putAll(analysisProperties);
launcher.executeOldVersion(prop);
}
}
+
+ static class IssueListenerAdapter implements org.sonar.runner.batch.IssueListener {
+ private IssueListener apiIssueListener;
+
+ public IssueListenerAdapter(IssueListener apiIssueListener) {
+ this.apiIssueListener = apiIssueListener;
+ }
+
+ @Override
+ public void handle(org.sonar.runner.batch.IssueListener.Issue issue) {
+ apiIssueListener.handle(transformIssue(issue));
+ }
+
+ private static org.sonar.runner.api.Issue transformIssue(org.sonar.runner.batch.IssueListener.Issue batchIssue) {
+ org.sonar.runner.api.Issue.Builder issueBuilder = org.sonar.runner.api.Issue.builder();
+
+ issueBuilder.setAssignee(batchIssue.getAssignee());
+ issueBuilder.setComponentKey(batchIssue.getComponentKey());
+ issueBuilder.setKey(batchIssue.getKey());
+ issueBuilder.setLine(batchIssue.getLine());
+ issueBuilder.setMessage(batchIssue.getMessage());
+ issueBuilder.setNew(batchIssue.isNew());
+ issueBuilder.setResolution(batchIssue.getResolution());
+ issueBuilder.setRule(batchIssue.getRule());
+ issueBuilder.setStatus(batchIssue.getStatus());
+
+ return issueBuilder.build();
+ }
+ }
+
+ private static class LoggerAdapter implements Logger {
+ private LogOutput logOutput;
+
+ LoggerAdapter(LogOutput logOutput) {
+ this.logOutput = logOutput;
+ }
+
+ @Override
+ public void warn(String msg) {
+ logOutput.log(msg, LogOutput.Level.WARN);
+ }
+
+ @Override
+ public void info(String msg) {
+ logOutput.log(msg, LogOutput.Level.INFO);
+ }
+
+ @Override
+ public void error(String msg, Throwable t) {
+ StringWriter errors = new StringWriter();
+ t.printStackTrace(new PrintWriter(errors));
+ logOutput.log(msg + "\n" + errors.toString(), LogOutput.Level.ERROR);
+ }
+
+ @Override
+ public void error(String msg) {
+ logOutput.log(msg, LogOutput.Level.ERROR);
+ }
+
+ @Override
+ public void debug(String msg) {
+ logOutput.log(msg, LogOutput.Level.DEBUG);
+ }
+ };
}
--- /dev/null
+/*
+ * SonarQube Runner - API
+ * Copyright (C) 2011 SonarSource
+ * sonarqube@googlegroups.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.runner.api;
+
+import javax.annotation.concurrent.Immutable;
+
+import java.util.Date;
+
+@Immutable
+public final class Issue {
+ private final String key;
+ private final String componentKey;
+ private final Integer line;
+ private final String message;
+ private final String rule;
+ private final String status;
+ private final String resolution;
+ private final boolean isNew;
+ private final String assignee;
+
+ private Issue(String key, String componentKey, Integer line, String message, String rule, String status, String resolution, boolean isNew, String assignee) {
+ super();
+ this.key = key;
+ this.componentKey = componentKey;
+ this.line = line;
+ this.message = message;
+ this.rule = rule;
+ this.status = status;
+ this.resolution = resolution;
+ this.isNew = isNew;
+ this.assignee = assignee;
+ }
+
+ public static class Builder {
+ private String key;
+ private String componentKey;
+ private Integer line;
+ private String message;
+ private String rule;
+ private String status;
+ private String resolution;
+ private boolean isNew;
+ private String assignee;
+
+ public String getKey() {
+ return key;
+ }
+
+ public Builder setKey(String key) {
+ this.key = key;
+ return this;
+ }
+
+ public String getComponentKey() {
+ return componentKey;
+ }
+
+ public Builder setComponentKey(String componentKey) {
+ this.componentKey = componentKey;
+ return this;
+ }
+
+ public Integer getLine() {
+ return line;
+ }
+
+ public Builder setLine(Integer line) {
+ this.line = line;
+ return this;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public Builder setMessage(String message) {
+ this.message = message;
+ return this;
+ }
+
+ public String getRule() {
+ return rule;
+ }
+
+ public Builder setRule(String rule) {
+ this.rule = rule;
+ return this;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public Builder setStatus(String status) {
+ this.status = status;
+ return this;
+ }
+
+ public String getResolution() {
+ return resolution;
+ }
+
+ public Builder setResolution(String resolution) {
+ this.resolution = resolution;
+ return this;
+ }
+
+ public boolean isNew() {
+ return isNew;
+ }
+
+ public Builder setNew(boolean isNew) {
+ this.isNew = isNew;
+ return this;
+ }
+
+ public String getAssignee() {
+ return assignee;
+ }
+
+ public Builder setAssignee(String assignee) {
+ this.assignee = assignee;
+ return this;
+ }
+
+ public Issue build() {
+ return new Issue(key, componentKey, line, message, rule, status, resolution, isNew, assignee);
+ }
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getComponentKey() {
+ return componentKey;
+ }
+
+ public Integer getLine() {
+ return line;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public String getRule() {
+ return rule;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public String getResolution() {
+ return resolution;
+ }
+
+ public boolean isNew() {
+ return isNew;
+ }
+
+ public String getAssignee() {
+ return assignee;
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube Runner - API
+ * Copyright (C) 2011 SonarSource
+ * sonarqube@googlegroups.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.runner.api;
+
+public interface IssueListener {
+ void handle(Issue issue);
+}
*/
package org.sonar.runner.api;
+import org.sonar.runner.api.EmbeddedRunner.IssueListenerAdapter;
+
+import java.awt.geom.IllegalPathStateException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Properties;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.home.cache.Logger;
import org.sonar.runner.batch.IsolatedLauncher;
import org.sonar.runner.impl.IsolatedLauncherFactory;
-
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
}));
}
+ @Test
+ public void test_issue_adapter() {
+ final List<Issue> issuesRecorded = new LinkedList<>();
+ IssueListener apiIssueListener = new IssueListener() {
+ @Override
+ public void handle(Issue issue) {
+ issuesRecorded.add(issue);
+ }
+ };
+ IssueListenerAdapter adapter = new IssueListenerAdapter(apiIssueListener);
+
+ org.sonar.runner.batch.IssueListener.Issue batchIssue = new org.sonar.runner.batch.IssueListener.Issue();
+ batchIssue.setAssignee("assignee");
+ adapter.handle(batchIssue);
+
+ assertThat(issuesRecorded).hasSize(1);
+ assertThat(issuesRecorded.get(0).getAssignee()).isEqualTo("assignee");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void reject_issue_listener_old_version() {
+ when(launcher.getVersion()).thenReturn("4.5");
+ launch_with_issue_listener();
+ }
+
+ @Test
+ public void launch_with_issue_listener() {
+ runner.start();
+ runner.runAnalysis(mock(Properties.class), mock(IssueListener.class));
+ runner.stop();
+
+ verify(launcher).execute(any(Properties.class), any(org.sonar.runner.batch.IssueListener.class));
+ }
+
@Test
public void should_launch_batch_analysisProperties() {
runner.setGlobalProperty("sonar.projectKey", "foo");
*/
package org.sonar.runner.impl;
+import org.sonar.runner.batch.IssueListener;
+
import java.util.Properties;
+
import org.junit.Before;
import org.junit.Test;
import org.sonar.home.cache.Logger;
import org.sonar.runner.batch.IsolatedLauncher;
import org.sonar.runner.batch.LogOutput;
-
import static org.fest.assertions.Fail.fail;
import static org.mockito.Mockito.mock;
public static class FakeIsolatedLauncher implements IsolatedLauncher {
public static Properties props = null;
+ public static IssueListener listener = null;
@Override
public void start(Properties properties, LogOutput logger) {
public String getVersion() {
return null;
}
+
+ @Override
+ public void execute(Properties properties, IssueListener listener) {
+ FakeIsolatedLauncher.props = properties;
+ FakeIsolatedLauncher.listener = listener;
+ }
}
}
<artifactId>sonar-runner-batch-interface</artifactId>
<name>SonarQube Runner - Batch Interface</name>
- <dependencies>
- <dependency>
- <groupId>org.codehaus.sonar</groupId>
- <artifactId>sonar-home</artifactId>
- <scope>provided</scope>
- </dependency>
- </dependencies>
</project>
void stop();
void execute(Properties properties);
-
+
+ void execute(Properties properties, IssueListener listener);
+
void executeOldVersion(Properties properties);
String getVersion();
+
}
--- /dev/null
+/*
+ * SonarQube Runner - Batch Interface
+ * Copyright (C) 2011 SonarSource
+ * sonarqube@googlegroups.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.runner.batch;
+
+import java.util.Date;
+
+public interface IssueListener {
+ void handle(Issue issue);
+
+ class Issue {
+ private String key;
+ private String componentKey;
+ private Integer line;
+ private String message;
+ private String rule;
+ private String status;
+ private String resolution;
+ private boolean isNew;
+ private String assignee;
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public void setComponentKey(String componentKey) {
+ this.componentKey = componentKey;
+ }
+
+ public void setLine(Integer line) {
+ this.line = line;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public void setRule(String rule) {
+ this.rule = rule;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public void setResolution(String resolution) {
+ this.resolution = resolution;
+ }
+
+ public void setNew(boolean isNew) {
+ this.isNew = isNew;
+ }
+
+ public void setAssignee(String assignee) {
+ this.assignee = assignee;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getComponentKey() {
+ return componentKey;
+ }
+
+ public Integer getLine() {
+ return line;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public String getRule() {
+ return rule;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public String getResolution() {
+ return resolution;
+ }
+
+ public boolean isNew() {
+ return isNew;
+ }
+
+ public String getAssignee() {
+ return assignee;
+ }
+
+ }
+}
batch.executeTask((Map) properties);
}
+ @Override
+ public void execute(Properties properties, IssueListener listener) {
+ org.sonar.batch.bootstrapper.IssueListener batchIssueListener = Compatibility.getBatchIssueListener(listener);
+ batch.executeTask((Map) properties, batchIssueListener);
+ }
+
Batch createBatch(Properties properties, @Nullable final org.sonar.runner.batch.LogOutput logOutput) {
EnvironmentInformation env = new EnvironmentInformation(properties.getProperty("sonarRunner.app"), properties.getProperty("sonarRunner.appVersion"));
Batch.Builder builder = Batch.builder()
*/
package org.sonar.runner.batch;
+import org.sonar.api.issue.Issue;
import org.sonar.batch.bootstrapper.Batch;
import org.sonar.batch.bootstrapper.LogOutput;
public class Compatibility {
-
private Compatibility() {
// Utility class
}
});
}
+ static org.sonar.batch.bootstrapper.IssueListener getBatchIssueListener(IssueListener listener) {
+ return new IssueListenerAdapter(listener);
+ }
+
+ static class IssueListenerAdapter implements org.sonar.batch.bootstrapper.IssueListener {
+ private IssueListener listener;
+
+ public IssueListenerAdapter(IssueListener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ public void handle(Issue issue) {
+ listener.handle(transformIssue(issue));
+ }
+
+ private static IssueListener.Issue transformIssue(Issue batchIssue) {
+ IssueListener.Issue newIssue = new IssueListener.Issue();
+ newIssue.setAssignee(batchIssue.assignee());
+ newIssue.setComponentKey(batchIssue.componentKey());
+ newIssue.setKey(batchIssue.key());
+ newIssue.setResolution(batchIssue.resolution());
+ newIssue.setRule(batchIssue.ruleKey().toString());
+ newIssue.setMessage(batchIssue.message());
+ newIssue.setNew(batchIssue.isNew());
+ newIssue.setLine(batchIssue.line());
+
+ return newIssue;
+ }
+ }
}