Преглед на файлове

New WS api/rules/list for batch

tags/5.2-RC1
Simon Brandhof преди 8 години
родител
ревизия
314af7bed8

+ 1537
- 0
server/sonar-server/src/main/gen-java/org/sonarqube/ws/Rules.java
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 1
- 0
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java Целия файл

@@ -463,6 +463,7 @@ public class PlatformLevel4 extends PlatformLevel {
org.sonar.server.rule.ws.ShowAction.class,
org.sonar.server.rule.ws.CreateAction.class,
org.sonar.server.rule.ws.DeleteAction.class,
org.sonar.server.rule.ws.ListAction.class,
TagsAction.class,
RuleMapping.class,
ActiveRuleCompleter.class,

+ 82
- 0
server/sonar-server/src/main/java/org/sonar/server/rule/ws/ListAction.java Целия файл

@@ -0,0 +1,82 @@
/*
* 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.server.rule.ws;

import com.google.common.base.Strings;
import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.rule.RuleDto;
import org.sonar.server.plugins.MimeTypes;
import org.sonarqube.ws.Rules.ListResponse;

public class ListAction implements RulesWsAction {

private final DbClient dbClient;

public ListAction(DbClient dbClient) {
this.dbClient = dbClient;
}

@Override
public void define(WebService.NewController controller) {
controller
.createAction("list")
.setDescription("List of rules, excluding the manual rules and the rules with status REMOVED. JSON format is not supported for response.")
.setSince("5.2")
.setInternal(true)
.setHandler(this);
}

@Override
public void handle(Request wsRequest, Response wsResponse) throws Exception {
DbSession dbSession = dbClient.openSession(false);
final ListResponse.Builder listResponseBuilder = ListResponse.newBuilder();
final ListResponse.Rule.Builder ruleBuilder = ListResponse.Rule.newBuilder();
try {
dbClient.ruleDao().selectEnabledAndNonManual(dbSession, new ResultHandler() {
@Override
public void handleResult(ResultContext resultContext) {
RuleDto dto = (RuleDto) resultContext.getResultObject();
ruleBuilder
.clear()
.setRepository(dto.getRepositoryKey())
.setKey(dto.getRuleKey());
String internalKey = dto.getConfigKey();
if (!Strings.isNullOrEmpty(internalKey)) {
ruleBuilder.setInternalKey(internalKey);
}
listResponseBuilder.addRules(ruleBuilder.build());
}
});
} finally {
dbClient.closeSession(dbSession);
}

// JSON response is voluntarily not supported. This WS is for internal use.
wsResponse.stream().setMediaType(MimeTypes.PROTOBUF);
listResponseBuilder.build().writeTo(wsResponse.stream().output());
}

}

+ 38
- 0
server/sonar-server/src/main/protobuf/ws-rules.proto Целия файл

@@ -0,0 +1,38 @@
// SonarQube, open source software quality management tool.
// Copyright (C) 2008-2015 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.

syntax = "proto2";

package sonarqube.ws.rules;

option java_package = "org.sonarqube.ws";
option java_outer_classname = "Rules";
option optimize_for = SPEED;

// WS api/rules/list for internal use only
message ListResponse {

message Rule {
optional string repository = 1;
optional string key = 2;
optional string internal_key = 3;
}

repeated Rule rules = 1;

}

+ 70
- 0
server/sonar-server/src/test/java/org/sonar/server/rule/ws/ListActionTest.java Целия файл

@@ -0,0 +1,70 @@
/*
* 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.server.rule.ws;

import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
import org.sonar.db.rule.RuleTesting;
import org.sonar.server.plugins.MimeTypes;
import org.sonar.server.ws.TestResponse;
import org.sonar.server.ws.WsActionTester;
import org.sonarqube.ws.Rules;

import static org.assertj.core.api.Assertions.assertThat;

public class ListActionTest {

@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);

ListAction underTest = new ListAction(dbTester.getDbClient());

WsActionTester tester = new WsActionTester(underTest);

@Test
public void define() throws Exception {
WebService.Action def = tester.getDef();
assertThat(def.params()).isEmpty();
}

@Test
public void return_rules_in_protobuf() throws Exception {
dbTester.getDbClient().ruleDao().insert(dbTester.getSession(), RuleTesting.newDto(RuleKey.of("java", "S001")).setConfigKey(null));
dbTester.getDbClient().ruleDao().insert(dbTester.getSession(), RuleTesting.newDto(RuleKey.of("java", "S002")).setConfigKey("I002"));
dbTester.getSession().commit();

TestResponse response = tester.newRequest()
.setMimeType(MimeTypes.PROTOBUF)
.execute();

assertThat(response.getMediaType()).isEqualTo(MimeTypes.PROTOBUF);
Rules.ListResponse listResponse = Rules.ListResponse.parseFrom(response.getInputStream());
assertThat(listResponse.getRulesCount()).isEqualTo(2);

assertThat(listResponse.getRules(0).getKey()).isEqualTo("S001");
assertThat(listResponse.getRules(0).hasInternalKey()).isFalse();
assertThat(listResponse.getRules(1).getKey()).isEqualTo("S002");
assertThat(listResponse.getRules(1).getInternalKey()).isEqualTo("I002");
}
}

+ 1
- 1
server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWsMediumTest.java Целия файл

@@ -97,7 +97,7 @@ public class RulesWsMediumTest {
WebService.Controller controller = context.controller(API_ENDPOINT);

assertThat(controller).isNotNull();
assertThat(controller.actions()).hasSize(8);
assertThat(controller.actions()).hasSize(9);
assertThat(controller.action(API_SEARCH_METHOD)).isNotNull();
assertThat(controller.action(API_SHOW_METHOD)).isNotNull();
assertThat(controller.action(API_TAGS_METHOD)).isNotNull();

+ 130
- 0
server/sonar-server/src/test/java/org/sonar/server/ws/DumbResponse.java Целия файл

@@ -0,0 +1,130 @@
/*
* 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.server.ws;

import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Map;
import javax.annotation.CheckForNull;
import org.apache.commons.io.IOUtils;
import org.sonar.api.server.ws.Response;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.api.utils.text.XmlWriter;

public class DumbResponse implements Response {
private InMemoryStream stream;

private final ByteArrayOutputStream output = new ByteArrayOutputStream();

private Map<String, String> headers = Maps.newHashMap();

public class InMemoryStream implements Response.Stream {
private String mediaType;

private int status;

@CheckForNull
public String mediaType() {
return mediaType;
}

public int status() {
return status;
}

@Override
public Response.Stream setMediaType(String s) {
this.mediaType = s;
return this;
}

@Override
public Response.Stream setStatus(int i) {
this.status = i;
return this;
}
@Override
public OutputStream output() {
return output;
}

}

@Override
public JsonWriter newJsonWriter() {
return JsonWriter.of(new OutputStreamWriter(output, StandardCharsets.UTF_8));
}

@Override
public XmlWriter newXmlWriter() {
return XmlWriter.of(new OutputStreamWriter(output, StandardCharsets.UTF_8));
}

@Override
public InMemoryStream stream() {
if (stream == null) {
stream = new InMemoryStream();
}
return stream;
}

@Override
public Response noContent() {
stream().setStatus(HttpURLConnection.HTTP_NO_CONTENT);
IOUtils.closeQuietly(output);
return this;
}

public String outputAsString() {
return new String(output.toByteArray(), StandardCharsets.UTF_8);
}

@Override
public Response setHeader(String name, String value) {
headers.put(name, value);
return this;
}

@Override
public Collection<String> getHeaderNames() {
return headers.keySet();
}

@Override
public String getHeader(String name) {
return headers.get(name);
}

public byte[] getFlushedOutput() {
try {
output.flush();
return output.toByteArray();
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
}

+ 89
- 0
server/sonar-server/src/test/java/org/sonar/server/ws/TestRequest.java Целия файл

@@ -0,0 +1,89 @@
/*
* 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.server.ws;

import com.google.common.base.Throwables;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import org.sonar.api.server.ws.internal.ValidatingRequest;

import static com.google.common.base.Preconditions.checkNotNull;

public class TestRequest extends ValidatingRequest {

private final Map<String, String> params = new HashMap<>();
private String method = "GET";
private String mimeType = "application/octet-stream";

@Override
protected String readParam(String key) {
return params.get(key);
}

@Override
protected InputStream readInputStreamParam(String key) {
throw new UnsupportedOperationException("Not supported in test yet");
}

@Override
public String method() {
return method;
}

@Override
public boolean hasParam(String key) {
return params.containsKey(key);
}

public TestRequest setMethod(String method) {
checkNotNull(method);
this.method = method;
return this;
}

public String getMimeType() {
return mimeType;
}

public TestRequest setMimeType(String type) {
checkNotNull(type);
this.mimeType = type;
return this;
}

public TestRequest setParam(String key, String value) {
checkNotNull(key);
checkNotNull(value);
this.params.put(key, value);
return this;
}

public TestResponse execute() {
try {
DumbResponse response = new DumbResponse();
action().handler().handle(this, response);
return new TestResponse(response);
} catch (Exception e) {
throw Throwables.propagate(e);
}
}

}

+ 46
- 0
server/sonar-server/src/test/java/org/sonar/server/ws/TestResponse.java Целия файл

@@ -0,0 +1,46 @@
/*
* 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.server.ws;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

public class TestResponse {

private final DumbResponse dumbResponse;

TestResponse(DumbResponse dumbResponse) {
this.dumbResponse = dumbResponse;
}

public InputStream getInputStream() {
return new ByteArrayInputStream(dumbResponse.getFlushedOutput());
}

public String getInput() {
return new String(dumbResponse.getFlushedOutput(), StandardCharsets.UTF_8);
}

public String getMediaType() {
return dumbResponse.stream().mediaType();
}

}

+ 47
- 0
server/sonar-server/src/test/java/org/sonar/server/ws/WsActionTester.java Целия файл

@@ -0,0 +1,47 @@
/*
* 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.server.ws;

import com.google.common.collect.Iterables;
import org.sonar.api.server.ws.WebService;

public class WsActionTester {

public static final String CONTROLLER_KEY = "test";
private final WebService.Action action;

public WsActionTester(WsAction wsAction) {
WebService.Context context = new WebService.Context();
WebService.NewController newController = context.createController(CONTROLLER_KEY);
wsAction.define(newController);
newController.done();
action = Iterables.get(context.controller(CONTROLLER_KEY).actions(), 0);
}

public WebService.Action getDef() {
return action;
}

public TestRequest newRequest() {
TestRequest request = new TestRequest();
request.setAction(action);
return request;
}
}

+ 14
- 0
sonar-core/src/test/java/org/sonar/core/util/ProtobufJsonFormatTest.java Целия файл

@@ -66,4 +66,18 @@ public class ProtobufJsonFormatTest {

ProtobufJsonFormat.write(protobuf, JsonWriter.of(new StringWriter()));
}

@Test
public void protobuf_empty_strings_are_not_output() throws Exception {
org.sonar.core.test.Test.Fake protobuf = org.sonar.core.test.Test.Fake.newBuilder().build();

// field is not set but value is "", not null
assertThat(protobuf.hasAString()).isFalse();
assertThat(protobuf.getAString()).isEqualTo("");

StringWriter json = new StringWriter();
JsonWriter jsonWriter = JsonWriter.of(json);
ProtobufJsonFormat.write(protobuf, jsonWriter);
assertThat(json.toString()).isEqualTo("{}");
}
}

+ 9
- 0
sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java Целия файл

@@ -23,6 +23,7 @@ import com.google.common.base.Function;
import com.google.common.base.Optional;
import java.util.List;
import javax.annotation.Nonnull;
import org.apache.ibatis.session.ResultHandler;
import org.sonar.api.rule.RuleKey;
import org.sonar.db.Dao;
import org.sonar.db.DbSession;
@@ -56,6 +57,14 @@ public class RuleDao implements Dao {
return mapper(session).selectEnabledAndNonManual();
}

public void selectEnabledAndNonManual(DbSession session, ResultHandler resultHandler) {
mapper(session).selectEnabledAndNonManual(resultHandler);
}

public void insert(DbSession session, RuleDto dto) {
mapper(session).insert(dto);
}

private RuleMapper mapper(DbSession session) {
return session.getMapper(RuleMapper.class);
}

+ 3
- 0
sonar-db/src/main/java/org/sonar/db/rule/RuleMapper.java Целия файл

@@ -23,6 +23,7 @@ import java.sql.Timestamp;
import java.util.List;
import javax.annotation.Nullable;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.session.ResultHandler;
import org.sonar.api.rule.RuleKey;

public interface RuleMapper {
@@ -31,6 +32,8 @@ public interface RuleMapper {

List<RuleDto> selectEnabledAndNonManual();

void selectEnabledAndNonManual(ResultHandler resultHandler);

List<RuleDto> selectNonManual();

List<RuleDto> selectBySubCharacteristicId(int characteristicId);

+ 34
- 0
sonar-db/src/test/java/org/sonar/db/rule/RuleDaoTest.java Целия файл

@@ -20,8 +20,12 @@
package org.sonar.db.rule;

import com.google.common.base.Optional;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
@@ -113,4 +117,34 @@ public class RuleDaoTest {
assertThat(ruleDto.getEffortToFixDescription()).isEqualTo("squid.S115.effortToFix");
}

@Test
public void insert() throws Exception {
dbTester.getDbClient().ruleDao().insert(dbTester.getSession(), RuleTesting.newDto(RuleKey.of("java", "S001")).setConfigKey(null));
dbTester.getDbClient().ruleDao().insert(dbTester.getSession(), RuleTesting.newDto(RuleKey.of("java", "S002")).setConfigKey("I002"));
dbTester.getSession().commit();

List<Map<String, Object>> rows = dbTester.select("select plugin_rule_key as \"ruleKey\" from rules order by plugin_rule_key");
assertThat(rows).hasSize(2);
assertThat(rows.get(0).get("ruleKey")).isEqualTo("S001");
assertThat(rows.get(1).get("ruleKey")).isEqualTo("S002");

}

@Test
public void selectEnabledAndNonManual_with_ResultHandler() {
dbTester.prepareDbUnit(getClass(), "selectEnabledAndNonManual.xml");

final List<RuleDto> rules = new ArrayList<>();
ResultHandler resultHandler = new ResultHandler() {
@Override
public void handleResult(ResultContext resultContext) {
rules.add((RuleDto) resultContext.getResultObject());
}
};
underTest.selectEnabledAndNonManual(dbTester.getSession(), resultHandler);

assertThat(rules.size()).isEqualTo(1);
RuleDto ruleDto = rules.get(0);
assertThat(ruleDto.getId()).isEqualTo(1);
}
}

+ 27
- 0
sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectEnabledAndNonManual.xml Целия файл

@@ -0,0 +1,27 @@
<dataset>

<rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="AvoidNull" plugin_name="checkstyle" name="Avoid Null" description="Should avoid NULL" status="READY"
note_data="Rule note with accents éèà" note_user_login="polop.palap" note_created_at="2013-12-25" description_format="HTML"
characteristic_id="100" default_characteristic_id="101"
remediation_function="LINEAR" default_remediation_function="LINEAR_OFFSET"
remediation_coeff="1h" default_remediation_coeff="5d"
remediation_offset="5min" default_remediation_offset="10h"
effort_to_fix_description="squid.S115.effortToFix"/>

<rules tags="[null]" system_tags="[null]" id="2" plugin_rule_key="AvoidNull" plugin_name="squid" name="Avoid Null" description="Should avoid NULL" status="REMOVED"
note_data="[null]" note_user_login="[null]" note_created_at="[null]" description_format="HTML"
characteristic_id="[null]" default_characteristic_id="[null]"
remediation_function="[null]" default_remediation_function="[null]"
remediation_coeff="[null]" default_remediation_coeff="[null]"
remediation_offset="[null]" default_remediation_offset="[null]"
effort_to_fix_description="[null]"/>

<rules tags="[null]" system_tags="[null]" id="3" plugin_rule_key="AvoidNull" plugin_name="manual" name="Manual Rule" description="Should not appear" status="READY"
note_data="[null]" note_user_login="[null]" note_created_at="[null]" description_format="HTML"
characteristic_id="[null]" default_characteristic_id="[null]"
remediation_function="[null]" default_remediation_function="[null]"
remediation_coeff="[null]" default_remediation_coeff="[null]"
remediation_offset="[null]" default_remediation_offset="[null]"
effort_to_fix_description="[null]"/>

</dataset>

Loading…
Отказ
Запис