diff options
Diffstat (limited to 'sonar-server/src/main')
27 files changed, 267 insertions, 457 deletions
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<Message> errors; - - public BadRequestException(String message) { - super(BAD_REQUEST, message); - this.errors = newArrayList(); - } - - public BadRequestException(String message, List<Message> 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<Message> errors) { - super(BAD_REQUEST, message, l10nKey, l10nParams); - this.errors = errors; + public BadRequestException(List<Message> 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<Message> 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<Message> 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<Message> 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<Message> 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<Message> messages = Lists.newArrayList(); + + public Errors() { + } + + public Errors add(Errors errors) { + this.messages.addAll(errors.messages()); + return this; + } + + public Errors add(Collection<Message> 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<Message> 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<String, Object> 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<String, Object> getParams() { - return params; - } - - public Message setParams(Map<String, Object> 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<Message.Level, Message> messagesByLevel = ArrayListMultimap.create(); - - public Messages add(Message message) { - messagesByLevel.put(message.getLevel(), message); - return this; - } - - public Collection<Message> all() { - return messagesByLevel.values(); - } - - public List<Message> 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<Message> 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<String, Object> props, String comment) { + private void parse(Map<String, Object> 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<String, Object> actionProperties = getActionProps(action, props); @@ -83,7 +83,7 @@ public class IssueBulkChangeQuery { } } - private List<String> sanitizeList(List<String> list) { + private List<String> sanitizeList(@Nullable List<String> 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<QualityGateDto> 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<Message> 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<Message> 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<Message> 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<Message> 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<Message> 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<BadRequestException.Message> 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<BadRequestException.Message> 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<ActiveRuleChange> 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<ProfileImporter> importers, List<ProfileExporter> exporters) { + List<ProfileImporter> importers, List<ProfileExporter> 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<BadRequestException.Message> 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<ProfileExporter> 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<BadRequestException.Message> 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<String> 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<String> options) { + public void validate(String value, @Nullable List<String> 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<String> 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<String> 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<String> options); + void validate(String value, @Nullable List<String> 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<String> options) { + public void validate(String value, String type, @Nullable List<String> 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<String> 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 |