diff options
12 files changed, 328 insertions, 203 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java index c0088d45fe4..0e88a06abd1 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java @@ -20,15 +20,12 @@ package org.sonar.server.qualityprofile.ws; import java.io.InputStream; -import java.io.OutputStreamWriter; -import java.nio.charset.StandardCharsets; import org.sonar.api.profiles.ProfileImporter; import org.sonar.api.resources.Languages; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService.NewAction; -import org.sonar.api.utils.text.JsonWriter; import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; @@ -37,13 +34,20 @@ import org.sonar.server.qualityprofile.QProfileExporters; import org.sonar.server.qualityprofile.QProfileFactory; import org.sonar.server.qualityprofile.QProfileName; import org.sonar.server.qualityprofile.QProfileResult; +import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; import org.sonar.server.user.UserSession; import org.sonar.server.util.LanguageParamUtils; +import org.sonarqube.ws.QualityProfiles.CreateWsResponse; +import org.sonarqube.ws.client.qualityprofile.CreateRequest; + +import static org.sonar.server.ws.WsUtils.writeProtobuf; +import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_CREATE; +import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE; +import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_NAME; public class CreateAction implements QProfileWsAction { - private static final String PARAM_PROFILE_NAME = "name"; - private static final String PARAM_LANGUAGE = "language"; + private static final String DEPRECATED_PARAM_PROFILE_NAME = "name"; private static final String PARAM_BACKUP_FORMAT = "backup_%s"; private final DbClient dbClient; @@ -58,7 +62,7 @@ public class CreateAction implements QProfileWsAction { private final UserSession userSession; public CreateAction(DbClient dbClient, QProfileFactory profileFactory, QProfileExporters exporters, - Languages languages, ProfileImporter[] importers, UserSession userSession) { + Languages languages, ProfileImporter[] importers, UserSession userSession) { this.dbClient = dbClient; this.profileFactory = profileFactory; this.exporters = exporters; @@ -73,16 +77,18 @@ public class CreateAction implements QProfileWsAction { @Override public void define(WebService.NewController controller) { - NewAction create = controller.createAction("create") + NewAction create = controller.createAction(ACTION_CREATE) .setSince("5.2") - .setDescription("Create a quality profile. Require Administer Quality Profiles permission.") + .setDescription("Create a quality profile.<br/>" + + "Require Administer Quality Profiles permission.") .setPost(true) .setResponseExample(getClass().getResource("example-create.json")) .setHandler(this); create.createParam(PARAM_PROFILE_NAME) - .setDescription("The name for the new quality profile.") + .setDescription("The name for the new quality profile. Since 6.1, this parameter has been renamed from '%s' to '%s'", DEPRECATED_PARAM_PROFILE_NAME, PARAM_PROFILE_NAME) .setExampleValue("My Sonar way") + .setDeprecatedKey(DEPRECATED_PARAM_PROFILE_NAME) .setRequired(true); create.createParam(PARAM_LANGUAGE) @@ -100,60 +106,53 @@ public class CreateAction implements QProfileWsAction { @Override public void handle(Request request, Response response) throws Exception { userSession.checkLoggedIn().checkPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN); - - String name = request.mandatoryParam(PARAM_PROFILE_NAME); - String language = request.mandatoryParam(PARAM_LANGUAGE); - + CreateRequest createRequest = toRequest(request); DbSession dbSession = dbClient.openSession(false); - try { - QProfileResult result = new QProfileResult(); - QualityProfileDto profile = profileFactory.create(dbSession, QProfileName.createFor(language, name)); - result.setProfile(profile); - for (ProfileImporter importer : importers) { - InputStream contentToImport = request.paramAsInputStream(getBackupParamName(importer.getKey())); - if (contentToImport != null) { - result.add(exporters.importXml(profile, importer.getKey(), contentToImport, dbSession)); - } - } - dbSession.commit(); - - response.stream().setMediaType(request.getMediaType()); - JsonWriter jsonWriter = JsonWriter.of(new OutputStreamWriter(response.stream().output(), StandardCharsets.UTF_8)); - writeResult(jsonWriter, result); + writeProtobuf(doHandle(dbSession, createRequest, request), request, response); } finally { dbSession.close(); } } - private void writeResult(JsonWriter json, QProfileResult result) { - String language = result.profile().getLanguage(); - json.beginObject().name("profile").beginObject() - .prop("key", result.profile().getKey()) - .prop("name", result.profile().getName()) - .prop("language", language) - .prop("languageName", languages.get(result.profile().getLanguage()).getName()) - .prop("isDefault", false) - .prop("isInherited", false) - .endObject(); - - if (!result.infos().isEmpty()) { - json.name("infos").beginArray(); - for (String info : result.infos()) { - json.value(info); + private CreateWsResponse doHandle(DbSession dbSession, CreateRequest createRequest, Request request) { + QProfileResult result = new QProfileResult(); + QualityProfileDto profile = profileFactory.create(dbSession, QProfileName.createFor(createRequest.getLanguage(), createRequest.getProfileName())); + result.setProfile(profile); + for (ProfileImporter importer : importers) { + String importerKey = importer.getKey(); + InputStream contentToImport = request.paramAsInputStream(getBackupParamName(importerKey)); + if (contentToImport != null) { + result.add(exporters.importXml(profile, importerKey, contentToImport, dbSession)); } - json.endArray(); } + dbSession.commit(); + return buildResponse(result); + } + private static CreateRequest toRequest(Request request) { + CreateRequest.Builder builder = CreateRequest.builder() + .setLanguage(request.mandatoryParam(PARAM_LANGUAGE)) + .setProfileName(request.mandatoryParam(PARAM_PROFILE_NAME)); + return builder.build(); + } + + private CreateWsResponse buildResponse(QProfileResult result) { + String language = result.profile().getLanguage(); + CreateWsResponse.QualityProfile.Builder builder = CreateWsResponse.QualityProfile.newBuilder() + .setKey(result.profile().getKey()) + .setName(result.profile().getName()) + .setLanguage(language) + .setLanguageName(languages.get(result.profile().getLanguage()).getName()) + .setIsDefault(false) + .setIsInherited(false); + if (!result.infos().isEmpty()) { + builder.getInfosBuilder().addAllInfos(result.infos()); + } if (!result.warnings().isEmpty()) { - json.name("warnings").beginArray(); - for (String warning : result.warnings()) { - json.value(warning); - } - json.endArray(); + builder.getWarningsBuilder().addAllWarnings(result.warnings()); } - - json.endObject().close(); + return CreateWsResponse.newBuilder().setProfile(builder.build()).build(); } private static String getBackupParamName(String importerKey) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionMediumTest.java deleted file mode 100644 index 9141b17ede0..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionMediumTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact 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.sonar.server.qualityprofile.ws; - -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.sonar.core.permission.GlobalPermissions; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.server.exceptions.BadRequestException; -import org.sonar.server.qualityprofile.QProfileExporters; -import org.sonar.server.qualityprofile.QProfileExportersTest.StandardExporter; -import org.sonar.server.qualityprofile.QProfileExportersTest.XooExporter; -import org.sonar.server.qualityprofile.QProfileExportersTest.XooProfileDefinition; -import org.sonar.server.qualityprofile.QProfileExportersTest.XooProfileImporter; -import org.sonar.server.qualityprofile.QProfileExportersTest.XooProfileImporterWithError; -import org.sonar.server.qualityprofile.QProfileExportersTest.XooProfileImporterWithMessages; -import org.sonar.server.qualityprofile.QProfileExportersTest.XooRulesDefinition; -import org.sonar.server.qualityprofile.QProfileLoader; -import org.sonar.server.tester.ServerTester; -import org.sonar.server.tester.UserSessionRule; -import org.sonar.server.ws.WsTester; - -public class CreateActionMediumTest { - - // TODO Replace with simpler test with DbTester / EsTester after removal of DaoV2 - @ClassRule - public static ServerTester tester = new ServerTester() - .withEsIndexes() - .withStartupTasks() - .addXoo() - .addComponents( - XooRulesDefinition.class, XooProfileDefinition.class, - XooExporter.class, StandardExporter.class, - XooProfileImporter.class, XooProfileImporterWithMessages.class, XooProfileImporterWithError.class); - @Rule - public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester); - - DbClient db; - DbSession dbSession; - QProfileExporters exporters; - QProfileLoader loader; - WsTester wsTester; - - @Before - public void before() { - db = tester.get(DbClient.class); - dbSession = db.openSession(false); - exporters = tester.get(QProfileExporters.class); - loader = tester.get(QProfileLoader.class); - wsTester = new WsTester(tester.get(QProfilesWs.class)); - } - - @After - public void after() { - dbSession.close(); - } - - @Test - public void create_nominal() throws Exception { - userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN); - - wsTester.newPostRequest("api/qualityprofiles", "create") - .setParam("backup_XooProfileImporter", "a value for xoo importer") - .setParam("language", "xoo") - .setParam("name", "My New Profile") - .execute().assertJson(this.getClass(), "create-nominal.json"); - } - - @Test - public void create_with_messages() throws Exception { - userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN); - - wsTester.newPostRequest("api/qualityprofiles", "create") - .setParam("backup_XooProfileImporter", "a value for xoo importer") - .setParam("backup_XooProfileImporterWithMessages", "this will generate some messages") - .setParam("language", "xoo") - .setParam("name", "My Other Profile") - .execute().assertJson(this.getClass(), "create-with-messages.json"); - } - - @Test(expected = BadRequestException.class) - public void fail_on_error_from_importer() throws Exception { - userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN); - - wsTester.newPostRequest("api/qualityprofiles", "create") - .setParam("backup_XooProfileImporter", "a value for xoo importer") - .setParam("backup_XooProfileImporterWithError", "this will fail") - .setParam("language", "xoo") - .setParam("name", "Error In Importer") - .execute(); - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionTest.java index 99827de0149..035496e1645 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionTest.java @@ -20,11 +20,13 @@ package org.sonar.server.qualityprofile.ws; import com.google.common.collect.ImmutableMap; +import java.io.IOException; import java.io.Reader; import java.util.Collections; import java.util.Map; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.sonar.api.config.MapSettings; import org.sonar.api.profiles.ProfileImporter; import org.sonar.api.profiles.RulesProfile; @@ -38,6 +40,7 @@ import org.sonar.db.qualityprofile.QualityProfileDto; import org.sonar.db.rule.RuleDto; import org.sonar.db.rule.RuleTesting; import org.sonar.server.es.EsTester; +import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.qualityprofile.QProfileExporters; import org.sonar.server.qualityprofile.QProfileFactory; import org.sonar.server.qualityprofile.QProfileLoader; @@ -59,6 +62,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.sonar.core.permission.GlobalPermissions.QUALITY_PROFILE_ADMIN; import static org.sonar.server.language.LanguageTesting.newLanguages; +import static org.sonarqube.ws.QualityProfiles.CreateWsResponse; +import static org.sonarqube.ws.QualityProfiles.CreateWsResponse.QualityProfile; +import static org.sonarqube.ws.QualityProfiles.CreateWsResponse.parseFrom; public class CreateActionTest { @@ -67,6 +73,9 @@ public class CreateActionTest { static final RuleDto RULE = RuleTesting.newXooX1().setSeverity("MINOR").setLanguage(XOO_LANGUAGE); @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Rule public DbTester dbTester = DbTester.create(System2.INSTANCE); @Rule @@ -98,16 +107,58 @@ public class CreateActionTest { public void create_profile() { setUserAsQualityProfileAdmin(); - executeRequest("New Profile", XOO_LANGUAGE); + CreateWsResponse response = executeRequest("New Profile", XOO_LANGUAGE); - QualityProfileDto profile = dbClient.qualityProfileDao().selectByNameAndLanguage("New Profile", XOO_LANGUAGE, dbSession); - assertThat(profile.getKey()).isNotNull(); - assertThat(profile.getLanguage()).isEqualTo(XOO_LANGUAGE); + QualityProfileDto dto = dbClient.qualityProfileDao().selectByNameAndLanguage("New Profile", XOO_LANGUAGE, dbSession); + assertThat(dto.getKey()).isNotNull(); + assertThat(dto.getLanguage()).isEqualTo(XOO_LANGUAGE); + assertThat(dto.getName()).isEqualTo("New Profile"); + + QualityProfile profile = response.getProfile(); + assertThat(profile.getKey()).isEqualTo(dto.getKey()); assertThat(profile.getName()).isEqualTo("New Profile"); + assertThat(profile.getLanguage()).isEqualTo(XOO_LANGUAGE); + assertThat(profile.getIsInherited()).isFalse(); + assertThat(profile.getIsDefault()).isFalse(); + assertThat(profile.hasInfos()).isFalse(); + assertThat(profile.hasWarnings()).isFalse(); + } + + @Test + public void create_profile_from_backup_xml() { + setUserAsQualityProfileAdmin(); + insertRule(RULE); + + executeRequest("New Profile", XOO_LANGUAGE, ImmutableMap.of("xoo_lint", "<xml/>")); + + QualityProfileDto dto = dbClient.qualityProfileDao().selectByNameAndLanguage("New Profile", XOO_LANGUAGE, dbSession); + assertThat(dto.getKey()).isNotNull(); + assertThat(dbClient.activeRuleDao().selectByProfileKey(dbSession, dto.getKey())).hasSize(1); + // FIXME + // assertThat(ruleIndex.searchAll(new RuleQuery().setQProfileKey(profile.getKey()).setActivation(true))).hasSize(1); + } + + @Test + public void create_profile_with_messages() { + setUserAsQualityProfileAdmin(); + + CreateWsResponse response = executeRequest("Profile with messages", XOO_LANGUAGE, ImmutableMap.of("with_messages", "<xml/>")); + + QualityProfile profile = response.getProfile(); + assertThat(profile.getInfos().getInfosList()).containsOnly("an info"); + assertThat(profile.getWarnings().getWarningsList()).containsOnly("a warning"); } @Test - public void return_created_profile_in_json() throws Exception { + public void fail_if_import_generate_error() { + setUserAsQualityProfileAdmin(); + + expectedException.expect(BadRequestException.class); + executeRequest("Profile with errors", XOO_LANGUAGE, ImmutableMap.of("with_errors", "<xml/>")); + } + + @Test + public void test_json() throws Exception { setUserAsQualityProfileAdmin(); TestResponse response = wsTester.newRequest() @@ -117,35 +168,21 @@ public class CreateActionTest { .setParam("name", "Yeehaw!") .execute(); - JsonAssert.assertJson(response.getInput()).isSimilarTo(getClass().getResource("CreateActionTest/create-no-importer.json")); + JsonAssert.assertJson(response.getInput()).isSimilarTo(getClass().getResource("CreateActionTest/test_json.json")); assertThat(response.getMediaType()).isEqualTo(MediaTypes.JSON); } - @Test - public void create_profile_from_xml() { - setUserAsQualityProfileAdmin(); - insertRule(RULE); - - executeRequest("New Profile", XOO_LANGUAGE, ImmutableMap.of("xoo_lint", "<xml/>")); - - QualityProfileDto profile = dbClient.qualityProfileDao().selectByNameAndLanguage("New Profile", XOO_LANGUAGE, dbSession); - assertThat(profile.getKey()).isNotNull(); - assertThat(dbClient.activeRuleDao().selectByProfileKey(dbSession, profile.getKey())).hasSize(1); - // FIXME - // assertThat(ruleIndex.searchAll(new RuleQuery().setQProfileKey(profile.getKey()).setActivation(true))).hasSize(1); - } - private void insertRule(RuleDto ruleDto) { dbClient.ruleDao().insert(dbSession, ruleDto); dbSession.commit(); ruleIndexer.index(); } - private void executeRequest(String name, String language) { - executeRequest(name, language, Collections.emptyMap()); + private CreateWsResponse executeRequest(String name, String language) { + return executeRequest(name, language, Collections.emptyMap()); } - private void executeRequest(String name, String language, Map<String, String> xmls) { + private CreateWsResponse executeRequest(String name, String language, Map<String, String> xmls) { TestRequest request = wsTester.newRequest() .setMediaType(MediaTypes.PROTOBUF) .setParam("name", name) @@ -153,7 +190,11 @@ public class CreateActionTest { for (Map.Entry<String, String> entry : xmls.entrySet()) { request.setParam("backup_" + entry.getKey(), entry.getValue()); } - request.execute(); + try { + return parseFrom(request.execute().getInputStream()); + } catch (IOException e) { + throw new IllegalStateException(e); + } } private void setUserAsQualityProfileAdmin() { @@ -162,9 +203,9 @@ public class CreateActionTest { private ProfileImporter[] createImporters() { class DefaultProfileImporter extends ProfileImporter { - private DefaultProfileImporter(String key, String name, String... languages) { - super(key, name); - setSupportedLanguages(languages); + private DefaultProfileImporter() { + super("xoo_lint", "Xoo Lint"); + setSupportedLanguages(XOO_LANGUAGE); } @Override @@ -173,10 +214,39 @@ public class CreateActionTest { rulesProfile.activateRule(org.sonar.api.rules.Rule.create(RULE.getRepositoryKey(), RULE.getRuleKey()), RulePriority.BLOCKER); return rulesProfile; } + } + class ProfileImporterGeneratingMessages extends ProfileImporter { + private ProfileImporterGeneratingMessages() { + super("with_messages", "With messages"); + setSupportedLanguages(XOO_LANGUAGE); + } + + @Override + public RulesProfile importProfile(Reader reader, ValidationMessages messages) { + RulesProfile rulesProfile = RulesProfile.create(); + messages.addWarningText("a warning"); + messages.addInfoText("an info"); + return rulesProfile; + } } + + class ProfileImporterGeneratingErrors extends ProfileImporter { + private ProfileImporterGeneratingErrors() { + super("with_errors", "With errors"); + setSupportedLanguages(XOO_LANGUAGE); + } + + @Override + public RulesProfile importProfile(Reader reader, ValidationMessages messages) { + RulesProfile rulesProfile = RulesProfile.create(); + messages.addErrorText("error!"); + return rulesProfile; + } + } + return new ProfileImporter[] { - new DefaultProfileImporter("xoo_lint", "Xoo Lint", XOO_LANGUAGE) + new DefaultProfileImporter(), new ProfileImporterGeneratingMessages(), new ProfileImporterGeneratingErrors() }; } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java index 4acd2d1ad60..44571cc9cde 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java @@ -213,8 +213,8 @@ public class QProfilesWsTest { assertThat(create).isNotNull(); assertThat(create.isPost()).isTrue(); assertThat(create.params()).hasSize(4); - assertThat(create.param("name")).isNotNull(); - assertThat(create.param("name").isRequired()).isTrue(); + assertThat(create.param("profileName")).isNotNull(); + assertThat(create.param("profileName").isRequired()).isTrue(); assertThat(create.param("language").possibleValues()).containsOnly(xoo1Key, xoo2Key); assertThat(create.param("language").isRequired()).isTrue(); assertThat(create.param("backup_" + xoo1Key)).isNotNull(); diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CreateActionMediumTest/create-nominal.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CreateActionMediumTest/create-nominal.json deleted file mode 100644 index a00e1eb1acc..00000000000 --- a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CreateActionMediumTest/create-nominal.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "profile": { - "name": "My New Profile", - "language": "xoo", - "languageName": "Xoo", - "isDefault": false, - "isInherited": false - } -}
\ No newline at end of file diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CreateActionTest/create-no-importer.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CreateActionTest/test_json.json index 367abddd246..367abddd246 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CreateActionTest/create-no-importer.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CreateActionTest/test_json.json diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/CreateRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/CreateRequest.java new file mode 100644 index 00000000000..9b7bfd9b12a --- /dev/null +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/CreateRequest.java @@ -0,0 +1,72 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.qualityprofile; + +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkArgument; + +public class CreateRequest { + + private final String profileName; + private final String language; + + private CreateRequest(Builder builder) { + this.profileName = builder.profileName; + this.language = builder.language; + } + + public String getLanguage() { + return language; + } + + public String getProfileName() { + return profileName; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String language; + private String profileName; + + private Builder() { + // enforce factory method use + } + + public Builder setLanguage(@Nullable String language) { + this.language = language; + return this; + } + + public Builder setProfileName(@Nullable String profileName) { + this.profileName = profileName; + return this; + } + + public CreateRequest build() { + checkArgument(language != null && !language.isEmpty(), "Language is mandatory and must not be empty."); + checkArgument(profileName != null && !profileName.isEmpty(), "Profile name is mandatory and must not be empty."); + return new CreateRequest(this); + } + } +} diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfileWsParameters.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfileWsParameters.java index 8d75d163c4d..3b73744eab3 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfileWsParameters.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfileWsParameters.java @@ -26,6 +26,7 @@ public class QualityProfileWsParameters { public static final String ACTION_SEARCH = "search"; public static final String ACTION_ADD_PROJECT = "add_project"; public static final String ACTION_REMOVE_PROJECT = "remove_project"; + public static final String ACTION_CREATE = "create"; public static final String PARAM_DEFAULTS = "defaults"; public static final String PARAM_LANGUAGE = "language"; diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfilesService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfilesService.java index f9256557011..94475a1ea46 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfilesService.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfilesService.java @@ -19,6 +19,7 @@ */ package org.sonarqube.ws.client.qualityprofile; +import org.sonarqube.ws.QualityProfiles.CreateWsResponse; import org.sonarqube.ws.QualityProfiles.SearchWsResponse; import org.sonarqube.ws.client.BaseService; import org.sonarqube.ws.client.GetRequest; @@ -26,6 +27,7 @@ import org.sonarqube.ws.client.PostRequest; import org.sonarqube.ws.client.WsConnector; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_ADD_PROJECT; +import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_CREATE; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_REMOVE_PROJECT; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_SEARCH; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.CONTROLLER_QUALITY_PROFILES; @@ -70,4 +72,11 @@ public class QualityProfilesService extends BaseService { .setParam(PARAM_PROJECT_UUID, request.getProjectUuid())); } + public CreateWsResponse create(CreateRequest request) { + PostRequest postRequest = new PostRequest(path(ACTION_CREATE)) + .setParam(PARAM_LANGUAGE, request.getLanguage()) + .setParam(PARAM_PROFILE_NAME, request.getProfileName()); + return call(postRequest, CreateWsResponse.parser()); + } + } diff --git a/sonar-ws/src/main/protobuf/ws-qualityprofiles.proto b/sonar-ws/src/main/protobuf/ws-qualityprofiles.proto index 0829180d46d..d131d02714c 100644 --- a/sonar-ws/src/main/protobuf/ws-qualityprofiles.proto +++ b/sonar-ws/src/main/protobuf/ws-qualityprofiles.proto @@ -45,3 +45,27 @@ message SearchWsResponse { optional string userUpdatedAt = 14; } } + +// WS api/qualityprofiles/create +message CreateWsResponse { + optional QualityProfile profile = 1; + + message QualityProfile { + optional string key = 1; + optional string name = 2; + optional string language = 3; + optional string languageName = 4; + optional bool isInherited = 5; + optional bool isDefault = 6; + optional Infos infos = 7; + optional Warnings warnings = 8; + + message Infos { + repeated string infos = 1; + } + + message Warnings { + repeated string warnings = 1; + } + } +} diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/qualityprofile/CreateRequestTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/qualityprofile/CreateRequestTest.java new file mode 100644 index 00000000000..768f3a68cda --- /dev/null +++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/qualityprofile/CreateRequestTest.java @@ -0,0 +1,59 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.qualityprofile; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CreateRequestTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + CreateRequest.Builder underTest = CreateRequest.builder(); + + @Test + public void create_set_request() { + CreateRequest result = underTest + .setLanguage("java") + .setProfileName("Sonar way") + .build(); + + assertThat(result.getLanguage()).isEqualTo("java"); + assertThat(result.getProfileName()).isEqualTo("Sonar way"); + } + + @Test + public void fail_when_no_language() { + expectedException.expect(IllegalArgumentException.class); + underTest.setProfileName("Sonar way").build(); + } + + @Test + public void fail_when_no_profile_name() { + expectedException.expect(IllegalArgumentException.class); + underTest.setLanguage("java").build(); + } + +} diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/qualityprofile/QualityProfilesServiceTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/qualityprofile/QualityProfilesServiceTest.java index 91ddb86ef69..0867a1542f3 100644 --- a/sonar-ws/src/test/java/org/sonarqube/ws/client/qualityprofile/QualityProfilesServiceTest.java +++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/qualityprofile/QualityProfilesServiceTest.java @@ -87,4 +87,17 @@ public class QualityProfilesServiceTest { .hasParam(PARAM_PROJECT_KEY, "sample") .andNoOtherParam(); } + + @Test + public void create_project() throws Exception { + underTest.create(CreateRequest.builder() + .setLanguage("xoo") + .setProfileName("Sonar Way") + .build()); + + serviceTester.assertThat(serviceTester.getPostRequest()) + .hasParam(PARAM_LANGUAGE, "xoo") + .hasParam(PARAM_PROFILE_NAME, "Sonar Way") + .andNoOtherParam(); + } } |