*/
package org.sonar.batch.bootstrap;
+import com.github.kevinsawicki.http.HttpRequest;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.List;
import java.util.Map;
import javax.annotation.CheckForNull;
+import org.apache.commons.lang.StringUtils;
import org.sonar.api.CoreProperties;
import org.sonar.api.SonarPlugin;
+import org.sonar.api.platform.Server;
+import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.UriReader;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.batch.analysis.AnalysisProperties;
import org.sonar.batch.analysis.DefaultAnalysisMode;
import org.sonar.batch.cache.GlobalPersistentCacheProvider;
import org.sonar.core.util.DefaultHttpDownloader;
import org.sonar.core.util.UuidFactoryImpl;
+import static java.lang.String.format;
+
public class GlobalContainer extends ComponentContainer {
+ private static final org.sonar.api.utils.log.Logger LOG = Loggers.get(GlobalContainer.class);
+
private final Map<String, String> bootstrapProperties;
private boolean preferCache;
}
public void executeAnalysis(Map<String, String> analysisProperties, Object... components) {
- AnalysisProperties props = new AnalysisProperties(analysisProperties, this.getComponentByType(GlobalProperties.class).property(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
+ GlobalProperties globalProperties = this.getComponentByType(GlobalProperties.class);
+ // SONAR-6888
+ String task = analysisProperties.get(CoreProperties.TASK);
+ if ("views".equals(task)) {
+ triggerViews(this.getComponentByType(ServerClient.class), this.getComponentByType(Server.class));
+ return;
+ }
+ if (StringUtils.isNotBlank(task) && !CoreProperties.SCAN_TASK.equals(task)) {
+ throw MessageException.of("Tasks are no more supported on batch side since SonarQube 5.2");
+ }
+
+ AnalysisProperties props = new AnalysisProperties(analysisProperties, globalProperties.property(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
if (isIssuesMode(props)) {
String projectKey = getProjectKeyWithBranch(props);
new ProjectSyncContainer(this, projectKey, false).execute();
new ProjectScanContainer(this, props, components).execute();
}
+ private static void triggerViews(ServerClient serverClient, Server server) {
+ LOG.info("Trigger Views update");
+ URL url;
+ try {
+ url = new URL(serverClient.getURL() + "/api/views/run");
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException("Invalid URL", e);
+ }
+ HttpRequest request = HttpRequest.post(url);
+ request.trustAllCerts();
+ request.trustAllHosts();
+ request.header("User-Agent", format("SonarQube %s", server.getVersion()));
+ request.basic(serverClient.getLogin(), serverClient.getPassword());
+ if (!request.ok()) {
+ int responseCode = request.code();
+ if (responseCode == 401) {
+ throw new IllegalStateException(format(serverClient.getMessageWhenNotAuthorized(), CoreProperties.LOGIN, CoreProperties.PASSWORD));
+ }
+ if (responseCode == 409) {
+ throw new IllegalStateException("A full refresh of Views is already queued or running");
+ }
+ if (responseCode == 403) {
+ // SONAR-4397 Details are in response content
+ throw new IllegalStateException(request.body());
+ }
+ throw new IllegalStateException(format("Fail to execute request [code=%s, url=%s]: %s", responseCode, url, request.body()));
+ }
+ }
+
@CheckForNull
private static String getProjectKeyWithBranch(AnalysisProperties props) {
String projectKey = props.property(CoreProperties.PROJECT_KEY_PROPERTY);
*/
package org.sonar.batch.bootstrap;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import java.io.IOException;
-
import static javax.servlet.http.HttpServletResponse.SC_OK;
import static org.apache.commons.io.IOUtils.write;
private String requestBody;
private String mockResponseData;
private int mockResponseStatus = SC_OK;
- private int numRequests = 0;
+ private List<String> targets = new ArrayList<>();
public void start() throws Exception {
server = new Server(0);
}
public int getNumberRequests() {
- return numRequests;
+ return targets.size();
}
/**
Handler handler = new AbstractHandler() {
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
- numRequests++;
+ targets.add(target);
setResponseBody(getMockResponseData());
setRequestBody(IOUtils.toString(baseRequest.getInputStream()));
response.setStatus(mockResponseStatus);
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 02110-1301, USA.
+ */
+package org.sonar.batch.mediumtest.tasks;
+
+import com.google.common.collect.ImmutableMap;
+import org.junit.After;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.MessageException;
+import org.sonar.api.utils.log.LogTester;
+import org.sonar.batch.bootstrap.MockHttpServer;
+import org.sonar.batch.mediumtest.BatchMediumTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class TasksMediumTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Rule
+ public LogTester logTester = new LogTester();
+
+ public BatchMediumTester tester = BatchMediumTester.builder()
+ .build();
+
+ private MockHttpServer server = null;
+
+ @After
+ public void stopServer() {
+ if (server != null) {
+ server.stop();
+ }
+ }
+
+ @After
+ public void stop() {
+ tester.stop();
+ }
+
+ @Test
+ public void triggerViews() throws Exception {
+ startServer(200, "OK");
+ tester = BatchMediumTester.builder()
+ .bootstrapProperties(ImmutableMap.of("sonar.host.url", "http://localhost:" + server.getPort()))
+ .build();
+ tester.start();
+ tester.newTask()
+ .properties(ImmutableMap.<String, String>builder()
+ .put("sonar.task", "views").build())
+ .start();
+
+ assertThat(logTester.logs()).contains("Trigger views update");
+ }
+
+ @Test(expected = MessageException.class)
+ public void unsupportedTask() throws Exception {
+ tester = BatchMediumTester.builder()
+ .build();
+ tester.start();
+ tester.newTask()
+ .properties(ImmutableMap.<String, String>builder()
+ .put("sonar.task", "foo").build())
+ .start();
+ }
+
+ private void startServer(Integer responseStatus, String responseData) throws Exception {
+ server = new MockHttpServer();
+ server.start();
+
+ if (responseStatus != null) {
+ server.setMockResponseStatus(responseStatus);
+ }
+ if (responseData != null) {
+ server.setMockResponseData(responseData);
+ }
+ }
+
+}