}
public void writeAndFlush(String payload) throws IOException {
+ payload = ensureCorrectMessageEnding(payload);
output().write(payload.getBytes(StandardCharsets.UTF_8));
flush();
}
+ private static String ensureCorrectMessageEnding(String payload) {
+ return payload.endsWith("\n\n") ? payload : (payload + "\n\n");
+ }
+
public void writeAndFlush(char character) {
write(character);
flush();
private final RuleActivatorEventsDistributor ruleActivatorEventsDistributor;
private final SonarLintClientPermissionsValidator sonarLintClientPermissionsValidator;
+ private final List<SonarLintClient> clients = new CopyOnWriteArrayList<>();
public SonarLintClientsRegistry(RuleActivatorEventsDistributor ruleActivatorEventsDistributor, SonarLintClientPermissionsValidator permissionsValidator) {
this.ruleActivatorEventsDistributor = ruleActivatorEventsDistributor;
this.sonarLintClientPermissionsValidator = permissionsValidator;
}
- private final List<SonarLintClient> clients = new CopyOnWriteArrayList<>();
-
public void registerClient(SonarLintClient sonarLintClient) {
clients.add(sonarLintClient);
sonarLintClient.scheduleHeartbeat();
package org.sonar.server.pushapi;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.mockito.Mockito;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.doThrow;
.schedule(any(HeartbeatTask.class), anyLong(), any());
}
+ @Test
+ public void writeAndFlush_payloadAlwaysEndsWithSlashNSlashN() throws IOException {
+ underTest.writeAndFlush("payload");
+
+ verify(outputStream, Mockito.times(1)).flush();
+ verify(outputStream, Mockito.times(1)).write("payload\n\n".getBytes(StandardCharsets.UTF_8));
+ }
+
+ @Test
+ public void writeAndFlush_payloadAlwaysEndsWithASingleSlashNSlashN_whenMessageAlreadyContainsIt() throws IOException {
+ underTest.writeAndFlush("payload\n\n");
+
+ verify(outputStream, Mockito.times(1)).flush();
+ verify(outputStream, Mockito.times(1)).write("payload\n\n".getBytes(StandardCharsets.UTF_8));
+ }
+
@Test
public void writeAndFlush_writeIsCalledOnceAndFlushIsCalledOnce() throws IOException {
underTest.writeAndFlush('a');
import org.sonarqube.ws.client.projects.ProjectsService;
import org.sonarqube.ws.client.projecttags.ProjectTagsService;
import org.sonarqube.ws.client.properties.PropertiesService;
+import org.sonarqube.ws.client.push.SonarLintServerPushService;
import org.sonarqube.ws.client.qualitygates.QualitygatesService;
import org.sonarqube.ws.client.qualityprofiles.QualityprofilesService;
import org.sonarqube.ws.client.roots.RootsService;
private final WebservicesService webservicesService;
private final BatchService batchService;
private final SecurityReportsService securityReportsService;
+ private final SonarLintServerPushService sonarLintPushService;
DefaultWsClient(WsConnector wsConnector) {
this.wsConnector = wsConnector;
this.webservicesService = new WebservicesService(wsConnector);
this.batchService = new BatchService(wsConnector);
this.securityReportsService = new SecurityReportsService(wsConnector);
+ this.sonarLintPushService = new SonarLintServerPushService(wsConnector);
}
@Override
return monitoringService;
}
+ @Override
+ public SonarLintServerPushService sonarLintPush() {
+ return sonarLintPushService;
+ }
+
@Override
public NavigationService navigation() {
return navigationService;
import org.sonarqube.ws.client.projects.ProjectsService;
import org.sonarqube.ws.client.projecttags.ProjectTagsService;
import org.sonarqube.ws.client.properties.PropertiesService;
+import org.sonarqube.ws.client.push.SonarLintServerPushService;
import org.sonarqube.ws.client.qualitygates.QualitygatesService;
import org.sonarqube.ws.client.qualityprofiles.QualityprofilesService;
import org.sonarqube.ws.client.roots.RootsService;
SecurityReportsService securityReports();
MonitoringService monitoring();
+
+ SonarLintServerPushService sonarLintPush();
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT 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 02110-1301, USA.
+ */
+package org.sonarqube.ws.client.push;
+
+import org.sonarqube.ws.client.BaseService;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.WsConnector;
+import org.sonarqube.ws.client.WsResponse;
+
+public class SonarLintServerPushService extends BaseService {
+ public SonarLintServerPushService(WsConnector wsConnector) {
+ super(wsConnector, "api/push");
+ }
+
+ public WsResponse connect(String projectKeys, String languages) {
+ return call(
+ new GetRequest(path("sonarlint_events"))
+ .setParam("projectKeys", projectKeys)
+ .setParam("languages", languages)
+ .setHeader("accept", "text/event-stream"));
+ }
+}