From ec5c44dd34ba4e77d43a0f6b67c9326a38c243dc Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Mon, 23 Feb 2015 21:51:43 +0100 Subject: [PATCH] Fix quality flaws --- .../org/sonar/process/LoopbackAddress.java | 2 +- .../computation/step/ParseReportStep.java | 9 ++-- .../sonar/server/issue/index/IssueIndex.java | 5 +- .../org/sonar/wsclient/services/WSUtils.java | 2 +- .../wsclient/unmarshallers/Unmarshallers.java | 2 +- .../sonar/batch/report/IssuesPublisher.java | 46 +++++++++------- .../sonar/core/util/NonNullInputFunction.java | 44 ++++++++++++++++ .../org/sonar/core/util/package-info.java | 24 +++++++++ .../core/util/NonNullInputFunctionTest.java | 52 +++++++++++++++++++ 9 files changed, 159 insertions(+), 27 deletions(-) create mode 100644 sonar-core/src/main/java/org/sonar/core/util/NonNullInputFunction.java create mode 100644 sonar-core/src/main/java/org/sonar/core/util/package-info.java create mode 100644 sonar-core/src/test/java/org/sonar/core/util/NonNullInputFunctionTest.java diff --git a/server/sonar-process/src/main/java/org/sonar/process/LoopbackAddress.java b/server/sonar-process/src/main/java/org/sonar/process/LoopbackAddress.java index 2302a626d2c..154fac61120 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/LoopbackAddress.java +++ b/server/sonar-process/src/main/java/org/sonar/process/LoopbackAddress.java @@ -27,7 +27,7 @@ import java.util.Enumeration; public class LoopbackAddress { - private static InetAddress instance; + private static volatile InetAddress instance; private LoopbackAddress() { // only static stuff diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ParseReportStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ParseReportStep.java index 042f13e7c4a..9d6f4a547e4 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ParseReportStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ParseReportStep.java @@ -92,10 +92,11 @@ public class ParseReportStep implements ComputationStep { private void recursivelyProcessComponent(BatchOutputReader reportReader, ComputationContext context, int componentRef) { BatchReport.Component component = reportReader.readComponent(componentRef); - issueComputation.processComponentIssues(context, component.getUuid(), reportReader.readComponentIssues(componentRef)); - - for (Integer childRef : component.getChildRefsList()) { - recursivelyProcessComponent(reportReader, context, childRef); + if (component != null) { + issueComputation.processComponentIssues(context, component.getUuid(), reportReader.readComponentIssues(componentRef)); + for (Integer childRef : component.getChildRefsList()) { + recursivelyProcessComponent(reportReader, context, childRef); + } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java index eb1a6f9b7c7..b719d076766 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java @@ -45,6 +45,7 @@ import org.sonar.api.issue.Issue; import org.sonar.api.rule.Severity; import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.System2; +import org.sonar.core.util.NonNullInputFunction; import org.sonar.server.es.*; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.issue.IssueQuery; @@ -101,9 +102,9 @@ public class IssueIndex extends BaseIndex { * Convert an Elasticsearch result (a map) to an {@link org.sonar.server.issue.index.IssueDoc}. It's * used for {@link org.sonar.server.es.SearchResult}. */ - private static final Function, IssueDoc> DOC_CONVERTER = new Function, IssueDoc>() { + private static final Function, IssueDoc> DOC_CONVERTER = new NonNullInputFunction, IssueDoc>() { @Override - public IssueDoc apply(Map input) { + protected IssueDoc doApply(Map input) { return new IssueDoc(input); } }; diff --git a/server/sonar-ws-client/src/main/java/org/sonar/wsclient/services/WSUtils.java b/server/sonar-ws-client/src/main/java/org/sonar/wsclient/services/WSUtils.java index 188204771b3..0c8dab2f8a9 100644 --- a/server/sonar-ws-client/src/main/java/org/sonar/wsclient/services/WSUtils.java +++ b/server/sonar-ws-client/src/main/java/org/sonar/wsclient/services/WSUtils.java @@ -31,7 +31,7 @@ import java.util.Set; */ public abstract class WSUtils { - private static WSUtils instance = null; + private static volatile WSUtils instance = null; public static void setInstance(WSUtils utils) { instance = utils; diff --git a/server/sonar-ws-client/src/main/java/org/sonar/wsclient/unmarshallers/Unmarshallers.java b/server/sonar-ws-client/src/main/java/org/sonar/wsclient/unmarshallers/Unmarshallers.java index 094bc270cd3..654e72fbb98 100644 --- a/server/sonar-ws-client/src/main/java/org/sonar/wsclient/unmarshallers/Unmarshallers.java +++ b/server/sonar-ws-client/src/main/java/org/sonar/wsclient/unmarshallers/Unmarshallers.java @@ -28,7 +28,7 @@ public final class Unmarshallers { private Unmarshallers() { } - private static Map unmarshallers; + private static volatile Map unmarshallers; static { unmarshallers = new HashMap(); diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java index a8e03ed8a4c..8be01240274 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java +++ b/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java @@ -81,33 +81,43 @@ public class IssuesPublisher implements ReportPublisher { if (message != null) { builder.setMsg(message); } - if (issue.effortToFix() != null) { - builder.setEffortToFix(issue.effortToFix()); + Double effortToFix = issue.effortToFix(); + if (effortToFix != null) { + builder.setEffortToFix(effortToFix); } - if (issue.debtInMinutes() != null) { - builder.setDebtInMinutes(issue.debtInMinutes()); + + Long debtInMinutes = issue.debtInMinutes(); + if (debtInMinutes != null) { + builder.setDebtInMinutes(debtInMinutes); } - if (issue.resolution() != null) { - builder.setResolution(issue.resolution()); + String resolution = issue.resolution(); + if (resolution != null) { + builder.setResolution(resolution); } - if (issue.status() != null) { - builder.setStatus(issue.status()); + String status = issue.status(); + if (status != null) { + builder.setStatus(status); } - if (issue.checksum() != null) { - builder.setChecksum(issue.checksum()); + String checksum = issue.checksum(); + if (checksum != null) { + builder.setChecksum(checksum); } builder.setManualSeverity(issue.manualSeverity()); - if (issue.reporter() != null) { - builder.setReporter(issue.reporter()); + String reporter = issue.reporter(); + if (reporter != null) { + builder.setReporter(reporter); } - if (issue.assignee() != null) { - builder.setAssignee(issue.assignee()); + String assignee = issue.assignee(); + if (assignee != null) { + builder.setAssignee(assignee); } - if (issue.actionPlanKey() != null) { - builder.setActionPlanKey(issue.actionPlanKey()); + String actionPlanKey = issue.actionPlanKey(); + if (actionPlanKey != null) { + builder.setActionPlanKey(actionPlanKey); } - if (issue.authorLogin() != null) { - builder.setAuthorLogin(issue.authorLogin()); + String authorLogin = issue.authorLogin(); + if (authorLogin != null) { + builder.setAuthorLogin(authorLogin); } String diff = diffsToString(issue.currentChange()); if (diff != null) { diff --git a/sonar-core/src/main/java/org/sonar/core/util/NonNullInputFunction.java b/sonar-core/src/main/java/org/sonar/core/util/NonNullInputFunction.java new file mode 100644 index 00000000000..bf312d68d25 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/util/NonNullInputFunction.java @@ -0,0 +1,44 @@ +/* + * 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.core.util; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; + +import javax.annotation.Nullable; + +/** + * Guava Function that does not accept null input elements + * @since 5.1 + */ +public abstract class NonNullInputFunction implements Function { + + @Override + public final T apply(@Nullable F input) { + Preconditions.checkNotNull(input, "Null inputs are not allowed in this function"); + return doApply(input); + } + + /** + * This method is the same as {@link #apply(Object)} except that the input argument + * is not marked as nullable + */ + protected abstract T doApply(F input); +} diff --git a/sonar-core/src/main/java/org/sonar/core/util/package-info.java b/sonar-core/src/main/java/org/sonar/core/util/package-info.java new file mode 100644 index 00000000000..5f2ad77c297 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/util/package-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +@ParametersAreNonnullByDefault +package org.sonar.core.util; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/sonar-core/src/test/java/org/sonar/core/util/NonNullInputFunctionTest.java b/sonar-core/src/test/java/org/sonar/core/util/NonNullInputFunctionTest.java new file mode 100644 index 00000000000..f7417d0ce48 --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/util/NonNullInputFunctionTest.java @@ -0,0 +1,52 @@ +/* + * 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.core.util; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; + +public class NonNullInputFunctionTest { + + NonNullInputFunction sut = new TestFunction(); + + @Test + public void fail_if_null_input() throws Exception { + try { + sut.apply(null); + fail(); + } catch (NullPointerException e) { + assertThat(e).hasMessage("Null inputs are not allowed in this function"); + } + } + + @Test + public void apply() throws Exception { + assertThat(sut.apply("foo")).isEqualTo(3); + } + + private static class TestFunction extends NonNullInputFunction { + @Override + protected Integer doApply(String input) { + return input.length(); + } + } +} -- 2.39.5