From 7e93f91f06dc47fcda0f69ece9ed284e6489ef10 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Sun, 19 Jan 2014 22:28:34 +0100 Subject: [PATCH] SONAR-5010 public API for Java web services --- sonar-plugin-api/pom.xml | 5 +++ .../org/sonar/api/utils/text}/JsonWriter.java | 42 ++++++++++++++++++- .../api/utils/text}/WriterException.java | 2 +- .../org/sonar/api/utils/text}/XmlWriter.java | 2 +- .../sonar/api/utils/text/package-info.java} | 20 ++------- .../java/org/sonar/api/web}/ws/Request.java | 2 +- .../org/sonar/api/web}/ws/RequestHandler.java | 2 +- .../java/org/sonar/api/web}/ws/Response.java | 19 +++++---- .../org/sonar/api/web}/ws/SimpleRequest.java | 2 +- .../org/sonar/api/web}/ws/SimpleResponse.java | 31 +++++++++----- .../org/sonar/api/web}/ws/WebService.java | 10 +++-- .../org/sonar/api/web/ws/package-info.java | 24 +++++++++++ .../sonar/api/utils/text}/JsonWriterTest.java | 31 +++++++++++++- .../sonar/api/utils/text}/XmlWriterTest.java | 2 +- .../sonar/api/web}/ws/SimpleRequestTest.java | 4 +- .../org/sonar/api/web}/ws/WebServiceTest.java | 41 +++++++++++++++++- .../sonar/server/ws/ListingWebService.java | 6 +++ .../org/sonar/server/ws/ServletRequest.java | 2 + .../org/sonar/server/ws/ServletResponse.java | 12 ++++-- .../org/sonar/server/ws/WebServiceEngine.java | 5 ++- .../app/controllers/api/java_ws_controller.rb | 4 +- .../app/controllers/issues_controller.rb | 36 ++++++++++++++++ .../server/ws/ListingWebServiceTest.java | 5 +-- .../sonar/server/ws/WebServiceEngineTest.java | 14 +++---- 24 files changed, 258 insertions(+), 65 deletions(-) rename {sonar-server/src/main/java/org/sonar/server/ws => sonar-plugin-api/src/main/java/org/sonar/api/utils/text}/JsonWriter.java (76%) rename {sonar-server/src/main/java/org/sonar/server/ws => sonar-plugin-api/src/main/java/org/sonar/api/utils/text}/WriterException.java (97%) rename {sonar-server/src/main/java/org/sonar/server/ws => sonar-plugin-api/src/main/java/org/sonar/api/utils/text}/XmlWriter.java (99%) rename sonar-plugin-api/src/{test/java/org/sonar/api/BaseModelTestCase.java => main/java/org/sonar/api/utils/text/package-info.java} (64%) rename {sonar-server/src/main/java/org/sonar/server => sonar-plugin-api/src/main/java/org/sonar/api/web}/ws/Request.java (97%) rename {sonar-server/src/main/java/org/sonar/server => sonar-plugin-api/src/main/java/org/sonar/api/web}/ws/RequestHandler.java (97%) rename {sonar-server/src/main/java/org/sonar/server => sonar-plugin-api/src/main/java/org/sonar/api/web}/ws/Response.java (75%) rename {sonar-server/src/main/java/org/sonar/server => sonar-plugin-api/src/main/java/org/sonar/api/web}/ws/SimpleRequest.java (98%) rename {sonar-server/src/main/java/org/sonar/server => sonar-plugin-api/src/main/java/org/sonar/api/web}/ws/SimpleResponse.java (61%) rename {sonar-server/src/main/java/org/sonar/server => sonar-plugin-api/src/main/java/org/sonar/api/web}/ws/WebService.java (95%) create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/web/ws/package-info.java rename {sonar-server/src/test/java/org/sonar/server/ws => sonar-plugin-api/src/test/java/org/sonar/api/utils/text}/JsonWriterTest.java (73%) rename {sonar-server/src/test/java/org/sonar/server/ws => sonar-plugin-api/src/test/java/org/sonar/api/utils/text}/XmlWriterTest.java (98%) rename {sonar-server/src/test/java/org/sonar/server => sonar-plugin-api/src/test/java/org/sonar/api/web}/ws/SimpleRequestTest.java (93%) rename {sonar-server/src/test/java/org/sonar/server => sonar-plugin-api/src/test/java/org/sonar/api/web}/ws/WebServiceTest.java (84%) diff --git a/sonar-plugin-api/pom.xml b/sonar-plugin-api/pom.xml index f6662a75c2a..b916f1dd6f7 100644 --- a/sonar-plugin-api/pom.xml +++ b/sonar-plugin-api/pom.xml @@ -13,6 +13,11 @@ SonarQube :: Plugin API + + com.google.code.gson + gson + provided + com.google.code.findbugs jsr305 diff --git a/sonar-server/src/main/java/org/sonar/server/ws/JsonWriter.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/text/JsonWriter.java similarity index 76% rename from sonar-server/src/main/java/org/sonar/server/ws/JsonWriter.java rename to sonar-plugin-api/src/main/java/org/sonar/api/utils/text/JsonWriter.java index 66a122d68dc..b5d1ebb1d96 100644 --- a/sonar-server/src/main/java/org/sonar/server/ws/JsonWriter.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/text/JsonWriter.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.ws; +package org.sonar.api.utils.text; import javax.annotation.Nullable; import java.io.Writer; @@ -39,9 +39,16 @@ public class JsonWriter { this.stream.setLenient(false); } + // for unit testing + JsonWriter(com.google.gson.stream.JsonWriter stream) { + this.stream = stream; + } + /** * Begins encoding a new array. Each call to this method must be paired with * a call to {@link #endArray}. Output is [. + * + * @throws org.sonar.api.utils.text.WriterException on any failure */ public JsonWriter beginArray() { try { @@ -54,6 +61,7 @@ public class JsonWriter { /** * Ends encoding the current array. Output is ]. + * @throws org.sonar.api.utils.text.WriterException on any failure */ public JsonWriter endArray() { try { @@ -67,6 +75,7 @@ public class JsonWriter { /** * Begins encoding a new object. Each call to this method must be paired * with a call to {@link #endObject}. Output is {. + * @throws org.sonar.api.utils.text.WriterException on any failure */ public JsonWriter beginObject() { try { @@ -79,6 +88,7 @@ public class JsonWriter { /** * Ends encoding the current object. Output is }. + * @throws org.sonar.api.utils.text.WriterException on any failure */ public JsonWriter endObject() { try { @@ -91,6 +101,7 @@ public class JsonWriter { /** * Encodes the property name. Output is "theName":. + * @throws org.sonar.api.utils.text.WriterException on any failure */ public JsonWriter name(String name) { try { @@ -103,6 +114,7 @@ public class JsonWriter { /** * Encodes {@code value}. Output is true or false. + * @throws org.sonar.api.utils.text.WriterException on any failure */ public JsonWriter value(boolean value) { try { @@ -113,6 +125,9 @@ public class JsonWriter { } } + /** + * @throws org.sonar.api.utils.text.WriterException on any failure + */ public JsonWriter value(double value) { try { stream.value(value); @@ -122,6 +137,9 @@ public class JsonWriter { } } + /** + * @throws org.sonar.api.utils.text.WriterException on any failure + */ public JsonWriter value(@Nullable String value) { try { stream.value(value); @@ -131,6 +149,9 @@ public class JsonWriter { } } + /** + * @throws org.sonar.api.utils.text.WriterException on any failure + */ public JsonWriter value(long value) { try { stream.value(value); @@ -140,6 +161,9 @@ public class JsonWriter { } } + /** + * @throws org.sonar.api.utils.text.WriterException on any failure + */ public JsonWriter value(@Nullable Number value) { try { stream.value(value); @@ -151,27 +175,43 @@ public class JsonWriter { /** * Encodes the property name and value. Output is for example "theName":123. + * @throws org.sonar.api.utils.text.WriterException on any failure */ public JsonWriter prop(String name, @Nullable Number value) { return name(name).value(value); } + /** + * @throws org.sonar.api.utils.text.WriterException on any failure + */ public JsonWriter prop(String name, @Nullable String value) { return name(name).value(value); } + /** + * @throws org.sonar.api.utils.text.WriterException on any failure + */ public JsonWriter prop(String name, boolean value) { return name(name).value(value); } + /** + * @throws org.sonar.api.utils.text.WriterException on any failure + */ public JsonWriter prop(String name, long value) { return name(name).value(value); } + /** + * @throws org.sonar.api.utils.text.WriterException on any failure + */ public JsonWriter prop(String name, double value) { return name(name).value(value); } + /** + * @throws org.sonar.api.utils.text.WriterException on any failure + */ public void close() { try { stream.close(); diff --git a/sonar-server/src/main/java/org/sonar/server/ws/WriterException.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/text/WriterException.java similarity index 97% rename from sonar-server/src/main/java/org/sonar/server/ws/WriterException.java rename to sonar-plugin-api/src/main/java/org/sonar/api/utils/text/WriterException.java index 9c9376c1375..a11bf7c6962 100644 --- a/sonar-server/src/main/java/org/sonar/server/ws/WriterException.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/text/WriterException.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.ws; +package org.sonar.api.utils.text; /** * @since 4.2 diff --git a/sonar-server/src/main/java/org/sonar/server/ws/XmlWriter.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/text/XmlWriter.java similarity index 99% rename from sonar-server/src/main/java/org/sonar/server/ws/XmlWriter.java rename to sonar-plugin-api/src/main/java/org/sonar/api/utils/text/XmlWriter.java index 2f5e2e50cd4..e9527358a4f 100644 --- a/sonar-server/src/main/java/org/sonar/server/ws/XmlWriter.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/text/XmlWriter.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.ws; +package org.sonar.api.utils.text; import javax.annotation.Nullable; import javax.xml.stream.XMLOutputFactory; diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/BaseModelTestCase.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/text/package-info.java similarity index 64% rename from sonar-plugin-api/src/test/java/org/sonar/api/BaseModelTestCase.java rename to sonar-plugin-api/src/main/java/org/sonar/api/utils/text/package-info.java index ada6c76712a..1c11215f8d5 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/BaseModelTestCase.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/text/package-info.java @@ -17,22 +17,8 @@ * 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.api; +@ParametersAreNonnullByDefault +package org.sonar.api.utils.text; -import static org.junit.Assert.assertEquals; +import javax.annotation.ParametersAreNonnullByDefault; -public abstract class BaseModelTestCase { - - protected String overFillString(int maxSize) { - StringBuilder overFilled = new StringBuilder(); - for (int i = 0; i < 50 + maxSize; i++) { - overFilled.append("x"); - } - return overFilled.toString(); - } - - protected void assertAbbreviated(int maxSize, String value) { - assertEquals(maxSize, value.length()); - assertEquals('.', value.charAt(maxSize - 1)); - } -} diff --git a/sonar-server/src/main/java/org/sonar/server/ws/Request.java b/sonar-plugin-api/src/main/java/org/sonar/api/web/ws/Request.java similarity index 97% rename from sonar-server/src/main/java/org/sonar/server/ws/Request.java rename to sonar-plugin-api/src/main/java/org/sonar/api/web/ws/Request.java index bb7111620d6..0aac4f12665 100644 --- a/sonar-server/src/main/java/org/sonar/server/ws/Request.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/web/ws/Request.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.ws; +package org.sonar.api.web.ws; import javax.annotation.CheckForNull; diff --git a/sonar-server/src/main/java/org/sonar/server/ws/RequestHandler.java b/sonar-plugin-api/src/main/java/org/sonar/api/web/ws/RequestHandler.java similarity index 97% rename from sonar-server/src/main/java/org/sonar/server/ws/RequestHandler.java rename to sonar-plugin-api/src/main/java/org/sonar/api/web/ws/RequestHandler.java index c4783b1c8a6..c7cc37ad1a2 100644 --- a/sonar-server/src/main/java/org/sonar/server/ws/RequestHandler.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/web/ws/RequestHandler.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.ws; +package org.sonar.api.web.ws; import org.sonar.api.ServerExtension; diff --git a/sonar-server/src/main/java/org/sonar/server/ws/Response.java b/sonar-plugin-api/src/main/java/org/sonar/api/web/ws/Response.java similarity index 75% rename from sonar-server/src/main/java/org/sonar/server/ws/Response.java rename to sonar-plugin-api/src/main/java/org/sonar/api/web/ws/Response.java index 8296c40ef30..6bcb3e75443 100644 --- a/sonar-server/src/main/java/org/sonar/server/ws/Response.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/web/ws/Response.java @@ -17,8 +17,12 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.ws; +package org.sonar.api.web.ws; +import org.sonar.api.utils.text.JsonWriter; +import org.sonar.api.utils.text.XmlWriter; + +import java.io.OutputStream; import java.io.Writer; /** @@ -26,15 +30,16 @@ import java.io.Writer; * * @since 4.2 */ -public abstract class Response { +public interface Response { + + int status(); - public abstract JsonWriter newJsonWriter(); + Response setStatus(int httpStatus); - public abstract XmlWriter newXmlWriter(); + JsonWriter newJsonWriter(); - public abstract Writer writer(); + XmlWriter newXmlWriter(); - public abstract int status(); + OutputStream output(); - public abstract Response setStatus(int httpStatus); } diff --git a/sonar-server/src/main/java/org/sonar/server/ws/SimpleRequest.java b/sonar-plugin-api/src/main/java/org/sonar/api/web/ws/SimpleRequest.java similarity index 98% rename from sonar-server/src/main/java/org/sonar/server/ws/SimpleRequest.java rename to sonar-plugin-api/src/main/java/org/sonar/api/web/ws/SimpleRequest.java index 014537e7ce1..5a89ca46dd6 100644 --- a/sonar-server/src/main/java/org/sonar/server/ws/SimpleRequest.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/web/ws/SimpleRequest.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.ws; +package org.sonar.api.web.ws; import com.google.common.collect.Maps; diff --git a/sonar-server/src/main/java/org/sonar/server/ws/SimpleResponse.java b/sonar-plugin-api/src/main/java/org/sonar/api/web/ws/SimpleResponse.java similarity index 61% rename from sonar-server/src/main/java/org/sonar/server/ws/SimpleResponse.java rename to sonar-plugin-api/src/main/java/org/sonar/api/web/ws/SimpleResponse.java index e686ecf90cf..0e70a571657 100644 --- a/sonar-server/src/main/java/org/sonar/server/ws/SimpleResponse.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/web/ws/SimpleResponse.java @@ -17,29 +17,38 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.ws; +package org.sonar.api.web.ws; -import javax.servlet.http.HttpServletResponse; -import java.io.StringWriter; -import java.io.Writer; +import org.apache.commons.io.Charsets; +import org.sonar.api.utils.text.JsonWriter; +import org.sonar.api.utils.text.XmlWriter; -public class SimpleResponse extends Response { - private int httpStatus = HttpServletResponse.SC_OK; - private final Writer writer = new StringWriter(); +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; + +public class SimpleResponse implements Response { + private int httpStatus = 200; + private final ByteArrayOutputStream output = new ByteArrayOutputStream(); @Override public JsonWriter newJsonWriter() { - return JsonWriter.of(writer); + return JsonWriter.of(new OutputStreamWriter(output, Charsets.UTF_8)); } @Override public XmlWriter newXmlWriter() { - return XmlWriter.of(writer); + return XmlWriter.of(new OutputStreamWriter(output, Charsets.UTF_8)); } @Override - public Writer writer() { - return writer; + public OutputStream output() { + return output; + } + + // for unit testing + public String outputAsString() { + return new String(output.toByteArray(), Charsets.UTF_8); } @Override diff --git a/sonar-server/src/main/java/org/sonar/server/ws/WebService.java b/sonar-plugin-api/src/main/java/org/sonar/api/web/ws/WebService.java similarity index 95% rename from sonar-server/src/main/java/org/sonar/server/ws/WebService.java rename to sonar-plugin-api/src/main/java/org/sonar/api/web/ws/WebService.java index 01d029e9825..0b8c680891e 100644 --- a/sonar-server/src/main/java/org/sonar/server/ws/WebService.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/web/ws/WebService.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.ws; +package org.sonar.api.web.ws; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -69,7 +69,9 @@ public interface WebService extends ServerExtension { private final Map actions = Maps.newHashMap(); private NewController(Context context, String path) { - // TODO check format of path + if (StringUtils.isBlank(path)) { + throw new IllegalArgumentException("Web service path can't be empty"); + } this.context = context; this.path = path; } @@ -191,6 +193,9 @@ public interface WebService extends ServerExtension { this.description = newAction.description; this.since = StringUtils.defaultIfBlank(newAction.since, controller.since); this.post = newAction.post; + if (newAction.handler == null) { + throw new IllegalStateException("RequestHandler is not set on action " + path); + } this.handler = newAction.handler; } @@ -219,7 +224,6 @@ public interface WebService extends ServerExtension { return post; } - @CheckForNull public RequestHandler handler() { return handler; } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/web/ws/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/web/ws/package-info.java new file mode 100644 index 00000000000..b5fcdf6e8d1 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/web/ws/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.api.web.ws; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-server/src/test/java/org/sonar/server/ws/JsonWriterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/text/JsonWriterTest.java similarity index 73% rename from sonar-server/src/test/java/org/sonar/server/ws/JsonWriterTest.java rename to sonar-plugin-api/src/test/java/org/sonar/api/utils/text/JsonWriterTest.java index f99f99074eb..4fe227d8be4 100644 --- a/sonar-server/src/test/java/org/sonar/server/ws/JsonWriterTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/utils/text/JsonWriterTest.java @@ -17,15 +17,21 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.ws; +package org.sonar.api.utils.text; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.sonar.api.utils.text.JsonWriter; +import org.sonar.api.utils.text.WriterException; +import java.io.IOException; import java.io.StringWriter; +import java.util.concurrent.atomic.AtomicInteger; import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class JsonWriterTest { @@ -69,6 +75,19 @@ public class JsonWriterTest { expect("{\"issues\":[{\"key\":\"ABC\"},{\"key\":\"DEF\"}]}"); } + @Test + public void type_of_values() throws Exception { + writer.beginObject() + .prop("aBoolean", true) + .prop("aInt", 123) + .prop("aLong", 1000L) + .prop("aDouble", 3.14) + .prop("aNumber", new AtomicInteger(123456789)) + .prop("aString", "bar") + .endObject().close(); + expect("{\"aBoolean\":true,\"aInt\":123,\"aLong\":1000,\"aDouble\":3.14,\"aNumber\":123456789,\"aString\":\"bar\"}"); + } + @Test public void ignore_null_values() throws Exception { writer.beginObject() @@ -100,4 +119,14 @@ public class JsonWriterTest { thrown.expect(WriterException.class); writer.beginObject().endArray().close(); } + + @Test + public void fail_to_begin_array() throws Exception { + com.google.gson.stream.JsonWriter gson = mock(com.google.gson.stream.JsonWriter.class); + when(gson.beginArray()).thenThrow(new IOException("the reason")); + thrown.expect(WriterException.class); + thrown.expectMessage("Fail to write JSON: the reason"); + + new JsonWriter(gson).beginArray(); + } } diff --git a/sonar-server/src/test/java/org/sonar/server/ws/XmlWriterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/text/XmlWriterTest.java similarity index 98% rename from sonar-server/src/test/java/org/sonar/server/ws/XmlWriterTest.java rename to sonar-plugin-api/src/test/java/org/sonar/api/utils/text/XmlWriterTest.java index 9302b4318f5..4aa1f98b443 100644 --- a/sonar-server/src/test/java/org/sonar/server/ws/XmlWriterTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/utils/text/XmlWriterTest.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.ws; +package org.sonar.api.utils.text; import org.junit.Rule; import org.junit.Test; diff --git a/sonar-server/src/test/java/org/sonar/server/ws/SimpleRequestTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/web/ws/SimpleRequestTest.java similarity index 93% rename from sonar-server/src/test/java/org/sonar/server/ws/SimpleRequestTest.java rename to sonar-plugin-api/src/test/java/org/sonar/api/web/ws/SimpleRequestTest.java index c5164d4317a..b6120c5cc39 100644 --- a/sonar-server/src/test/java/org/sonar/server/ws/SimpleRequestTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/web/ws/SimpleRequestTest.java @@ -17,10 +17,12 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.ws; +package org.sonar.api.web.ws; import com.google.common.collect.ImmutableMap; import org.junit.Test; +import org.sonar.api.web.ws.Request; +import org.sonar.api.web.ws.SimpleRequest; import static org.fest.assertions.Assertions.assertThat; diff --git a/sonar-server/src/test/java/org/sonar/server/ws/WebServiceTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/web/ws/WebServiceTest.java similarity index 84% rename from sonar-server/src/test/java/org/sonar/server/ws/WebServiceTest.java rename to sonar-plugin-api/src/test/java/org/sonar/api/web/ws/WebServiceTest.java index 7f17e67b33c..0485597ee18 100644 --- a/sonar-server/src/test/java/org/sonar/server/ws/WebServiceTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/web/ws/WebServiceTest.java @@ -17,9 +17,13 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.ws; +package org.sonar.api.web.ws; import org.junit.Test; +import org.sonar.api.web.ws.Request; +import org.sonar.api.web.ws.RequestHandler; +import org.sonar.api.web.ws.Response; +import org.sonar.api.web.ws.WebService; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Fail.fail; @@ -98,6 +102,7 @@ public class WebServiceTest { WebService.Action createAction = controller.action("create"); assertThat(createAction).isNotNull(); assertThat(createAction.key()).isEqualTo("create"); + assertThat(createAction.toString()).isEqualTo("api/metric/create"); // overrides controller version assertThat(createAction.since()).isEqualTo("4.1"); assertThat(createAction.isPost()).isTrue(); @@ -109,7 +114,7 @@ public class WebServiceTest { @Override public void define(Context context) { NewController controller = context.newController("rule"); - controller.newAction("index"); + controller.newAction("index").setHandler(mock(RequestHandler.class)); controller.done(); } }.define(context); @@ -135,6 +140,23 @@ public class WebServiceTest { } } + @Test + public void fail_if_no_action_handler() { + try { + new WebService() { + @Override + public void define(Context context) { + NewController controller = context.newController("rule"); + controller.newAction("show"); + controller.done(); + } + }.define(context); + fail(); + } catch (IllegalStateException e) { + assertThat(e).hasMessage("RequestHandler is not set on action rule/show"); + } + } + @Test public void fail_if_duplicated_action_keys() { try { @@ -169,6 +191,21 @@ public class WebServiceTest { } } + @Test + public void fail_if_no_ws_path() { + try { + new WebService() { + @Override + public void define(Context context) { + context.newController(null).done(); + } + }.define(context); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage("Web service path can't be empty"); + } + } + @Test public void handle_request() throws Exception { MetricWebService metricWs = new MetricWebService(); diff --git a/sonar-server/src/main/java/org/sonar/server/ws/ListingWebService.java b/sonar-server/src/main/java/org/sonar/server/ws/ListingWebService.java index 6f84efe8304..9d5afcbc995 100644 --- a/sonar-server/src/main/java/org/sonar/server/ws/ListingWebService.java +++ b/sonar-server/src/main/java/org/sonar/server/ws/ListingWebService.java @@ -19,6 +19,12 @@ */ package org.sonar.server.ws; +import org.sonar.api.utils.text.JsonWriter; +import org.sonar.api.web.ws.Request; +import org.sonar.api.web.ws.RequestHandler; +import org.sonar.api.web.ws.Response; +import org.sonar.api.web.ws.WebService; + import java.util.List; /** diff --git a/sonar-server/src/main/java/org/sonar/server/ws/ServletRequest.java b/sonar-server/src/main/java/org/sonar/server/ws/ServletRequest.java index 0b20e1d3ac0..e38e53975b3 100644 --- a/sonar-server/src/main/java/org/sonar/server/ws/ServletRequest.java +++ b/sonar-server/src/main/java/org/sonar/server/ws/ServletRequest.java @@ -19,6 +19,8 @@ */ package org.sonar.server.ws; +import org.sonar.api.web.ws.Request; + import javax.servlet.http.HttpServletRequest; public class ServletRequest extends Request { diff --git a/sonar-server/src/main/java/org/sonar/server/ws/ServletResponse.java b/sonar-server/src/main/java/org/sonar/server/ws/ServletResponse.java index fc21e30faca..97c03a98989 100644 --- a/sonar-server/src/main/java/org/sonar/server/ws/ServletResponse.java +++ b/sonar-server/src/main/java/org/sonar/server/ws/ServletResponse.java @@ -19,11 +19,15 @@ */ package org.sonar.server.ws; +import org.sonar.api.utils.text.JsonWriter; +import org.sonar.api.utils.text.XmlWriter; +import org.sonar.api.web.ws.Response; + import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.io.Writer; +import java.io.OutputStream; -public class ServletResponse extends Response { +public class ServletResponse implements Response { private final HttpServletResponse source; @@ -50,9 +54,9 @@ public class ServletResponse extends Response { } @Override - public Writer writer() { + public OutputStream output() { try { - return source.getWriter(); + return source.getOutputStream(); } catch (IOException e) { throw new IllegalStateException(e); } 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 4a1fc653394..84037f4e460 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 @@ -21,9 +21,12 @@ package org.sonar.server.ws; import org.picocontainer.Startable; import org.sonar.api.ServerComponent; +import org.sonar.api.utils.text.JsonWriter; +import org.sonar.api.web.ws.Request; +import org.sonar.api.web.ws.Response; +import org.sonar.api.web.ws.WebService; import javax.servlet.http.HttpServletResponse; -import java.io.StringWriter; import java.util.List; /** diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/java_ws_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/java_ws_controller.rb index 6b06249c14a..8ff82b92ebf 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/java_ws_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/java_ws_controller.rb @@ -40,6 +40,8 @@ class Api::JavaWsController < Api::ApiController engine = Java::OrgSonarServerPlatform::Platform.component(Java::OrgSonarServerWs::WebServiceEngine.java_class) engine.execute(ws_request, ws_response, params[:wspath], params[:wsaction]) - render :text => ws_response.writer(), :status => ws_response.status(), :content_type => media_type + + # response is already written to HttpServletResponse. No need to feed :text + render :text => '', :status => ws_response.status(), :content_type => media_type end end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb index 158fc98daf3..8d5a686080c 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb @@ -60,6 +60,42 @@ class IssuesController < ApplicationController end + # GET /issues/init?[id=] + def page_init + hash = {} + hash[:canBulkChange]=logged_in? + hash[:canManageFilter]=logged_in? + + if logged_in? + favorite_filters = Internal.issues.findFavouriteIssueFiltersForCurrentUser() + hash[:favorites] = favorite_filters.map do |filter| + { + :id => filter.id().to_i, + :name => filter.name(), + :user => filter.user(), + :shared => filter.shared() + # no need to export description and query fields + } + end + end + + if params[:id] + filter = Internal.issues.findIssueFilter(params[:id].to_i) + hash[:filter] = { + :id => filter.id().to_i, + :name => filter.name(), + :user => filter.user(), + :shared => filter.shared(), + :description => filter.description(), + :query => filter.data() + } + end + + respond_to do |format| + format.json { render :json => hash, :status => 200 } + end + end + # Load existing filter # GET /issues/filter/ def filter diff --git a/sonar-server/src/test/java/org/sonar/server/ws/ListingWebServiceTest.java b/sonar-server/src/test/java/org/sonar/server/ws/ListingWebServiceTest.java index 05cf1e35718..95227dd8dc6 100644 --- a/sonar-server/src/test/java/org/sonar/server/ws/ListingWebServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/ws/ListingWebServiceTest.java @@ -22,8 +22,7 @@ package org.sonar.server.ws; import org.apache.commons.io.IOUtils; import org.junit.Test; import org.skyscreamer.jsonassert.JSONAssert; - -import java.io.StringWriter; +import org.sonar.api.web.ws.*; import static org.fest.assertions.Assertions.assertThat; @@ -62,7 +61,7 @@ public class ListingWebServiceTest { JSONAssert.assertEquals( IOUtils.toString(getClass().getResource("/org/sonar/server/ws/ListingWebServiceTest/index.json")), - response.writer().toString(), true + response.outputAsString(), true ); } 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 6976b1e4dfa..5565f7e1598 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,10 +19,10 @@ */ package org.sonar.server.ws; -import com.google.common.collect.Maps; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.sonar.api.web.ws.*; import static org.fest.assertions.Assertions.assertThat; @@ -52,7 +52,7 @@ public class WebServiceEngineTest { SimpleResponse response = new SimpleResponse(); engine.execute(request, response, "api/system", "health"); - assertThat(response.writer().toString()).isEqualTo("good"); + assertThat(response.outputAsString()).isEqualTo("good"); assertThat(response.status()).isEqualTo(200); } @@ -62,7 +62,7 @@ public class WebServiceEngineTest { SimpleResponse response = new SimpleResponse(); engine.execute(request, response, "api/xxx", "health"); - assertThat(response.writer().toString()).isEqualTo("{\"errors\":[{\"msg\":\"Unknown web service: api/xxx\"}]}"); + assertThat(response.outputAsString()).isEqualTo("{\"errors\":[{\"msg\":\"Unknown web service: api/xxx\"}]}"); assertThat(response.status()).isEqualTo(400); } @@ -72,7 +72,7 @@ public class WebServiceEngineTest { SimpleResponse response = new SimpleResponse(); engine.execute(request, response, "api/system", "xxx"); - assertThat(response.writer().toString()).isEqualTo("{\"errors\":[{\"msg\":\"Unknown action: api/system/xxx\"}]}"); + assertThat(response.outputAsString()).isEqualTo("{\"errors\":[{\"msg\":\"Unknown action: api/system/xxx\"}]}"); assertThat(response.status()).isEqualTo(400); } @@ -82,7 +82,7 @@ public class WebServiceEngineTest { SimpleResponse response = new SimpleResponse(); engine.execute(request, response, "api/system", "ping"); - assertThat(response.writer().toString()).isEqualTo("{\"errors\":[{\"msg\":\"Method POST is required\"}]}"); + assertThat(response.outputAsString()).isEqualTo("{\"errors\":[{\"msg\":\"Method POST is required\"}]}"); assertThat(response.status()).isEqualTo(405); } @@ -94,7 +94,7 @@ public class WebServiceEngineTest { .setHandler(new RequestHandler() { @Override public void handle(Request request, Response response) throws Exception { - response.writer().write("good"); + response.output().write("good".getBytes()); } }); newController.newAction("ping") @@ -102,7 +102,7 @@ public class WebServiceEngineTest { .setHandler(new RequestHandler() { @Override public void handle(Request request, Response response) throws Exception { - response.writer().write("pong"); + response.output().write("pong".getBytes()); } }); newController.done(); -- 2.39.5