From 69fffe506946ca3ec0a0fd079a8bffee05b0bf57 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Mon, 16 Jun 2014 14:21:25 +0200 Subject: [PATCH] SONAR-5007 improve l10n of server exception handling --- .../DefaultRubyComponentService.java | 2 +- .../server/debt/DebtModelOperations.java | 3 +- .../exceptions/BadRequestException.java | 144 ++++-------------- .../org/sonar/server/exceptions/Errors.java | 100 ++++++++++++ .../org/sonar/server/exceptions/Message.java | 84 ++-------- .../org/sonar/server/exceptions/Messages.java | 66 -------- .../server/exceptions/ServerException.java | 33 ---- .../server/exceptions/Verifications.java | 33 ++++ .../issue/InternalRubyIssueService.java | 2 +- .../server/issue/IssueBulkChangeQuery.java | 8 +- .../server/qualitygate/QualityGates.java | 82 +++++----- .../qualityprofile/BulkChangeResult.java | 14 +- .../qualityprofile/QProfileOperations.java | 5 +- .../QProfileRepositoryExporter.java | 16 +- .../server/qualityprofile/QProfileReset.java | 12 +- .../server/qualityprofile/QProfiles.java | 2 +- .../ws/BulkRuleActivationActions.java | 8 +- .../ws/QProfileRestoreBuiltInAction.java | 28 +--- .../org/sonar/server/rule/RuleOperations.java | 2 +- .../server/util/BooleanTypeValidation.java | 2 +- .../server/util/FloatTypeValidation.java | 5 +- .../server/util/IntegerTypeValidation.java | 2 +- .../server/util/StringListTypeValidation.java | 2 +- .../org/sonar/server/util/TypeValidation.java | 3 +- .../sonar/server/util/TypeValidations.java | 3 +- .../org/sonar/server/util/Validation.java | 10 +- .../org/sonar/server/ws/WebServiceEngine.java | 53 ++----- .../server/debt/DebtModelOperationsTest.java | 13 +- .../exceptions/BadRequestExceptionTest.java | 79 +--------- .../exceptions/ServerExceptionTest.java | 20 +-- .../server/exceptions/VerificationsTest.java | 42 +++++ .../issue/InternalRubyIssueServiceTest.java | 6 +- .../issue/IssueBulkChangeQueryTest.java | 4 +- .../server/qualitygate/ws/QGatesWsTest.java | 2 +- .../QProfileRepositoryExporterTest.java | 10 +- .../RuleActivatorMediumTest.java | 4 +- .../ws/QProfileRestoreBuiltInActionTest.java | 31 +--- .../qualityprofile/ws/QProfilesWsTest.java | 4 +- .../util/BooleanTypeValidationTest.java | 2 +- .../server/util/FloatTypeValidationTest.java | 2 +- .../util/IntegerTypeValidationTest.java | 2 +- .../util/StringListTypeValidationTest.java | 4 +- .../server/util/TypeValidationsTest.java | 2 +- .../sonar/server/ws/WebServiceEngineTest.java | 68 +++------ 44 files changed, 373 insertions(+), 646 deletions(-) create mode 100644 sonar-server/src/main/java/org/sonar/server/exceptions/Errors.java delete mode 100644 sonar-server/src/main/java/org/sonar/server/exceptions/Messages.java create mode 100644 sonar-server/src/main/java/org/sonar/server/exceptions/Verifications.java create mode 100644 sonar-server/src/test/java/org/sonar/server/exceptions/VerificationsTest.java diff --git a/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java b/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java index ace86157de1..94de74f57e4 100644 --- a/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java +++ b/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java @@ -75,7 +75,7 @@ public class DefaultRubyComponentService implements RubyComponentService { .setCreatedAt(new Date())); component = (ComponentDto) resourceDao.findByKey(kee); if (component == null) { - throw new BadRequestException(String.format("%s not created: %s", null, kee)); + throw new BadRequestException(String.format("Component not created: %s", kee)); } resourceIndexerDao.indexResource(component.getId()); return component.getId(); diff --git a/sonar-server/src/main/java/org/sonar/server/debt/DebtModelOperations.java b/sonar-server/src/main/java/org/sonar/server/debt/DebtModelOperations.java index 5773eb9dcf4..fcb32e591e8 100644 --- a/sonar-server/src/main/java/org/sonar/server/debt/DebtModelOperations.java +++ b/sonar-server/src/main/java/org/sonar/server/debt/DebtModelOperations.java @@ -41,6 +41,7 @@ import org.sonar.server.util.Validation; import javax.annotation.CheckForNull; import javax.annotation.Nullable; + import java.util.Date; import java.util.List; @@ -253,7 +254,7 @@ public class DebtModelOperations implements ServerComponent { private void checkNotAlreadyExists(String name, SqlSession session) { if (dbClient.debtCharacteristicDao().selectByName(name, session) != null) { - throw BadRequestException.ofL10n(Validation.IS_ALREADY_USED_MESSAGE, name); + throw new BadRequestException(Validation.IS_ALREADY_USED_MESSAGE, name); } } diff --git a/sonar-server/src/main/java/org/sonar/server/exceptions/BadRequestException.java b/sonar-server/src/main/java/org/sonar/server/exceptions/BadRequestException.java index 27e6c2f1453..22f224b3d6f 100644 --- a/sonar-server/src/main/java/org/sonar/server/exceptions/BadRequestException.java +++ b/sonar-server/src/main/java/org/sonar/server/exceptions/BadRequestException.java @@ -19,16 +19,11 @@ */ package org.sonar.server.exceptions; -import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import com.google.common.base.Objects; +import org.sonar.api.utils.ValidationMessages; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - -import java.util.Arrays; import java.util.List; -import static com.google.common.collect.Lists.newArrayList; - /** * Request is not valid and can not be processed. */ @@ -36,127 +31,48 @@ public class BadRequestException extends ServerException { private static final int BAD_REQUEST = 400; - private final List errors; - - public BadRequestException(String message) { - super(BAD_REQUEST, message); - this.errors = newArrayList(); - } - - public BadRequestException(String message, List errors) { - super(BAD_REQUEST, message); - this.errors = errors; - } + private final Errors errors; - public BadRequestException(@Nullable String message, @Nullable String l10nKey, @Nullable Object[] l10nParams) { - super(BAD_REQUEST, message, l10nKey, l10nParams); - this.errors = newArrayList(); + public BadRequestException(String l10nKey, Object... l10nParams) { + super(BAD_REQUEST); + this.errors = new Errors().add(Message.of(l10nKey, l10nParams)); } - public BadRequestException(@Nullable String message, @Nullable String l10nKey, @Nullable Object[] l10nParams, List errors) { - super(BAD_REQUEST, message, l10nKey, l10nParams); - this.errors = errors; + public BadRequestException(List messages) { + super(BAD_REQUEST); + this.errors = new Errors().add(messages); } - public static BadRequestException of(String message) { - return new BadRequestException(message); + public BadRequestException(Errors e) { + super(BAD_REQUEST); + this.errors = e; } - public static BadRequestException of(String message, List errors) { - return new BadRequestException(message, errors); + public BadRequestException(ValidationMessages validationMessages) { + super(BAD_REQUEST); + this.errors = new Errors(); + for (String s : validationMessages.getErrors()) { + errors.add(Message.of(s)); + } } - public static BadRequestException of(List errors) { - return new BadRequestException(null, null, null, errors); + public Errors errors() { + return errors; } - public static BadRequestException ofL10n(String l10nKey, Object... l10nParams) { - return new BadRequestException(null, l10nKey, l10nParams); + public Message firstError() { + return errors.messages().get(0); } - public static BadRequestException ofL10n(List errors, String l10nKey, Object... l10nParams) { - return new BadRequestException(null, l10nKey, l10nParams, errors); + @Override + public String getMessage() { + return firstError().getKey(); } - /** - * List of error messages. Empty if there are no errors. - */ - public List errors() { - return errors; + @Override + public String toString() { + return Objects.toStringHelper(this) + .add("errors", errors) + .toString(); } - - public static class Message { - private final String l10nKey; - private final Object[] l10nParams; - private final String text; - - private Message(@Nullable String l10nKey, @Nullable Object[] l10nParams, @Nullable String text) { - this.l10nKey = l10nKey; - this.l10nParams = l10nParams; - this.text = text; - } - - public static Message of(String text) { - return new Message(null, null, text); - } - - public static Message ofL10n(String l10nKey, Object... l10nParams) { - return new Message(l10nKey, l10nParams, null); - } - - @CheckForNull - public String text() { - return text; - } - - @CheckForNull - public String l10nKey() { - return l10nKey; - } - - public Object[] l10nParams() { - if (l10nParams == null) { - return new Object[0]; - } else { - return Arrays.copyOf(l10nParams, l10nParams.length); - } - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Message message = (Message) o; - - if (l10nKey != null ? !l10nKey.equals(message.l10nKey) : message.l10nKey != null) { - return false; - } - // Probably incorrect - comparing Object[] arrays with Arrays.equals - if (!Arrays.equals(l10nParams, message.l10nParams)) { - return false; - } - if (text != null ? !text.equals(message.text) : message.text != null) { - return false; - } - return true; - } - - @Override - public int hashCode() { - int result = l10nKey != null ? l10nKey.hashCode() : 0; - result = 31 * result + (l10nParams != null ? Arrays.hashCode(l10nParams) : 0); - result = 31 * result + (text != null ? text.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return new ReflectionToStringBuilder(this).toString(); - } - } - } diff --git a/sonar-server/src/main/java/org/sonar/server/exceptions/Errors.java b/sonar-server/src/main/java/org/sonar/server/exceptions/Errors.java new file mode 100644 index 00000000000..0cdee465cf1 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/exceptions/Errors.java @@ -0,0 +1,100 @@ +/* + * 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.exceptions; + +import com.google.common.base.Objects; +import com.google.common.collect.Lists; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.i18n.I18n; +import org.sonar.api.utils.text.JsonWriter; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +public class Errors { + + private final List messages = Lists.newArrayList(); + + public Errors() { + } + + public Errors add(Errors errors) { + this.messages.addAll(errors.messages()); + return this; + } + + public Errors add(Collection messages) { + for (Message message : messages) { + add(message); + } + return this; + } + + public Errors add(Message message, Message... others) { + messages.add(message); + Collections.addAll(messages, others); + return this; + } + + public List messages() { + return messages; + } + + public boolean isEmpty() { + return messages.isEmpty(); + } + + public boolean check(boolean expression, String l10nKey, Object... l10nParams) { + if (!expression) { + add(Message.of(l10nKey, l10nParams)); + } + return expression; + } + + public void writeJson(JsonWriter json, I18n i18n, Locale locale) { + writeJson(json, i18n, locale, "errors"); + } + + public void writeJsonAsWarnings(JsonWriter json, I18n i18n, Locale locale) { + writeJson(json, i18n, locale, "warnings"); + } + + private void writeJson(JsonWriter json, I18n i18n, Locale locale, String name) { + if (!messages.isEmpty()) { + json.name(name).beginArray(); + for (Message message : messages) { + json.beginObject(); + String text = StringUtils.defaultString(i18n.message(locale, message.getKey(), message.getKey(), message.getParams()), message.getKey()); + json.prop("msg", text); + json.endObject(); + } + json.endArray(); + } + } + + @Override + public String toString() { + return Objects.toStringHelper(this) + .add("messages", messages) + .toString(); + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/exceptions/Message.java b/sonar-server/src/main/java/org/sonar/server/exceptions/Message.java index 5a332610ba5..0882de85f19 100644 --- a/sonar-server/src/main/java/org/sonar/server/exceptions/Message.java +++ b/sonar-server/src/main/java/org/sonar/server/exceptions/Message.java @@ -20,92 +20,36 @@ package org.sonar.server.exceptions; import com.google.common.base.Objects; - -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - -import java.util.Map; +import com.google.common.base.Preconditions; +import org.apache.commons.lang.StringUtils; public class Message { - public static enum Level { - INFO, WARNING, ERROR - } - - private final String code; - private String label; - private Object[] l10nParams = new Object[0]; - private Level level; - private Map params; - - private Message(String code) { - this.code = code; - } - - public String getCode() { - return code; - } -@CheckForNull - public String getLabel() { - return label; - } - - public Message setLabel(String s) { - this.label = s; - return this; - } - - public Object[] getL10nParams() { - return l10nParams; - } + private final String key; + private final Object[] params; - public Message setL10nParams(Object[] l10nParams) { - this.l10nParams = l10nParams; - return this; - } - - public Level getLevel() { - return level; - } - - public Message setLevel(Level level) { - this.level = level; - return this; - } - - public Map getParams() { - return params; - } - - public Message setParams(Map params) { + private Message(String key, Object[] params) { + this.key = key; this.params = params; - return this; } - public Message setParam(String key, @Nullable Object value) { - this.params.put(key, value); - return this; + public String getKey() { + return key; } - public static Message newError(String code) { - return new Message(code).setLevel(Level.ERROR); - } - - public static Message newWarning(String code) { - return new Message(code).setLevel(Level.WARNING); + public Object[] getParams() { + return params; } - public static Message newInfo(String code) { - return new Message(code).setLevel(Level.INFO); + public static Message of(String l10nKey, Object... l10nParams) { + Preconditions.checkArgument(StringUtils.isNotBlank(l10nKey)); + return new Message(l10nKey, l10nParams); } @Override public String toString() { return Objects.toStringHelper(this) - .add("code", code) - .add("label", label) - .add("l10nParams", l10nParams) - .add("level", level) + .add("key", key) .add("params", params) .toString(); } diff --git a/sonar-server/src/main/java/org/sonar/server/exceptions/Messages.java b/sonar-server/src/main/java/org/sonar/server/exceptions/Messages.java deleted file mode 100644 index 89a68ca5292..00000000000 --- a/sonar-server/src/main/java/org/sonar/server/exceptions/Messages.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.exceptions; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.ListMultimap; -import org.sonar.api.utils.text.JsonWriter; - -import java.util.Collection; -import java.util.List; - -public class Messages { - - private ListMultimap messagesByLevel = ArrayListMultimap.create(); - - public Messages add(Message message) { - messagesByLevel.put(message.getLevel(), message); - return this; - } - - public Collection all() { - return messagesByLevel.values(); - } - - public List getByLevel(Message.Level level) { - return messagesByLevel.get(level); - } - - public boolean hasLevel(Message.Level level) { - return messagesByLevel.containsKey(level); - } - - public void writeJson(JsonWriter json) { - writeJson(json, "errors", Message.Level.ERROR); - writeJson(json, "warnings", Message.Level.WARNING); - writeJson(json, "infos", Message.Level.INFO); - } - - private void writeJson(JsonWriter json, String label, Message.Level level) { - List messages = messagesByLevel.get(level); - if (!messages.isEmpty()) { - json.name(label).beginArray(); - for (Message message : messages) { - json.beginObject().prop("msg", message.getLabel()).endObject(); - } - json.endArray(); - } - } -} diff --git a/sonar-server/src/main/java/org/sonar/server/exceptions/ServerException.java b/sonar-server/src/main/java/org/sonar/server/exceptions/ServerException.java index 2dfd845e758..bce33f965ca 100644 --- a/sonar-server/src/main/java/org/sonar/server/exceptions/ServerException.java +++ b/sonar-server/src/main/java/org/sonar/server/exceptions/ServerException.java @@ -19,52 +19,19 @@ */ package org.sonar.server.exceptions; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - -import java.util.Arrays; - public class ServerException extends RuntimeException { private final int httpCode; - private final String l10nKey; - private final Object[] l10nParams; - public ServerException(int httpCode) { this.httpCode = httpCode; - this.l10nKey = null; - this.l10nParams = null; } public ServerException(int httpCode, String message) { super(message); this.httpCode = httpCode; - this.l10nKey = null; - this.l10nParams = null; - } - - public ServerException(int httpCode, @Nullable String message, @Nullable String l10nKey, @Nullable Object[] l10nParams) { - super(message); - this.httpCode = httpCode; - this.l10nKey = l10nKey; - this.l10nParams = l10nParams; } public int httpCode() { return httpCode; } - - @CheckForNull - public String l10nKey() { - return l10nKey; - } - - @CheckForNull - public Object[] l10nParams() { - if (l10nParams == null) { - return new Object[0]; - } else { - return Arrays.copyOf(l10nParams, l10nParams.length); - } - } } diff --git a/sonar-server/src/main/java/org/sonar/server/exceptions/Verifications.java b/sonar-server/src/main/java/org/sonar/server/exceptions/Verifications.java new file mode 100644 index 00000000000..d865ab29864 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/exceptions/Verifications.java @@ -0,0 +1,33 @@ +/* + * 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.exceptions; + +public class Verifications { + + private Verifications() { + // only static stuff + } + + public static void check(boolean expression, String l10nKey, Object... l10nParams) { + if (!expression) { + throw new BadRequestException(l10nKey, l10nParams); + } + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java b/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java index 0ccfca938c2..9ed1662e746 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java @@ -615,7 +615,7 @@ public class InternalRubyIssueService implements ServerComponent { private void checkOptionalSizeParameter(String value, String paramName, Integer size) { if (!Strings.isNullOrEmpty(value) && value.length() > size) { - throw BadRequestException.ofL10n(Validation.IS_TOO_LONG_MESSAGE, paramName, size); + throw new BadRequestException(Validation.IS_TOO_LONG_MESSAGE, paramName, size); } } diff --git a/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeQuery.java b/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeQuery.java index aa7f17c020b..2dff217866e 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeQuery.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeQuery.java @@ -62,14 +62,14 @@ public class IssueBulkChangeQuery { parse(props, null); } - private void parse(Map props, String comment) { + private void parse(Map props, @Nullable String comment) { this.issues = sanitizeList(RubyUtils.toStrings(props.get("issues"))); if (issues == null || issues.isEmpty()) { - throw BadRequestException.ofL10n("issue_bulk_change.error.empty_issues"); + throw new BadRequestException("issue_bulk_change.error.empty_issues"); } actions = sanitizeList(RubyUtils.toStrings(props.get("actions"))); if (actions == null || actions.isEmpty()) { - throw BadRequestException.ofL10n("issue_bulk_change.error.need_one_action"); + throw new BadRequestException("issue_bulk_change.error.need_one_action"); } for (String action : actions) { Map actionProperties = getActionProps(action, props); @@ -83,7 +83,7 @@ public class IssueBulkChangeQuery { } } - private List sanitizeList(List list) { + private List sanitizeList(@Nullable List list) { if (list == null || list.isEmpty()) { return Collections.emptyList(); } diff --git a/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java b/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java index 7117afc7a0b..924eb4a914c 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java +++ b/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java @@ -40,7 +40,8 @@ import org.sonar.core.qualitygate.db.QualityGateDao; import org.sonar.core.qualitygate.db.QualityGateDto; import org.sonar.server.component.persistence.ComponentDao; import org.sonar.server.exceptions.BadRequestException; -import org.sonar.server.exceptions.BadRequestException.Message; +import org.sonar.server.exceptions.Errors; +import org.sonar.server.exceptions.Message; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.exceptions.ServerException; import org.sonar.server.user.UserSession; @@ -50,10 +51,6 @@ import javax.annotation.CheckForNull; import javax.annotation.Nullable; import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import static com.google.common.collect.Lists.newArrayList; /** * @since 4.3 @@ -75,7 +72,7 @@ public class QualityGates { private final MyBatis myBatis; public QualityGates(QualityGateDao dao, QualityGateConditionDao conditionDao, MetricFinder metricFinder, PropertiesDao propertiesDao, ComponentDao componentDao, - MyBatis myBatis) { + MyBatis myBatis) { this.dao = dao; this.conditionDao = conditionDao; this.metricFinder = metricFinder; @@ -119,10 +116,10 @@ public class QualityGates { dao.insert(destinationGate, session); for (QualityGateConditionDto sourceCondition : conditionDao.selectForQualityGate(sourceId, session)) { conditionDao.insert(new QualityGateConditionDto().setQualityGateId(destinationGate.getId()) - .setMetricId(sourceCondition.getMetricId()).setOperator(sourceCondition.getOperator()) - .setWarningThreshold(sourceCondition.getWarningThreshold()).setErrorThreshold(sourceCondition.getErrorThreshold()).setPeriod(sourceCondition.getPeriod()), + .setMetricId(sourceCondition.getMetricId()).setOperator(sourceCondition.getOperator()) + .setWarningThreshold(sourceCondition.getWarningThreshold()).setErrorThreshold(sourceCondition.getErrorThreshold()).setPeriod(sourceCondition.getPeriod()), session - ); + ); } session.commit(); } finally { @@ -131,7 +128,6 @@ public class QualityGates { return destinationGate; } - public Collection list() { return dao.selectAll(); } @@ -173,7 +169,7 @@ public class QualityGates { } public QualityGateConditionDto createCondition(long qGateId, String metricKey, String operator, - @Nullable String warningThreshold, @Nullable String errorThreshold, @Nullable Integer period) { + @Nullable String warningThreshold, @Nullable String errorThreshold, @Nullable Integer period) { checkPermission(UserSession.get()); getNonNullQgate(qGateId); Metric metric = getNonNullMetric(metricKey); @@ -186,7 +182,7 @@ public class QualityGates { } public QualityGateConditionDto updateCondition(long condId, String metricKey, String operator, - @Nullable String warningThreshold, @Nullable String errorThreshold, @Nullable Integer period) { + @Nullable String warningThreshold, @Nullable String errorThreshold, @Nullable Integer period) { checkPermission(UserSession.get()); QualityGateConditionDto condition = getNonNullCondition(condId); Metric metric = getNonNullMetric(metricKey); @@ -257,42 +253,36 @@ public class QualityGates { } private void validateCondition(Metric metric, String operator, @Nullable String warningThreshold, @Nullable String errorThreshold, @Nullable Integer period) { - List validationMessages = newArrayList(); - validateMetric(metric, validationMessages); - validateOperator(metric, operator, validationMessages); - validateThresholds(warningThreshold, errorThreshold, validationMessages); - validatePeriod(metric, period, validationMessages); - if (!validationMessages.isEmpty()) { - throw BadRequestException.of(validationMessages); + Errors errors = new Errors(); + validateMetric(metric, errors); + checkOperator(metric, operator, errors); + checkThresholds(warningThreshold, errorThreshold, errors); + checkPeriod(metric, period, errors); + if (!errors.isEmpty()) { + throw new BadRequestException(errors); } } - private void validatePeriod(Metric metric, @Nullable Integer period, List validationMessages) { + private void checkPeriod(Metric metric, @Nullable Integer period, Errors errors) { if (period == null) { - if (metric.getKey().startsWith("new_")) { - validationMessages.add(Message.of("A period must be selected for differential metrics.")); - } - } else if (period < 1 || period > 5) { - validationMessages.add(Message.of("Valid periods are integers between 1 and 5 (included).")); + errors.check(!metric.getKey().startsWith("new_"), "A period must be selected for differential metrics."); + + } else { + errors.check(period >= 1 && period <= 5, "Valid periods are integers between 1 and 5 (included)."); } } - private void validateThresholds(@Nullable String warningThreshold, @Nullable String errorThreshold, List validationMessages) { - if (warningThreshold == null && errorThreshold == null) { - validationMessages.add(Message.of("At least one threshold (warning, error) must be set.")); - } + private void checkThresholds(@Nullable String warningThreshold, @Nullable String errorThreshold, Errors errors) { + errors.check(warningThreshold != null || errorThreshold != null, "At least one threshold (warning, error) must be set."); } - private void validateOperator(Metric metric, String operator, List validationMessages) { - if (!QualityGateConditionDto.isOperatorAllowed(operator, metric.getType())) { - validationMessages.add(Message.of(String.format("Operator %s is not allowed for metric type %s.", operator, metric.getType()))); - } + private void checkOperator(Metric metric, String operator, Errors errors) { + errors + .check(QualityGateConditionDto.isOperatorAllowed(operator, metric.getType()), String.format("Operator %s is not allowed for metric type %s.", operator, metric.getType())); } - private void validateMetric(Metric metric, List validationMessages) { - if (!isAlertable(metric)) { - validationMessages.add(Message.of(String.format("Metric '%s' cannot be used to define a condition.", metric.getKey()))); - } + private void validateMetric(Metric metric, Errors errors) { + errors.check(isAlertable(metric), String.format("Metric '%s' cannot be used to define a condition.", metric.getKey())); } private boolean isAvailableForInit(Metric metric) { @@ -355,24 +345,22 @@ public class QualityGates { } private void validateQualityGate(@Nullable Long updatingQgateId, @Nullable String name) { - List messages = newArrayList(); + Errors errors = new Errors(); if (Strings.isNullOrEmpty(name)) { - messages.add(BadRequestException.Message.ofL10n(Validation.CANT_BE_EMPTY_MESSAGE, "Name")); + errors.add(Message.of(Validation.CANT_BE_EMPTY_MESSAGE, "Name")); } else { - messages.addAll(checkQgateNotAlreadyExists(updatingQgateId, name)); + checkQgateNotAlreadyExists(updatingQgateId, name, errors); } - if (!messages.isEmpty()) { - throw BadRequestException.of(messages); + if (!errors.isEmpty()) { + throw new BadRequestException(errors); } } - private Collection checkQgateNotAlreadyExists(@Nullable Long updatingQgateId, String name) { + private void checkQgateNotAlreadyExists(@Nullable Long updatingQgateId, String name, Errors errors) { QualityGateDto existingQgate = dao.selectByName(name); boolean isModifyingCurrentQgate = updatingQgateId != null && existingQgate != null && existingQgate.getId().equals(updatingQgateId); - if (!isModifyingCurrentQgate && existingQgate != null) { - return Collections.singleton(BadRequestException.Message.ofL10n(Validation.IS_ALREADY_USED_MESSAGE, "Name")); - } - return Collections.emptySet(); + errors.check(isModifyingCurrentQgate || existingQgate == null, Validation.IS_ALREADY_USED_MESSAGE, "Name"); + } private void checkPermission(UserSession userSession) { diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/BulkChangeResult.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/BulkChangeResult.java index e44abb4a86a..8eadf2c012c 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/BulkChangeResult.java +++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/BulkChangeResult.java @@ -20,25 +20,19 @@ package org.sonar.server.qualityprofile; import com.google.common.collect.Lists; -import org.sonar.server.exceptions.Message; -import org.sonar.server.exceptions.Messages; +import org.sonar.server.exceptions.Errors; import java.util.Collection; import java.util.List; public class BulkChangeResult { - private final Messages messages = new Messages(); + private final Errors errors = new Errors(); private int succeeded = 0, failed = 0; private final List changes = Lists.newArrayList(); - BulkChangeResult addMessage(Message message) { - this.messages.add(message); - return this; - } - - public Messages getMessages() { - return messages; + public Errors getErrors() { + return errors; } public int countSucceeded() { diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileOperations.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileOperations.java index a9c4ebb17f3..52c1775beda 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileOperations.java +++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileOperations.java @@ -32,6 +32,7 @@ import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.user.UserSession; import javax.annotation.Nullable; + import java.util.List; import java.util.Map; @@ -47,7 +48,7 @@ public class QProfileOperations implements ServerComponent { private final QProfileLookup profileLookup; public QProfileOperations(MyBatis myBatis, QualityProfileDao dao, PropertiesDao propertiesDao, - QProfileRepositoryExporter exporter, PreviewCache dryRunCache, QProfileLookup profileLookup) { + QProfileRepositoryExporter exporter, PreviewCache dryRunCache, QProfileLookup profileLookup) { this.myBatis = myBatis; this.dao = dao; this.propertiesDao = propertiesDao; @@ -128,7 +129,7 @@ public class QProfileOperations implements ServerComponent { private void checkNotAlreadyExists(String name, String language, DbSession session) { if (dao.selectByNameAndLanguage(name, language, session) != null) { - throw BadRequestException.ofL10n("quality_profiles.profile_x_already_exists", name); + throw new BadRequestException("quality_profiles.profile_x_already_exists", name); } } diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRepositoryExporter.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRepositoryExporter.java index 5a098665cce..d3bdcf5d466 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRepositoryExporter.java +++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRepositoryExporter.java @@ -68,7 +68,7 @@ public class QProfileRepositoryExporter implements ServerComponent { } public QProfileRepositoryExporter(DatabaseSessionFactory sessionFactory, ActiveRuleDao activeRuleDao, - List importers, List exporters) { + List importers, List exporters) { this.sessionFactory = sessionFactory; this.activeRuleDao = activeRuleDao; this.importers = importers; @@ -89,7 +89,7 @@ public class QProfileRepositoryExporter implements ServerComponent { DatabaseSession session = sessionFactory.getSession(); RulesProfile rulesProfile = session.getSingleResult(RulesProfile.class, "id", profile.id()); if (rulesProfile == null) { - throw new NotFoundException("This profile does not exists."); + throw new NotFoundException("This profile does not exist"); } ProfileExporter exporter = getProfileExporter(pluginKey); Writer writer = new StringWriter(); @@ -114,16 +114,12 @@ public class QProfileRepositoryExporter implements ServerComponent { paramsByActiveRule.put(activeRuleDto.getId(), activeRuleParamDto); } } - //ruleRegistry.bulkIndexActiveRules(activeRuleDtos, paramsByActiveRule); + // TODO ruleRegistry.bulkIndexActiveRules(activeRuleDtos, paramsByActiveRule); } private void processValidationMessages(ValidationMessages messages, QProfileResult result) { if (!messages.getErrors().isEmpty()) { - List errors = newArrayList(); - for (String error : messages.getErrors()) { - errors.add(BadRequestException.Message.of(error)); - } - throw BadRequestException.of("Fail to import profile", errors); + throw new BadRequestException(messages); } result.addWarnings(messages.getWarnings()); result.addInfos(messages.getInfos()); @@ -154,7 +150,7 @@ public class QProfileRepositoryExporter implements ServerComponent { return importer; } } - throw BadRequestException.of("No such importer : " + importerKey); + throw new BadRequestException("No such importer : " + importerKey); } private ProfileExporter getProfileExporter(String exporterKey) { @@ -163,7 +159,7 @@ public class QProfileRepositoryExporter implements ServerComponent { return exporter; } } - throw BadRequestException.of("No such exporter : " + exporterKey); + throw new BadRequestException("No such exporter : " + exporterKey); } public List getProfileExportersForLanguage(String language) { diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileReset.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileReset.java index ac11fe27dc5..c664c5b395f 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileReset.java +++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileReset.java @@ -23,7 +23,6 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Sets; -import org.slf4j.LoggerFactory; import org.sonar.api.ServerComponent; import org.sonar.api.profiles.ProfileDefinition; import org.sonar.api.profiles.RulesProfile; @@ -44,8 +43,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import static com.google.common.collect.Lists.newArrayList; - public class QProfileReset implements ServerComponent { private final DbClient db; @@ -121,7 +118,7 @@ public class QProfileReset implements ServerComponent { result.addChanges(changes); } catch (BadRequestException e) { result.incrementFailed(); - //TODOresult.addMessage() + result.getErrors().add(e.errors()); } } @@ -155,12 +152,7 @@ public class QProfileReset implements ServerComponent { private void processValidationMessages(ValidationMessages messages) { if (!messages.getErrors().isEmpty()) { - List errors = newArrayList(); - for (String error : messages.getErrors()) { - errors.add(BadRequestException.Message.of(error)); - } - throw BadRequestException.of("Fail to restore profile", errors); + throw new BadRequestException(messages); } } } - diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java index 1e11d2b9296..cd688a37511 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java +++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java @@ -147,7 +147,7 @@ public class QProfiles implements ServerComponent { private void checkProfileNameParam(String name) { if (Strings.isNullOrEmpty(name)) { - throw BadRequestException.ofL10n("quality_profiles.please_type_profile_name"); + throw new BadRequestException("quality_profiles.please_type_profile_name"); } } diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BulkRuleActivationActions.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BulkRuleActivationActions.java index 06e5be6b991..1ef15238fe0 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BulkRuleActivationActions.java +++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BulkRuleActivationActions.java @@ -20,6 +20,7 @@ package org.sonar.server.qualityprofile.ws; import org.sonar.api.ServerComponent; +import org.sonar.api.i18n.I18n; import org.sonar.api.rule.Severity; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.RequestHandler; @@ -31,6 +32,7 @@ import org.sonar.server.qualityprofile.BulkChangeResult; import org.sonar.server.qualityprofile.QProfileService; import org.sonar.server.rule.RuleService; import org.sonar.server.rule.ws.SearchAction; +import org.sonar.server.user.UserSession; public class BulkRuleActivationActions implements ServerComponent { @@ -42,10 +44,12 @@ public class BulkRuleActivationActions implements ServerComponent { private final QProfileService profileService; private final RuleService ruleService; + private final I18n i18n; - public BulkRuleActivationActions(QProfileService profileService, RuleService ruleService) { + public BulkRuleActivationActions(QProfileService profileService, RuleService ruleService, I18n i18n) { this.profileService = profileService; this.ruleService = ruleService; + this.i18n = i18n; } void define(WebService.NewController controller) { @@ -117,7 +121,7 @@ public class BulkRuleActivationActions implements ServerComponent { JsonWriter json = response.newJsonWriter().beginObject(); json.prop("succeeded", result.countSucceeded()); json.prop("failed", result.countFailed()); - result.getMessages().writeJson(json); + result.getErrors().writeJsonAsWarnings(json, i18n, UserSession.get().locale()); json.endObject().close(); } diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileRestoreBuiltInAction.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileRestoreBuiltInAction.java index b3e849494d2..1d05d7a645e 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileRestoreBuiltInAction.java +++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileRestoreBuiltInAction.java @@ -24,8 +24,6 @@ import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.RequestHandler; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; -import org.sonar.api.utils.text.JsonWriter; -import org.sonar.server.qualityprofile.QProfileResult; import org.sonar.server.qualityprofile.QProfileService; public class QProfileRestoreBuiltInAction implements RequestHandler { @@ -53,31 +51,7 @@ public class QProfileRestoreBuiltInAction implements RequestHandler { public void handle(Request request, Response response) { String language = request.mandatoryParam("language"); service.restoreBuiltInProfilesForLanguage(language); - - // TODO - QProfileResult result = new QProfileResult(); - - if (!result.infos().isEmpty() || !result.warnings().isEmpty()) { - JsonWriter json = response.newJsonWriter(); - json.beginObject(); - if (!result.infos().isEmpty()) { - json.name("infos").beginArray(); - for (String info : result.infos()) { - json.value(info); - } - json.endArray(); - } - if (!result.warnings().isEmpty()) { - json.name("warnings").beginArray(); - for (String warning : result.warnings()) { - json.value(warning); - } - json.endArray(); - } - json.endObject().close(); - } else { - response.noContent(); - } + response.noContent(); } } diff --git a/sonar-server/src/main/java/org/sonar/server/rule/RuleOperations.java b/sonar-server/src/main/java/org/sonar/server/rule/RuleOperations.java index 72ef0af1d8e..d346638ff21 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/RuleOperations.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/RuleOperations.java @@ -87,7 +87,7 @@ public class RuleOperations implements ServerComponent { session.commit(); } } catch (IllegalArgumentException e) { - throw BadRequestException.of(e.getMessage()); + throw new BadRequestException(e.getMessage()); } finally { MyBatis.closeQuietly(session); } diff --git a/sonar-server/src/main/java/org/sonar/server/util/BooleanTypeValidation.java b/sonar-server/src/main/java/org/sonar/server/util/BooleanTypeValidation.java index 39169be427a..53424f2778c 100644 --- a/sonar-server/src/main/java/org/sonar/server/util/BooleanTypeValidation.java +++ b/sonar-server/src/main/java/org/sonar/server/util/BooleanTypeValidation.java @@ -36,7 +36,7 @@ public class BooleanTypeValidation implements TypeValidation { @Override public void validate(String value, List options) { if (!StringUtils.equalsIgnoreCase(value, "true") && !StringUtils.equalsIgnoreCase(value, "false")) { - throw BadRequestException.ofL10n("errors.type.notBoolean", value); + throw new BadRequestException("errors.type.notBoolean", value); } } diff --git a/sonar-server/src/main/java/org/sonar/server/util/FloatTypeValidation.java b/sonar-server/src/main/java/org/sonar/server/util/FloatTypeValidation.java index e1ea779e66f..c068601bb83 100644 --- a/sonar-server/src/main/java/org/sonar/server/util/FloatTypeValidation.java +++ b/sonar-server/src/main/java/org/sonar/server/util/FloatTypeValidation.java @@ -23,6 +23,7 @@ package org.sonar.server.util; import org.sonar.api.PropertyType; import org.sonar.server.exceptions.BadRequestException; +import javax.annotation.Nullable; import java.util.List; public class FloatTypeValidation implements TypeValidation { @@ -33,11 +34,11 @@ public class FloatTypeValidation implements TypeValidation { } @Override - public void validate(String value, List options) { + public void validate(String value, @Nullable List options) { try { Double.parseDouble(value); } catch (NumberFormatException e) { - throw BadRequestException.ofL10n("errors.type.notFloat", value); + throw new BadRequestException("errors.type.notFloat", value); } } diff --git a/sonar-server/src/main/java/org/sonar/server/util/IntegerTypeValidation.java b/sonar-server/src/main/java/org/sonar/server/util/IntegerTypeValidation.java index 68d93a3ffb7..31f87e6a0de 100644 --- a/sonar-server/src/main/java/org/sonar/server/util/IntegerTypeValidation.java +++ b/sonar-server/src/main/java/org/sonar/server/util/IntegerTypeValidation.java @@ -36,7 +36,7 @@ public class IntegerTypeValidation implements TypeValidation { @Override public void validate(String value, List options) { if (!NumberUtils.isDigits(value)) { - throw BadRequestException.ofL10n("errors.type.notInteger", value); + throw new BadRequestException("errors.type.notInteger", value); } } diff --git a/sonar-server/src/main/java/org/sonar/server/util/StringListTypeValidation.java b/sonar-server/src/main/java/org/sonar/server/util/StringListTypeValidation.java index e435ead4a27..762f21effba 100644 --- a/sonar-server/src/main/java/org/sonar/server/util/StringListTypeValidation.java +++ b/sonar-server/src/main/java/org/sonar/server/util/StringListTypeValidation.java @@ -37,7 +37,7 @@ public class StringListTypeValidation implements TypeValidation { public void validate(String value, List options) { if (!options.contains(value)) { String optionsAsString = StringUtils.join(options, ", "); - throw BadRequestException.ofL10n("errors.type.notInOptions", value, optionsAsString); + throw new BadRequestException("errors.type.notInOptions", value, optionsAsString); } } diff --git a/sonar-server/src/main/java/org/sonar/server/util/TypeValidation.java b/sonar-server/src/main/java/org/sonar/server/util/TypeValidation.java index 3fa6c9916f3..e754199be38 100644 --- a/sonar-server/src/main/java/org/sonar/server/util/TypeValidation.java +++ b/sonar-server/src/main/java/org/sonar/server/util/TypeValidation.java @@ -22,11 +22,12 @@ package org.sonar.server.util; import org.sonar.api.ServerComponent; +import javax.annotation.Nullable; import java.util.List; public interface TypeValidation extends ServerComponent { String key(); - void validate(String value, List options); + void validate(String value, @Nullable List options); } diff --git a/sonar-server/src/main/java/org/sonar/server/util/TypeValidations.java b/sonar-server/src/main/java/org/sonar/server/util/TypeValidations.java index 5487d65cc76..5f160211aeb 100644 --- a/sonar-server/src/main/java/org/sonar/server/util/TypeValidations.java +++ b/sonar-server/src/main/java/org/sonar/server/util/TypeValidations.java @@ -25,6 +25,7 @@ import com.google.common.collect.Iterables; import org.sonar.api.ServerComponent; import org.sonar.server.exceptions.BadRequestException; +import javax.annotation.Nullable; import java.util.List; public class TypeValidations implements ServerComponent { @@ -42,7 +43,7 @@ public class TypeValidations implements ServerComponent { } } - public void validate(String value, String type, List options) { + public void validate(String value, String type, @Nullable List options) { TypeValidation typeValidation = findByKey(type); typeValidation.validate(value, options); } diff --git a/sonar-server/src/main/java/org/sonar/server/util/Validation.java b/sonar-server/src/main/java/org/sonar/server/util/Validation.java index d9fdd396afd..6d9f1f471d4 100644 --- a/sonar-server/src/main/java/org/sonar/server/util/Validation.java +++ b/sonar-server/src/main/java/org/sonar/server/util/Validation.java @@ -34,20 +34,14 @@ public class Validation { public static void checkMandatoryParameter(String value, String paramName) { if (Strings.isNullOrEmpty(value)) { - throw BadRequestException.ofL10n(Validation.CANT_BE_EMPTY_MESSAGE, paramName); - } - } - - public static void checkMandatoryParameter(Object value, String paramName) { - if (value == null) { - throw BadRequestException.ofL10n(Validation.CANT_BE_EMPTY_MESSAGE, paramName); + throw new BadRequestException(Validation.CANT_BE_EMPTY_MESSAGE, paramName); } } public static void checkMandatorySizeParameter(String value, String paramName, Integer size) { checkMandatoryParameter(value, paramName); if (!Strings.isNullOrEmpty(value) && value.length() > size) { - throw BadRequestException.ofL10n(Validation.IS_TOO_LONG_MESSAGE, paramName, size); + throw new BadRequestException(Validation.IS_TOO_LONG_MESSAGE, paramName, size); } } diff --git a/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java b/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java index f308e185053..498af7da455 100644 --- a/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java +++ b/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java @@ -19,7 +19,6 @@ */ package org.sonar.server.ws; -import org.elasticsearch.common.collect.Lists; import org.picocontainer.Startable; import org.slf4j.LoggerFactory; import org.sonar.api.ServerComponent; @@ -29,17 +28,16 @@ import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.internal.ValidatingRequest; import org.sonar.api.utils.text.JsonWriter; import org.sonar.server.exceptions.BadRequestException; -import org.sonar.server.exceptions.BadRequestException.Message; +import org.sonar.server.exceptions.Errors; +import org.sonar.server.exceptions.Message; import org.sonar.server.exceptions.ServerException; import org.sonar.server.plugins.MimeTypes; +import org.sonar.server.user.UserSession; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; import javax.servlet.http.HttpServletResponse; + import java.io.OutputStreamWriter; -import java.util.Collection; import java.util.List; -import java.util.Locale; /** * @since 4.2 @@ -77,7 +75,7 @@ public class WebServiceEngine implements ServerComponent, Startable { } public void execute(ValidatingRequest request, ServletResponse response, - String controllerPath, String actionKey) { + String controllerPath, String actionKey) { try { WebService.Action action = getAction(controllerPath, actionKey); request.setAction(action); @@ -86,15 +84,15 @@ public class WebServiceEngine implements ServerComponent, Startable { } catch (IllegalArgumentException e) { // TODO replace by BadRequestException in Request#mandatoryParam() - sendError(400, e.getMessage(), response); + sendErrors(response, 400, new Errors().add(Message.of(e.getMessage()))); } catch (BadRequestException e) { - sendError(e, response); + sendErrors(response, 400, e.errors()); } catch (ServerException e) { - sendError(e.httpCode(), message(e.getMessage(), e.l10nKey(), e.l10nParams()), response); + sendErrors(response, e.httpCode(), new Errors().add(Message.of(e.getMessage()))); } catch (Exception e) { // TODO implement Request.toString() LoggerFactory.getLogger(getClass()).error("Fail to process request " + request, e); - sendError(500, e.getMessage(), response); + sendErrors(response, 500, new Errors().add(Message.of(e.getMessage()))); } } @@ -117,32 +115,7 @@ public class WebServiceEngine implements ServerComponent, Startable { } } - private void sendError(BadRequestException e, ServletResponse response) { - Collection messages = Lists.newArrayList(); - String exceptionMessage = message(e.getMessage(), e.l10nKey(), e.l10nParams()); - if (exceptionMessage != null) { - messages.add(exceptionMessage); - } - for (Message message : e.errors()) { - messages.add(message(message.text(), message.l10nKey(), message.l10nParams())); - } - sendErrors(response, e.httpCode(), messages.toArray(new String[messages.size()])); - } - - @CheckForNull - private String message(@Nullable String message, @Nullable String l10nKey, Object... l10nParams) { - if (l10nKey != null) { - return i18n.message(Locale.getDefault(), l10nKey, message, l10nParams); - } else { - return message; - } - } - - private void sendError(int status, @Nullable String message, ServletResponse response) { - sendErrors(response, status, message); - } - - private void sendErrors(ServletResponse response, int status, String... errors) { + private void sendErrors(ServletResponse response, int status, Errors errors) { ServletResponse.ServletStream stream = response.stream(); stream.reset(); stream.setStatus(status); @@ -151,11 +124,7 @@ public class WebServiceEngine implements ServerComponent, Startable { try { json.beginObject(); - json.name("errors").beginArray(); - for (String message : errors) { - json.beginObject().prop("msg", message).endObject(); - } - json.endArray(); + errors.writeJson(json, i18n, UserSession.get().locale()); json.endObject(); } finally { // TODO if close() fails, the runtime exception should not hide the diff --git a/sonar-server/src/test/java/org/sonar/server/debt/DebtModelOperationsTest.java b/sonar-server/src/test/java/org/sonar/server/debt/DebtModelOperationsTest.java index f141537f4e6..3f2d1c6e314 100644 --- a/sonar-server/src/test/java/org/sonar/server/debt/DebtModelOperationsTest.java +++ b/sonar-server/src/test/java/org/sonar/server/debt/DebtModelOperationsTest.java @@ -151,8 +151,8 @@ public class DebtModelOperationsTest { try { service.create("Compilation", 1); fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("A sub characteristic can not have a sub characteristic as parent."); + } catch (BadRequestException e) { + assertThat(e.firstError().getKey()).isEqualTo("A sub characteristic can not have a sub characteristic as parent."); } } @@ -177,8 +177,8 @@ public class DebtModelOperationsTest { service.create("Compilation", 1); fail(); } catch (BadRequestException e) { - assertThat(e.l10nKey()).isEqualTo("errors.is_already_used"); - assertThat(e.l10nParams()[0]).isEqualTo("Compilation"); + assertThat(e.firstError().getKey()).isEqualTo("errors.is_already_used"); + assertThat(e.firstError().getParams()[0]).isEqualTo("Compilation"); } } @@ -327,10 +327,9 @@ public class DebtModelOperationsTest { try { service.moveDown(10); fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("Sub characteristics can not be moved."); + } catch (BadRequestException e) { + assertThat(e.firstError().getKey()).isEqualTo("Sub characteristics can not be moved."); } - verify(dao, never()).update(any(CharacteristicDto.class), eq(session)); } diff --git a/sonar-server/src/test/java/org/sonar/server/exceptions/BadRequestExceptionTest.java b/sonar-server/src/test/java/org/sonar/server/exceptions/BadRequestExceptionTest.java index 56cce142570..d9247211061 100644 --- a/sonar-server/src/test/java/org/sonar/server/exceptions/BadRequestExceptionTest.java +++ b/sonar-server/src/test/java/org/sonar/server/exceptions/BadRequestExceptionTest.java @@ -22,91 +22,14 @@ package org.sonar.server.exceptions; import org.junit.Test; -import static com.google.common.collect.Lists.newArrayList; import static org.fest.assertions.Assertions.assertThat; public class BadRequestExceptionTest { @Test public void text_error() throws Exception { - BadRequestException exception = BadRequestException.of("error"); + BadRequestException exception = new BadRequestException("error"); assertThat(exception.getMessage()).isEqualTo("error"); } - @Test - public void text_error_with_list_of_errors() throws Exception { - BadRequestException exception = BadRequestException.of("error", newArrayList(BadRequestException.Message.of("new error"))); - - assertThat(exception.errors()).hasSize(1); - assertThat(exception.errors().get(0).text()).isEqualTo("new error"); - } - - @Test - public void text_error_with_list_of_l18n_errors() throws Exception { - BadRequestException exception = BadRequestException.of("error", newArrayList(BadRequestException.Message.ofL10n("issue.error.123", "10"))); - - assertThat(exception.errors()).hasSize(1); - assertThat(exception.errors().get(0).l10nKey()).isEqualTo("issue.error.123"); - assertThat(exception.errors().get(0).l10nParams()).containsOnly("10"); - } - - @Test - public void list_of_errors() throws Exception { - BadRequestException exception = BadRequestException.of(newArrayList(BadRequestException.Message.of("new error"))); - - assertThat(exception.errors()).hasSize(1); - assertThat(exception.errors().get(0).text()).isEqualTo("new error"); - } - - @Test - public void l10n_errors() throws Exception { - BadRequestException exception = BadRequestException.ofL10n("issue.error.123", "10"); - assertThat(exception.getMessage()).isNull(); - assertThat(exception.l10nKey()).isEqualTo("issue.error.123"); - assertThat(exception.l10nParams()).containsOnly("10"); - } - - @Test - public void l10n_errors_with_list_of_errors() throws Exception { - BadRequestException exception = BadRequestException.ofL10n(newArrayList(BadRequestException.Message.of("new error")), "issue.error.123", "10"); - assertThat(exception.getMessage()).isNull(); - assertThat(exception.l10nKey()).isEqualTo("issue.error.123"); - assertThat(exception.l10nParams()).containsOnly("10"); - assertThat(exception.errors()).hasSize(1); - assertThat(exception.errors().get(0).text()).isEqualTo("new error"); - } - - @Test - public void test_equals_and_hashcode() throws Exception { - BadRequestException.Message msg = BadRequestException.Message.of("error1"); - BadRequestException.Message sameMsg = BadRequestException.Message.of("error1"); - BadRequestException.Message msg2 = BadRequestException.Message.of("error2"); - - assertThat(msg.toString()).contains("error1"); - assertThat(msg).isEqualTo(sameMsg); - assertThat(msg).isEqualTo(sameMsg); - assertThat(msg.hashCode()).isEqualTo(msg.hashCode()); - assertThat(msg.hashCode()).isEqualTo(sameMsg.hashCode()); - - assertThat(msg).isNotEqualTo(msg2); - } - - @Test - public void test_equals_and_hashcode_on_l10n() throws Exception { - BadRequestException.Message msg = BadRequestException.Message.ofL10n("error.123", "10"); - BadRequestException.Message sameMsg = BadRequestException.Message.ofL10n("error.123", "10"); - BadRequestException.Message msg2 = BadRequestException.Message.ofL10n("error.123", "200"); - BadRequestException.Message msg3 = BadRequestException.Message.ofL10n("error.50"); - - assertThat(msg.toString()).contains("error.123").contains("10"); - assertThat(msg).isEqualTo(msg); - assertThat(msg).isEqualTo(sameMsg); - assertThat(msg.hashCode()).isEqualTo(msg.hashCode()); - assertThat(msg.hashCode()).isEqualTo(sameMsg.hashCode()); - - assertThat(msg).isNotEqualTo(msg2); - assertThat(msg).isNotEqualTo(msg3); - assertThat(msg).isNotEqualTo("issue.error.123"); - } - } diff --git a/sonar-server/src/test/java/org/sonar/server/exceptions/ServerExceptionTest.java b/sonar-server/src/test/java/org/sonar/server/exceptions/ServerExceptionTest.java index 75f193db777..cb780e3383d 100644 --- a/sonar-server/src/test/java/org/sonar/server/exceptions/ServerExceptionTest.java +++ b/sonar-server/src/test/java/org/sonar/server/exceptions/ServerExceptionTest.java @@ -27,31 +27,15 @@ import static org.fest.assertions.Assertions.assertThat; public class ServerExceptionTest { @Test - public void should_create_exception_with_status(){ + public void should_create_exception_with_status() { ServerException exception = new ServerException(400); assertThat(exception.httpCode()).isEqualTo(400); } @Test - public void should_create_exception_with_status_and_message(){ + public void should_create_exception_with_status_and_message() { ServerException exception = new ServerException(404, "Not found"); assertThat(exception.httpCode()).isEqualTo(404); assertThat(exception.getMessage()).isEqualTo("Not found"); } - - @Test - public void should_create_exception_with_status_and_l10n_message_with_param(){ - ServerException exception = new ServerException(404, null, "key", new String[]{"value"}); - assertThat(exception.httpCode()).isEqualTo(404); - assertThat(exception.l10nKey()).isEqualTo("key"); - assertThat(exception.l10nParams()).containsOnly("value"); - } - - @Test - public void should_create_exception_with_status_and_l10n_message_without_param(){ - ServerException exception = new ServerException(404, null, "key", null); - assertThat(exception.httpCode()).isEqualTo(404); - assertThat(exception.l10nKey()).isEqualTo("key"); - assertThat(exception.l10nParams()).isEmpty(); - } } diff --git a/sonar-server/src/test/java/org/sonar/server/exceptions/VerificationsTest.java b/sonar-server/src/test/java/org/sonar/server/exceptions/VerificationsTest.java new file mode 100644 index 00000000000..57e2df0d00e --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/exceptions/VerificationsTest.java @@ -0,0 +1,42 @@ +/* + * 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.exceptions; + +import org.junit.Test; + +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.Fail.fail; + +public class VerificationsTest { + + @Test + public void check() throws Exception { + // no exception + Verifications.check(true, "my.l10n.key", "foo", "bar"); + + try { + Verifications.check(false, "my.l10n.key", "foo", "bar"); + fail(); + } catch (BadRequestException e) { + assertThat(e.firstError().getKey()).isEqualTo("my.l10n.key"); + assertThat(e.firstError().getParams()).containsOnly("foo", "bar"); + } + } +} diff --git a/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java b/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java index f637730d0ec..508890be52b 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java @@ -41,6 +41,7 @@ import org.sonar.core.resource.ResourceDao; import org.sonar.core.resource.ResourceDto; import org.sonar.core.resource.ResourceQuery; import org.sonar.server.exceptions.BadRequestException; +import org.sonar.server.exceptions.Message; import org.sonar.server.issue.actionplan.ActionPlanService; import org.sonar.server.issue.filter.IssueFilterService; import org.sonar.server.user.UserSession; @@ -653,8 +654,9 @@ public class InternalRubyIssueServiceTest { private void checkBadRequestException(Exception e, String key, Object... params) { BadRequestException exception = (BadRequestException) e; - assertThat(exception.l10nKey()).isEqualTo(key); - assertThat(exception.l10nParams()).containsOnly(params); + Message msg = exception.errors().messages().get(0); + assertThat(msg.getKey()).isEqualTo(key); + assertThat(msg.getParams()).containsOnly(params); } private String createLongString(int size) { diff --git a/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeQueryTest.java b/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeQueryTest.java index 508c9584915..990384443e6 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeQueryTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeQueryTest.java @@ -155,8 +155,8 @@ public class IssueBulkChangeQueryTest { private void checkBadRequestException(Exception e, String key, Object... params) { BadRequestException exception = (BadRequestException) e; - assertThat(exception.l10nKey()).isEqualTo(key); - assertThat(exception.l10nParams()).containsOnly(params); + assertThat(exception.firstError().getKey()).isEqualTo(key); + assertThat(exception.firstError().getParams()).containsOnly(params); } } diff --git a/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QGatesWsTest.java b/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QGatesWsTest.java index 78adc0d479e..ad089547b51 100644 --- a/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QGatesWsTest.java +++ b/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QGatesWsTest.java @@ -208,7 +208,7 @@ public class QGatesWsTest { @Test(expected = BadRequestException.class) public void create_with_duplicate_name() throws Exception { String name = "New QG"; - when(qGates.create(name)).thenThrow(BadRequestException.of("Name is already used")); + when(qGates.create(name)).thenThrow(new BadRequestException("Name is already used")); tester.newGetRequest("api/qualitygates", "create").setParam("name", name).execute(); } diff --git a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRepositoryExporterTest.java b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRepositoryExporterTest.java index f780b3e4634..50584694df2 100644 --- a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRepositoryExporterTest.java +++ b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRepositoryExporterTest.java @@ -20,7 +20,6 @@ package org.sonar.server.qualityprofile; -import com.google.common.collect.Multimap; import org.apache.ibatis.session.SqlSession; import org.junit.Before; import org.junit.Test; @@ -54,9 +53,12 @@ import static com.google.common.collect.Lists.newArrayList; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Fail.fail; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyListOf; import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class QProfileRepositoryExporterTest { @@ -256,7 +258,7 @@ public class QProfileRepositoryExporterTest { operations.exportToXml(new QProfile().setId(1), "pmd"); fail(); } catch (Exception e) { - assertThat(e).isInstanceOf(NotFoundException.class).hasMessage("This profile does not exists."); + assertThat(e).isInstanceOf(NotFoundException.class).hasMessage("This profile does not exist"); } verify(exporter, never()).exportProfile(any(RulesProfile.class), any(Writer.class)); diff --git a/sonar-server/src/test/java/org/sonar/server/qualityprofile/RuleActivatorMediumTest.java b/sonar-server/src/test/java/org/sonar/server/qualityprofile/RuleActivatorMediumTest.java index 0fcdf7c3930..31c2ecb28da 100644 --- a/sonar-server/src/test/java/org/sonar/server/qualityprofile/RuleActivatorMediumTest.java +++ b/sonar-server/src/test/java/org/sonar/server/qualityprofile/RuleActivatorMediumTest.java @@ -34,6 +34,7 @@ import org.sonar.core.rule.RuleDto; import org.sonar.core.rule.RuleParamDto; import org.sonar.server.db.DbClient; import org.sonar.server.exceptions.BadRequestException; +import org.sonar.server.exceptions.Message; import org.sonar.server.qualityprofile.index.ActiveRuleIndex; import org.sonar.server.rule.RuleTesting; import org.sonar.server.rule.index.RuleIndex; @@ -320,7 +321,8 @@ public class RuleActivatorMediumTest { ruleActivator.activate(activation); fail(); } catch (BadRequestException e) { - assertThat(e.l10nKey()).isEqualTo("errors.type.notInteger"); + Message msg = e.errors().messages().get(0); + assertThat(msg.getKey()).isEqualTo("errors.type.notInteger"); verifyZeroActiveRules(XOO_PROFILE_KEY); } } diff --git a/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRestoreBuiltInActionTest.java b/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRestoreBuiltInActionTest.java index b6756eddd4a..cf660c36572 100644 --- a/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRestoreBuiltInActionTest.java +++ b/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRestoreBuiltInActionTest.java @@ -25,6 +25,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import org.sonar.api.i18n.I18n; import org.sonar.server.qualityprofile.QProfileService; import org.sonar.server.rule.RuleService; import org.sonar.server.ws.WsTester; @@ -37,6 +38,9 @@ public class QProfileRestoreBuiltInActionTest { @Mock QProfileService profileService; + @Mock + I18n i18n; + WsTester tester; @Before @@ -46,7 +50,7 @@ public class QProfileRestoreBuiltInActionTest { tester = new WsTester(new QProfilesWs( new QProfileRestoreBuiltInAction(this.profileService), new RuleActivationActions(profileService), - new BulkRuleActivationActions(profileService, ruleService))); + new BulkRuleActivationActions(profileService, ruleService, i18n))); } @Test @@ -56,29 +60,4 @@ public class QProfileRestoreBuiltInActionTest { WsTester.TestRequest request = tester.newPostRequest("api/qualityprofiles", "restore_built_in").setParam("language", "java"); request.execute().assertNoContent(); } - - // TODO -// @Test -// public void show_infos() throws Exception { -// when(profileService.recreateBuiltInProfilesByLanguage("java")).thenReturn(new QProfileResult().addInfos(newArrayList("Some info"))); -// -// WsTester.TestRequest request = tester.newPostRequest("api/qualityprofiles", "recreate_built_in").setParam("language", "java"); -// request.execute().assertJson(getClass(), "show_infos.json"); -// } -// -// @Test -// public void show_warnings() throws Exception { -// when(profileService.recreateBuiltInProfilesByLanguage("java")).thenReturn(new QProfileResult().addWarnings(newArrayList("Some warning"))); -// -// WsTester.TestRequest request = tester.newPostRequest("api/qualityprofiles", "recreate_built_in").setParam("language", "java"); -// request.execute().assertJson(getClass(), "show_warnings.json"); -// } -// -// @Test -// public void show_infos_and_warnings() throws Exception { -// when(profileService.recreateBuiltInProfilesByLanguage("java")).thenReturn(new QProfileResult().addInfos(newArrayList("Some info")).addWarnings(newArrayList("Some warning"))); -// -// WsTester.TestRequest request = tester.newPostRequest("api/qualityprofiles", "recreate_built_in").setParam("language", "java"); -// request.execute().assertJson(getClass(), "show_infos_and_warnings.json"); -// } } diff --git a/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java b/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java index a26a4f92cd8..e54509a3de7 100644 --- a/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java +++ b/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java @@ -22,6 +22,7 @@ package org.sonar.server.qualityprofile.ws; import org.junit.Before; import org.junit.Test; +import org.sonar.api.i18n.I18n; import org.sonar.api.server.ws.WebService; import org.sonar.server.qualityprofile.QProfileService; import org.sonar.server.rule.RuleService; @@ -38,10 +39,11 @@ public class QProfilesWsTest { public void setUp() { QProfileService profileService = mock(QProfileService.class); RuleService ruleService = mock(RuleService.class); + I18n i18n = mock(I18n.class); controller = new WsTester(new QProfilesWs(new QProfileRestoreBuiltInAction( mock(QProfileService.class)), new RuleActivationActions(profileService), - new BulkRuleActivationActions(profileService, ruleService) + new BulkRuleActivationActions(profileService, ruleService, i18n) )).controller(QProfilesWs.API_ENDPOINT); } diff --git a/sonar-server/src/test/java/org/sonar/server/util/BooleanTypeValidationTest.java b/sonar-server/src/test/java/org/sonar/server/util/BooleanTypeValidationTest.java index 8c07873d21d..031a1e98468 100644 --- a/sonar-server/src/test/java/org/sonar/server/util/BooleanTypeValidationTest.java +++ b/sonar-server/src/test/java/org/sonar/server/util/BooleanTypeValidationTest.java @@ -57,7 +57,7 @@ public class BooleanTypeValidationTest { } catch (Exception e) { assertThat(e).isInstanceOf(BadRequestException.class); BadRequestException badRequestException = (BadRequestException) e; - assertThat(badRequestException.l10nParams()[0]).isEqualTo("abc"); + assertThat(badRequestException.firstError().getParams()[0]).isEqualTo("abc"); } } diff --git a/sonar-server/src/test/java/org/sonar/server/util/FloatTypeValidationTest.java b/sonar-server/src/test/java/org/sonar/server/util/FloatTypeValidationTest.java index a1a11664b0f..7c7b170475f 100644 --- a/sonar-server/src/test/java/org/sonar/server/util/FloatTypeValidationTest.java +++ b/sonar-server/src/test/java/org/sonar/server/util/FloatTypeValidationTest.java @@ -55,7 +55,7 @@ public class FloatTypeValidationTest { } catch (Exception e) { assertThat(e).isInstanceOf(BadRequestException.class); BadRequestException badRequestException = (BadRequestException) e; - assertThat(badRequestException.l10nParams()[0]).isEqualTo("abc"); + assertThat(badRequestException.firstError().getParams()[0]).isEqualTo("abc"); } } diff --git a/sonar-server/src/test/java/org/sonar/server/util/IntegerTypeValidationTest.java b/sonar-server/src/test/java/org/sonar/server/util/IntegerTypeValidationTest.java index 9db9ed73e23..43620979026 100644 --- a/sonar-server/src/test/java/org/sonar/server/util/IntegerTypeValidationTest.java +++ b/sonar-server/src/test/java/org/sonar/server/util/IntegerTypeValidationTest.java @@ -54,7 +54,7 @@ public class IntegerTypeValidationTest { } catch (Exception e) { assertThat(e).isInstanceOf(BadRequestException.class); BadRequestException badRequestException = (BadRequestException) e; - assertThat(badRequestException.l10nParams()[0]).isEqualTo("abc"); + assertThat(badRequestException.firstError().getParams()[0]).isEqualTo("abc"); } } diff --git a/sonar-server/src/test/java/org/sonar/server/util/StringListTypeValidationTest.java b/sonar-server/src/test/java/org/sonar/server/util/StringListTypeValidationTest.java index 0c50e23d9b9..750d91ef7f1 100644 --- a/sonar-server/src/test/java/org/sonar/server/util/StringListTypeValidationTest.java +++ b/sonar-server/src/test/java/org/sonar/server/util/StringListTypeValidationTest.java @@ -55,8 +55,8 @@ public class StringListTypeValidationTest { } catch (Exception e) { assertThat(e).isInstanceOf(BadRequestException.class); BadRequestException badRequestException = (BadRequestException) e; - assertThat(badRequestException.l10nParams()[0]).isEqualTo("abc"); - assertThat(badRequestException.l10nParams()[1]).isEqualTo("a, b, c"); + assertThat(badRequestException.firstError().getParams()[0]).isEqualTo("abc"); + assertThat(badRequestException.firstError().getParams()[1]).isEqualTo("a, b, c"); } } diff --git a/sonar-server/src/test/java/org/sonar/server/util/TypeValidationsTest.java b/sonar-server/src/test/java/org/sonar/server/util/TypeValidationsTest.java index 604b5540033..fc2331d5f86 100644 --- a/sonar-server/src/test/java/org/sonar/server/util/TypeValidationsTest.java +++ b/sonar-server/src/test/java/org/sonar/server/util/TypeValidationsTest.java @@ -64,7 +64,7 @@ public class TypeValidationsTest { } catch (Exception e) { assertThat(e).isInstanceOf(BadRequestException.class); BadRequestException badRequestException = (BadRequestException) e; - assertThat(badRequestException.getMessage()).isEqualTo("Type 'Unknown' is not valid."); + assertThat(badRequestException.firstError().getKey()).isEqualTo("Type 'Unknown' is not valid."); } } diff --git a/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java b/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java index 6bf8690856d..738f763865c 100644 --- a/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java +++ b/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java @@ -19,12 +19,13 @@ */ package org.sonar.server.ws; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.commons.io.IOUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.sonar.api.i18n.I18n; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.RequestHandler; @@ -32,17 +33,19 @@ import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.internal.ValidatingRequest; import org.sonar.server.exceptions.BadRequestException; -import org.sonar.server.exceptions.BadRequestException.Message; -import org.sonar.server.exceptions.ServerException; +import org.sonar.server.exceptions.Errors; +import org.sonar.server.exceptions.Message; import org.sonar.server.plugins.MimeTypes; import javax.annotation.Nullable; + import java.io.IOException; -import java.util.List; import java.util.Locale; import java.util.Map; import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; @@ -83,7 +86,7 @@ public class WebServiceEngineTest { } I18n i18n = mock(I18n.class); - WebServiceEngine engine = new WebServiceEngine(new WebService[]{new SystemWebService()}, i18n); + WebServiceEngine engine = new WebServiceEngine(new WebService[] {new SystemWebService()}, i18n); @Before public void start() { @@ -230,13 +233,13 @@ public class WebServiceEngineTest { public void bad_request_with_i18n_message() throws Exception { ValidatingRequest request = new SimpleRequest("GET").setParam("count", "3"); ServletResponse response = new ServletResponse(); - when(i18n.message(eq(Locale.getDefault()), eq("bad.request.reason"), anyString(), eq(0))).thenReturn("Bad request reason #0"); + when(i18n.message(Locale.ENGLISH, "bad.request.reason", "bad.request.reason", 0)).thenReturn("reason #0"); engine.execute(request, response, "api/system", "fail_with_i18n_message"); - assertThat(response.stream().outputAsString()).isEqualTo("{\"errors\":[" - + "{\"msg\":\"Bad request reason #0\"}" - + "]}"); + assertThat(response.stream().outputAsString()).isEqualTo( + "{\"errors\":[{\"msg\":\"reason #0\"}]}" + ); assertThat(response.stream().httpStatus()).isEqualTo(400); assertThat(response.stream().mediaType()).isEqualTo(MimeTypes.JSON); } @@ -261,34 +264,20 @@ public class WebServiceEngineTest { public void bad_request_with_multiple_i18n_messages() throws Exception { ValidatingRequest request = new SimpleRequest("GET").setParam("count", "3"); ServletResponse response = new ServletResponse(); - when(i18n.message(Locale.getDefault(), "bad.request.reason", null, 0)).thenReturn("Bad request reason #0"); - when(i18n.message(Locale.getDefault(), "bad.request.reason", null, 1)).thenReturn("Bad request reason #1"); - when(i18n.message(Locale.getDefault(), "bad.request.reason", null, 2)).thenReturn("Bad request reason #2"); + when(i18n.message(Locale.ENGLISH, "bad.request.reason", "bad.request.reason", 0)).thenReturn("reason #0"); + when(i18n.message(Locale.ENGLISH, "bad.request.reason", "bad.request.reason", 1)).thenReturn("reason #1"); + when(i18n.message(Locale.ENGLISH, "bad.request.reason", "bad.request.reason", 2)).thenReturn("reason #2"); engine.execute(request, response, "api/system", "fail_with_multiple_i18n_messages"); - assertThat(response.stream().outputAsString()).isEqualTo("{\"errors\":[" - + "{\"msg\":\"Bad request reason #0\"}," - + "{\"msg\":\"Bad request reason #1\"}," - + "{\"msg\":\"Bad request reason #2\"}" - + "]}"); + assertThat(response.stream().outputAsString()).isEqualTo("{\"errors\":[" + + "{\"msg\":\"reason #0\"}," + + "{\"msg\":\"reason #1\"}," + + "{\"msg\":\"reason #2\"}]}"); assertThat(response.stream().httpStatus()).isEqualTo(400); assertThat(response.stream().mediaType()).isEqualTo(MimeTypes.JSON); } - @Test - public void server_exception_with_i18n_message() throws Exception { - ValidatingRequest request = new SimpleRequest("GET"); - ServletResponse response = new ServletResponse(); - when(i18n.message(eq(Locale.getDefault()), eq("not.found"), anyString())).thenReturn("Element is not found"); - - engine.execute(request, response, "api/system", "server_exception_with_i18n_message"); - - assertThat(response.stream().outputAsString()).isEqualTo("{\"errors\":[{\"msg\":\"Element is not found\"}]}"); - assertThat(response.stream().httpStatus()).isEqualTo(404); - assertThat(response.stream().mediaType()).isEqualTo(MimeTypes.JSON); - } - static class SystemWebService implements WebService { @Override public void define(Context context) { @@ -327,7 +316,7 @@ public class WebServiceEngineTest { .setHandler(new RequestHandler() { @Override public void handle(Request request, Response response) { - throw BadRequestException.ofL10n("bad.request.reason", 0); + throw new BadRequestException("bad.request.reason", 0); } }); newController.createAction("fail_with_multiple_messages") @@ -335,11 +324,11 @@ public class WebServiceEngineTest { .setHandler(new RequestHandler() { @Override public void handle(Request request, Response response) { - List errors = Lists.newArrayList(); + Errors errors = new Errors(); for (int count = 0; count < Integer.valueOf(request.param("count")); count++) { errors.add(Message.of("Bad request reason #" + count)); } - throw BadRequestException.of(errors); + throw new BadRequestException(errors); } }); newController.createAction("fail_with_multiple_i18n_messages") @@ -347,18 +336,11 @@ public class WebServiceEngineTest { .setHandler(new RequestHandler() { @Override public void handle(Request request, Response response) { - List errors = Lists.newArrayList(); + Errors errors = new Errors(); for (int count = 0; count < Integer.valueOf(request.param("count")); count++) { - errors.add(Message.ofL10n("bad.request.reason", count)); + errors.add(Message.of("bad.request.reason", count)); } - throw BadRequestException.of(errors); - } - }); - newController.createAction("server_exception_with_i18n_message") - .setHandler(new RequestHandler() { - @Override - public void handle(Request request, Response response) { - throw new ServerException(404, null, "not.found", null); + throw new BadRequestException(errors); } }); newController.createAction("alive") -- 2.39.5