<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.codehaus.sonar</groupId>
</properties>
<dependencies>
- <!-- Don't forget to update configuration of the m-bundle-p (especially Require-Bundle)
- according to changes you make on dependencies -->
+ <!-- Don't forget to update configuration of the m-bundle-p (especially Require-Bundle)
+ according to changes you make on dependencies -->
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
- <optional>true</optional>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient4.version}</version>
- <optional>true</optional>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.github.kevinsawicki</groupId>
+ <artifactId>http-request</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <scope>provided</scope>
</dependency>
<!-- unit tests -->
<build>
<plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <configuration>
+ <createDependencyReducedPom>true</createDependencyReducedPom>
+ <minimizeJar>true</minimizeJar>
+ <relocations>
+ <relocation>
+ <pattern>com.github.kevinsawicki.http</pattern>
+ <shadedPattern>org.sonar.wsclient.kevinsawicki</shadedPattern>
+ </relocation>
+ <relocation>
+ <pattern>org.json.simple</pattern>
+ <shadedPattern>org.sonar.wsclient.jsonsimple</shadedPattern>
+ </relocation>
+ </relocations>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<Import-Package>!*</Import-Package>
<Require-Bundle>org.apache.httpcomponents.httpclient;bundle-version="${httpclient4.version}";optional="true",
org.apache.httpcomponents.httpcore;bundle-version="${httpclient4.version}";optional="true",
- com.googlecode.json-simple
</Require-Bundle>
<Export-Package>!.,org.sonar.wsclient,
org.sonar.wsclient.connectors,
- org.sonar.wsclient.services</Export-Package>
- <Bundle-RequiredExecutionEnvironment>J2SE-1.5</Bundle-RequiredExecutionEnvironment>
+ org.sonar.wsclient.services
+ </Export-Package>
+ <Bundle-RequiredExecutionEnvironment>J2SE-1.6</Bundle-RequiredExecutionEnvironment>
</instructions>
</configuration>
<executions>
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient;
+
+import org.sonar.wsclient.internal.HttpRequestFactory;
+import org.sonar.wsclient.issue.DefaultIssueClient;
+import org.sonar.wsclient.issue.IssueClient;
+
+/**
+ * @since 3.6
+ */
+public class SonarClient {
+
+ private final HttpRequestFactory requestFactory;
+
+ private SonarClient(Builder builder) {
+ requestFactory = new HttpRequestFactory(builder.url, builder.login, builder.password);
+ }
+
+ public IssueClient issueClient() {
+ return new DefaultIssueClient(requestFactory);
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private String login, password, url;
+
+ private Builder() {
+ }
+
+ public Builder login(String login) {
+ this.login = login;
+ return this;
+ }
+
+ public Builder password(String password) {
+ this.password = password;
+ return this;
+ }
+
+ public Builder url(String url) {
+ this.url = url;
+ return this;
+ }
+
+ public SonarClient build() {
+ if (url == null || "".equals(url)) {
+ throw new IllegalStateException("Server URL must be set");
+ }
+ return new SonarClient(this);
+ }
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.internal;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Not an API, please do not directly use this class.
+ */
+public class EncodingUtils {
+
+ private static final String DATETIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ";
+ private static final String DATE_FORMAT = "yyyy-MM-dd";
+
+ private EncodingUtils() {
+ // only static methods
+ }
+
+ public static String toQueryParam(String[] strings) {
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for (String string : strings) {
+ if (!first) {
+ sb.append(',');
+ }
+ sb.append(string);
+ first = false;
+ }
+ return sb.toString();
+ }
+
+ public static String toQueryParam(Date d, boolean includeTime) {
+ String format = (includeTime ? DATETIME_FORMAT : DATE_FORMAT);
+ SimpleDateFormat dateFormat = new SimpleDateFormat(format);
+ return dateFormat.format(d);
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.internal;
+
+import com.github.kevinsawicki.http.HttpRequest;
+
+import java.util.Map;
+
+/**
+ * Not an API, please do not directly use this class.
+ */
+public class HttpRequestFactory {
+
+ static final int CONNECT_TIMEOUT_MILLISECONDS = 30000;
+ static final int READ_TIMEOUT_MILLISECONDS = 60000;
+
+ private final String baseURl;
+ private final String login, password;
+
+ public HttpRequestFactory(String baseURl, String login, String password) {
+ this.baseURl = baseURl;
+ this.login = login;
+ this.password = password;
+ }
+
+ public HttpRequest get(String wsUrl, Map<String, Object> queryParams) {
+ HttpRequest request = HttpRequest.get(baseURl + wsUrl, queryParams, true);
+ return prepare(request);
+ }
+
+ public HttpRequest post(String wsUrl, Map<String, Object> queryParams) {
+ HttpRequest request = HttpRequest.post(baseURl + wsUrl, queryParams, true);
+ return prepare(request);
+ }
+
+ private HttpRequest prepare(HttpRequest request) {
+ request
+ .acceptGzipEncoding()
+ .uncompress(true)
+ .acceptJson()
+ .acceptCharset(HttpRequest.CHARSET_UTF8)
+ .connectTimeout(CONNECT_TIMEOUT_MILLISECONDS)
+ .readTimeout(READ_TIMEOUT_MILLISECONDS)
+ .trustAllCerts()
+ .trustAllCerts();
+ if (login != null) {
+ request.basic(login, password);
+ }
+ return request;
+ }
+}
--- /dev/null
+/*
+ * Sonar Runner - Implementation
+ * Copyright (C) 2011 SonarSource
+ * dev@sonar.codehaus.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.wsclient.internal;
\ No newline at end of file
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.issue;
+
+import com.github.kevinsawicki.http.HttpRequest;
+import org.sonar.wsclient.internal.HttpRequestFactory;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Do not instantiate this class, but use {@link org.sonar.wsclient.SonarClient#issueClient()}.
+ */
+public class DefaultIssueClient implements IssueClient {
+
+ private final HttpRequestFactory requestFactory;
+ private final IssueParser parser;
+
+ /**
+ * For internal use. Use {@link org.sonar.wsclient.SonarClient} to get an instance.
+ */
+ public DefaultIssueClient(HttpRequestFactory requestFactory) {
+ this.requestFactory = requestFactory;
+ this.parser = new IssueParser();
+ }
+
+ public Issues find(IssueQuery query) {
+ HttpRequest request = requestFactory.get(IssueQuery.BASE_URL, query.urlParams());
+ if (!request.ok()) {
+ throw new IllegalStateException("Fail to search for issues. Bad HTTP response status: " + request.code());
+ }
+ String json = request.body("UTF-8");
+ return parser.parseIssues(json);
+ }
+
+ @Override
+ public void apply(String issueKey, IssueChange change) {
+ if (!change.urlParams().isEmpty()) {
+ Map<String, Object> queryParams = new LinkedHashMap<String, Object>(change.urlParams());
+ queryParams.put("key", issueKey);
+ HttpRequest request = requestFactory.post(IssueChange.BASE_URL, queryParams);
+ if (!request.ok()) {
+ throw new IllegalStateException("Fail to change issue " + issueKey + ".Bad HTTP response status: " + request.code());
+ }
+ }
+ }
+
+ @Override
+ public void create(NewIssue newIssue) {
+ HttpRequest request = requestFactory.post(NewIssue.BASE_URL, newIssue.urlParams());
+ if (!request.ok()) {
+ throw new IllegalStateException("Fail to create issue. Bad HTTP response status: " + request.code());
+ }
+ }
+
+ @Override
+ public void comment(String issueKey, String comment) {
+ apply(issueKey, IssueChange.create().comment(comment));
+ }
+
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar{} if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.issue;
+
+import org.sonar.wsclient.unmarshallers.JsonUtils;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * @since 3.6
+ */
+public class Issue {
+
+ private final Map json;
+
+ Issue(Map json) {
+ this.json = json;
+ }
+
+ /**
+ * Unique key
+ */
+ public String key() {
+ return JsonUtils.getString(json, "key");
+ }
+
+ public String componentKey() {
+ return JsonUtils.getString(json, "component");
+ }
+
+ public String ruleKey() {
+ return JsonUtils.getString(json, "rule");
+ }
+
+ public String severity() {
+ return JsonUtils.getString(json, "severity");
+ }
+
+ public String title() {
+ return JsonUtils.getString(json, "title");
+ }
+
+ public String description() {
+ return JsonUtils.getString(json, "desc");
+ }
+
+ public Integer line() {
+ return JsonUtils.getInteger(json, "line");
+ }
+
+ public Double cost() {
+ return JsonUtils.getDouble(json, "cost");
+ }
+
+ public String status() {
+ return JsonUtils.getString(json, "status");
+ }
+
+ public String resolution() {
+ return JsonUtils.getString(json, "resolution");
+ }
+
+ public String userLogin() {
+ return JsonUtils.getString(json, "userLogin");
+ }
+
+ public String assignee() {
+ return JsonUtils.getString(json, "assignee");
+ }
+
+ public Date createdAt() {
+ return JsonUtils.getDateTime(json, "createdAt");
+ }
+
+ public Date updatedAt() {
+ return JsonUtils.getDateTime(json, "updatedAt");
+ }
+
+ public Date closedAt() {
+ return JsonUtils.getDateTime(json, "closedAt");
+ }
+
+ public String attribute(String key) {
+ return attributes().get(key);
+ }
+
+ public Map<String, String> attributes() {
+ Map<String, String> attr = (Map) json.get("attr");
+ if (attr == null) {
+ return Collections.emptyMap();
+ }
+ return attr;
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.issue;
+
+import javax.annotation.Nullable;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * @since 3.6
+ */
+public class IssueChange {
+ static final String BASE_URL = "/api/issues/change";
+ private final Map<String, Object> params = new LinkedHashMap<String, Object>();
+
+ private IssueChange() {
+ }
+
+ public static IssueChange create() {
+ return new IssueChange();
+ }
+
+ Map<String, Object> urlParams() {
+ return params;
+ }
+
+ public IssueChange severity(String s) {
+ params.put("newSeverity", s);
+ return this;
+ }
+
+ /**
+ * Add a comment
+ */
+ public IssueChange comment(String s) {
+ params.put("newComment", s);
+ return this;
+ }
+
+ public IssueChange cost(Double d) {
+ params.put("newCost", d);
+ return this;
+ }
+
+ public IssueChange resolution(String s) {
+ params.put("newResolution", s);
+ return this;
+ }
+
+ public IssueChange assignee(String login) {
+ params.put("newAssignee", login);
+ return this;
+ }
+
+ public IssueChange attribute(String key, @Nullable String value) {
+ if (value == null) {
+ params.put("newAttr[" + key + "]", "");
+ } else {
+ params.put("newAttr[" + key + "]", value);
+ }
+ return this;
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.issue;
+
+/**
+ * @since 3.6
+ */
+public interface IssueClient {
+
+ Issues find(IssueQuery query);
+
+ void apply(String issueKey, IssueChange change);
+
+ void create(NewIssue issue);
+
+ /**
+ * Shortcut for {@code #apply(issueKey, IssueChange.create().comment(comment)}
+ */
+ void comment(String issueKey, String comment);
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.issue;
+
+import org.json.simple.JSONValue;
+
+import java.util.List;
+import java.util.Map;
+
+class IssueParser {
+ Issues parseIssues(String json) {
+ Issues result = new Issues();
+ Map jRoot = (Map) JSONValue.parse(json);
+ List<Map> jIssues = (List) jRoot.get("issues");
+ for (Map jIssue : jIssues) {
+ result.add(new Issue(jIssue));
+ }
+ return result;
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.issue;
+
+import org.sonar.wsclient.internal.EncodingUtils;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @since 3.6
+ */
+public class IssueQuery {
+
+ static final String BASE_URL = "/api/issues/search";
+ private final Map<String, Object> params = new HashMap<String, Object>();
+
+ private IssueQuery() {
+ }
+
+ public static IssueQuery create() {
+ return new IssueQuery();
+ }
+
+ Map<String, Object> urlParams() {
+ return params;
+ }
+
+ public IssueQuery keys(String... keys) {
+ return addParam("keys", keys);
+ }
+
+ public IssueQuery severities(String... severities) {
+ return addParam("severities", severities);
+ }
+
+ public IssueQuery statuses(String... statuses) {
+ return addParam("statuses", statuses);
+ }
+
+ public IssueQuery resolutions(String... resolutions) {
+ return addParam("resolutions", resolutions);
+ }
+
+ public IssueQuery components(String... components) {
+ return addParam("components", components);
+ }
+
+ public IssueQuery componentRoots(String... componentRoots) {
+ return addParam("componentRoots", componentRoots);
+ }
+
+ public IssueQuery rules(String... s) {
+ return addParam("rules", s);
+ }
+
+ public IssueQuery userLogins(String... s) {
+ return addParam("userLogins", s);
+ }
+
+ public IssueQuery assignees(String... s) {
+ return addParam("assignees", s);
+ }
+
+ public IssueQuery createdAfter(Date d) {
+ params.put("createdAfter", EncodingUtils.toQueryParam(d, true));
+ return this;
+ }
+
+ public IssueQuery createdBefore(Date d) {
+ params.put("createdBefore", EncodingUtils.toQueryParam(d, true));
+ return this;
+ }
+
+ public IssueQuery limit(int limit) {
+ params.put("limit", limit);
+ return this;
+ }
+
+ public IssueQuery offset(int offset) {
+ params.put("offset", offset);
+ return this;
+ }
+
+ private IssueQuery addParam(String key, String[] values) {
+ if (values != null) {
+ params.put(key, EncodingUtils.toQueryParam(values));
+ }
+ return this;
+ }
+
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.issue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @since 3.6
+ */
+public class Issues {
+
+ private final List<Issue> list = new ArrayList<Issue>();
+
+ Issues add(Issue issue) {
+ list.add(issue);
+ return this;
+ }
+ public List<Issue> list() {
+ return list;
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.issue;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @since 3.6
+ */
+public class NewIssue {
+ static final String BASE_URL = "/api/issues/create";
+ private final Map<String, Object> params = new HashMap<String, Object>();
+
+ private NewIssue() {
+ }
+
+ public static NewIssue create() {
+ return new NewIssue();
+ }
+
+ Map<String, Object> urlParams() {
+ return params;
+ }
+
+ public NewIssue severity(String s) {
+ params.put("severity", s);
+ return this;
+ }
+
+ public NewIssue component(String s) {
+ params.put("component", s);
+ return this;
+ }
+
+ public NewIssue rule(String s) {
+ params.put("rule", s);
+ return this;
+ }
+
+ /**
+ * Optional line
+ */
+ public NewIssue line(int i) {
+ params.put("line", i);
+ return this;
+ }
+
+ public NewIssue description(String s) {
+ params.put("desc", s);
+ return this;
+ }
+
+ public NewIssue title(String s) {
+ params.put("title", s);
+ return this;
+ }
+
+ public NewIssue cost(Double d) {
+ params.put("cost", d);
+ return this;
+ }
+
+ public NewIssue attribute(String key, String value) {
+ params.put("attr[" + key + "]", value);
+ return this;
+ }
+}
--- /dev/null
+/*
+ * Sonar Runner - Implementation
+ * Copyright (C) 2011 SonarSource
+ * dev@sonar.codehaus.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.wsclient.issue;
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2011-2013 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package org.sonar.wsclient;
+
+import org.apache.commons.io.IOUtils;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import static javax.servlet.http.HttpServletResponse.SC_OK;
+import static org.apache.commons.io.IOUtils.write;
+
+public class MockHttpServer {
+ private Server server;
+ private String responseBody;
+ private int responseStatus = SC_OK;
+ private String requestBody, requestPath;
+ private Map requestHeaders = new HashMap();
+
+ public void start() throws Exception {
+ // 0 is random available port
+ server = new Server(0);
+ server.setHandler(getMockHandler());
+ server.start();
+ }
+
+ public Handler getMockHandler() {
+ Handler handler = new AbstractHandler() {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest httpServletRequest, HttpServletResponse response) throws IOException, ServletException {
+ requestPath = baseRequest.getUri().toString();
+ requestBody = IOUtils.toString(baseRequest.getInputStream());
+ requestHeaders.clear();
+ Enumeration headerNames = baseRequest.getHeaderNames();
+ while (headerNames.hasMoreElements()) {
+ String headerName = (String)headerNames.nextElement();
+ requestHeaders.put(headerName, baseRequest.getHeader(headerName));
+ }
+ response.setStatus(responseStatus);
+ response.setContentType("application/json;charset=utf-8");
+ write(responseBody, response.getOutputStream());
+ baseRequest.setHandled(true);
+ }
+ };
+ return handler;
+ }
+
+ public void stop() {
+ try {
+ if (server != null) {
+ server.stop();
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException("Fail to stop HTTP server", e);
+ }
+ }
+
+ public MockHttpServer doReturnBody(String responseBody) {
+ this.responseBody = responseBody;
+ return this;
+ }
+
+ public MockHttpServer doReturnStatus(int status) {
+ this.responseStatus = status;
+ return this;
+ }
+
+ public String requestBody() {
+ return requestBody;
+ }
+
+ public String requestPath() {
+ return requestPath;
+ }
+
+ public Map requestHeaders() {
+ return requestHeaders;
+ }
+
+ public int getPort() {
+ return server.getConnectors()[0].getLocalPort();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2011-2013 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package org.sonar.wsclient;
+
+import org.junit.rules.ExternalResource;
+
+import java.util.Map;
+
+public final class MockHttpServerInterceptor extends ExternalResource {
+
+ private MockHttpServer server;
+
+ @Override
+ protected final void before() throws Throwable {
+ server = new MockHttpServer();
+ server.start();
+ }
+
+ @Override
+ protected void after() {
+ server.stop();
+ }
+
+ public MockHttpServerInterceptor doReturnBody(String body) {
+ server.doReturnBody(body);
+ return this;
+ }
+
+ public MockHttpServerInterceptor doReturnStatus(int status) {
+ server.doReturnStatus(status);
+ return this;
+ }
+
+ public String requestedPath() {
+ return server.requestPath();
+ }
+
+ public Map requestHeaders() {
+ return server.requestHeaders();
+ }
+
+ public int port() {
+ return server.getPort();
+ }
+
+ public String url() {
+ return "http://localhost:" + port();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient;
+
+import org.junit.Test;
+import org.sonar.wsclient.issue.DefaultIssueClient;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class SonarClientTest {
+ @Test
+ public void should_build_client() {
+ SonarClient client = SonarClient.builder().url("http://localhost:9000").build();
+ assertThat(client.issueClient()).isNotNull().isInstanceOf(DefaultIssueClient.class);
+ }
+
+ @Test
+ public void url_should_not_be_null() {
+ try {
+ SonarClient.builder().build();
+ fail();
+ } catch (IllegalStateException e) {
+ assertThat(e).hasMessage("Server URL must be set");
+ }
+ }
+
+ @Test
+ public void url_should_not_be_empty() {
+ try {
+ SonarClient.builder().url("").build();
+ fail();
+ } catch (IllegalStateException e) {
+ assertThat(e).hasMessage("Server URL must be set");
+ }
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.internal;
+
+import org.junit.Test;
+
+import java.util.Date;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class EncodingUtilsTest {
+ @Test
+ public void test_date_param() {
+
+ assertThat(EncodingUtils.toQueryParam(new Date(), false)).isNotEmpty().matches("\\d{4}-\\d{2}-\\d{2}");
+ assertThat(EncodingUtils.toQueryParam(new Date(), true)).isNotEmpty();
+ }
+
+ @Test
+ public void test_string_array_param() {
+ assertThat(EncodingUtils.toQueryParam(new String[]{"foo", "bar"})).isEqualTo("foo,bar");
+ assertThat(EncodingUtils.toQueryParam(new String[]{"foo"})).isEqualTo("foo");
+ assertThat(EncodingUtils.toQueryParam(new String[]{""})).isEqualTo("");
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.internal;
+
+import com.github.kevinsawicki.http.HttpRequest;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.wsclient.MockHttpServerInterceptor;
+
+import java.util.Collections;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class HttpRequestFactoryTest {
+ @Rule
+ public MockHttpServerInterceptor httpServer = new MockHttpServerInterceptor();
+
+ @Test
+ public void test_get() {
+ httpServer.doReturnStatus(200).doReturnBody("list of issues");
+
+ HttpRequestFactory factory = new HttpRequestFactory(httpServer.url(), null, null);
+ HttpRequest request = factory.get("/api/issues", Collections.<String, Object>emptyMap());
+
+ assertThat(request.method()).isEqualTo("GET");
+ assertThat(request.body()).isEqualTo("list of issues");
+ assertThat(request.code()).isEqualTo(200);
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues");
+ }
+
+ @Test
+ public void test_post() {
+ httpServer.doReturnStatus(200);
+
+ HttpRequestFactory factory = new HttpRequestFactory(httpServer.url(), null, null);
+ HttpRequest request = factory.post("/api/issues/change", Collections.<String, Object>emptyMap());
+
+ assertThat(request.method()).isEqualTo("POST");
+ assertThat(request.code()).isEqualTo(200);
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/change");
+ }
+
+ @Test
+ public void test_authentication() {
+ httpServer.doReturnStatus(200).doReturnBody("list of issues");
+
+ HttpRequestFactory factory = new HttpRequestFactory(httpServer.url(), "karadoc", "legrascestlavie");
+ HttpRequest request = factory.get("/api/issues", Collections.<String, Object>emptyMap());
+
+ assertThat(request.body()).isEqualTo("list of issues");
+ assertThat(request.code()).isEqualTo(200);
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues");
+ assertThat(httpServer.requestHeaders().get("Authorization")).isEqualTo("Basic a2FyYWRvYzpsZWdyYXNjZXN0bGF2aWU=");
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.issue;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.wsclient.MockHttpServerInterceptor;
+import org.sonar.wsclient.internal.HttpRequestFactory;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class DefaultIssueClientTest {
+ @Rule
+ public MockHttpServerInterceptor httpServer = new MockHttpServerInterceptor();
+
+ @Test
+ public void should_find_issues() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url(), null, null);
+ httpServer.doReturnBody("{\"issues\": [{\"key\": \"ABCDE\"}]}");
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ IssueQuery query = IssueQuery.create().keys("ABCDE");
+ Issues issues = client.find(query);
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/search?keys=ABCDE");
+ assertThat(issues.list()).hasSize(1);
+ assertThat(issues.list().get(0).key()).isEqualTo("ABCDE");
+ }
+
+ @Test
+ public void should_fail_to_find_issues() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url(), null, null);
+ httpServer.doReturnStatus(500);
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ try {
+ client.find(IssueQuery.create());
+ fail();
+ } catch (IllegalStateException e) {
+ assertThat(e).hasMessage("Fail to search for issues. Bad HTTP response status: 500");
+ }
+ }
+
+ @Test
+ public void should_apply_change() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url(), null, null);
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ client.apply("ABCDE", IssueChange.create().severity("BLOCKER").comment("because!"));
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/change?newSeverity=BLOCKER&newComment=because!&key=ABCDE");
+ }
+
+ @Test
+ public void should_not_apply_empty_change() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url(), null, null);
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ client.apply("ABCDE", IssueChange.create());
+
+ assertThat(httpServer.requestedPath()).isNull();
+ }
+
+ @Test
+ public void should_create_issue() {
+ HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url(), null, null);
+
+ IssueClient client = new DefaultIssueClient(requestFactory);
+ client.create(NewIssue.create().component("Action.java").rule("squid:AvoidCycle"));
+
+ assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/create?component=Action.java&rule=squid:AvoidCycle");
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.issue;
+
+import org.junit.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.MapAssert.entry;
+
+public class IssueChangeTest {
+ @Test
+ public void should_create_empty_change() {
+ IssueChange change = IssueChange.create();
+ assertThat(change.urlParams()).isEmpty();
+ }
+
+ @Test
+ public void should_create_change() {
+ IssueChange change = IssueChange.create()
+ .comment("this is a comment")
+ .assignee("lancelot")
+ .attribute("JIRA", "FOO-1234")
+ .attribute("LINK", null)
+ .cost(4.2)
+ .resolution("FIXED")
+ .severity("BLOCKER");
+ assertThat(change.urlParams()).hasSize(7).includes(
+ entry("newComment", "this is a comment"),
+ entry("newAssignee", "lancelot"),
+ entry("newAttr[JIRA]", "FOO-1234"),
+ entry("newAttr[LINK]", ""),
+ entry("newCost", 4.2),
+ entry("newResolution", "FIXED"),
+ entry("newSeverity", "BLOCKER")
+ );
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.issue;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class IssueParserTest {
+ @Test
+ public void test_GET_search() throws Exception {
+ String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/search.json"));
+ Issues issues = new IssueParser().parseIssues(json);
+ assertThat(issues).isNotNull();
+ List<Issue> list = issues.list();
+ assertThat(list).hasSize(2);
+ Issue first = list.get(0);
+ assertThat(first.key()).isEqualTo("ABCDE");
+ assertThat(first.componentKey()).isEqualTo("Action.java");
+ assertThat(first.ruleKey()).isEqualTo("squid:AvoidCycle");
+ assertThat(first.severity()).isEqualTo("CRITICAL");
+ assertThat(first.line()).isEqualTo(10);
+ assertThat(first.resolution()).isEqualTo("FIXED");
+ assertThat(first.status()).isEqualTo("OPEN");
+ assertThat(first.assignee()).isEqualTo("karadoc");
+ assertThat(first.description()).isEqualTo("the desc");
+ assertThat(first.cost()).isEqualTo(4.2);
+ assertThat(first.title()).isEqualTo("the title");
+ assertThat(first.userLogin()).isEqualTo("perceval");
+ assertThat(first.createdAt()).isNotNull();
+ assertThat(first.updatedAt()).isNotNull();
+ assertThat(first.closedAt()).isNotNull();
+ assertThat(first.attribute("JIRA")).isEqualTo("FOO-1234");
+ assertThat(first.attribute("OTHER")).isNull();
+ assertThat(first.attributes()).hasSize(1);
+
+ Issue second = list.get(1);
+ assertThat(second.key()).isEqualTo("FGHIJ");
+ assertThat(second.line()).isNull();
+ assertThat(second.cost()).isNull();
+ assertThat(second.description()).isNull();
+ assertThat(second.attribute("JIRA")).isNull();
+ assertThat(second.attributes()).isEmpty();
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.issue;
+
+import org.junit.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.MapAssert.entry;
+
+public class IssueQueryTest {
+ @Test
+ public void get_all_issues() {
+ IssueQuery query = IssueQuery.create();
+ assertThat(query.urlParams()).isEmpty();
+ }
+
+ @Test
+ public void get_all_issues_by_parameter() {
+ IssueQuery query = IssueQuery.create()
+ .keys("ABCDE", "FGHIJ")
+ .assignees("arthur", "perceval")
+ .components("Action.java", "Filter.java")
+ .componentRoots("struts")
+ .resolutions("FIXED", "FALSE-POSITIVE")
+ .rules("squid:AvoidCycle")
+ .statuses("OPEN", "CLOSED")
+ .severities("BLOCKER", "INFO")
+ .userLogins("login1", "login2")
+ .limit(5)
+ .offset(4);
+
+ assertThat(query.urlParams()).hasSize(11);
+ assertThat(query.urlParams()).includes(entry("keys", "ABCDE,FGHIJ"));
+ assertThat(query.urlParams()).includes(entry("assignees", "arthur,perceval"));
+ assertThat(query.urlParams()).includes(entry("components", "Action.java,Filter.java"));
+ assertThat(query.urlParams()).includes(entry("componentRoots", "struts"));
+ assertThat(query.urlParams()).includes(entry("resolutions", "FIXED,FALSE-POSITIVE"));
+ assertThat(query.urlParams()).includes(entry("statuses", "OPEN,CLOSED"));
+ assertThat(query.urlParams()).includes(entry("severities", "BLOCKER,INFO"));
+ assertThat(query.urlParams()).includes(entry("userLogins", "login1,login2"));
+ assertThat(query.urlParams()).includes(entry("limit", 5));
+ assertThat(query.urlParams()).includes(entry("offset", 4));
+ }
+
+ @Test
+ public void should_ignore_null_values() {
+ IssueQuery query = IssueQuery.create().severities(null);
+ assertThat(query.urlParams()).isEmpty();
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.wsclient.issue;
+
+import org.junit.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.MapAssert.entry;
+
+public class NewIssueTest {
+ @Test
+ public void test_create_empty() {
+ assertThat(NewIssue.create().urlParams()).isEmpty();
+ }
+
+ @Test
+ public void test_create() {
+ NewIssue newIssue = NewIssue.create()
+ .component("Action.java")
+ .cost(4.2)
+ .description("the desc")
+ .line(123)
+ .rule("squid:AvoidCycle")
+ .severity("BLOCKER")
+ .title("the title")
+ .attribute("JIRA", "FOO-123");
+
+ assertThat(newIssue.urlParams()).hasSize(8).includes(
+ entry("component", "Action.java"),
+ entry("cost", 4.2),
+ entry("desc", "the desc"),
+ entry("line", 123),
+ entry("rule", "squid:AvoidCycle"),
+ entry("severity", "BLOCKER"),
+ entry("title", "the title"),
+ entry("attr[JIRA]", "FOO-123")
+ );
+ }
+}
--- /dev/null
+{
+ "issues": [
+ {
+ "key": "ABCDE",
+ "component": "Action.java",
+ "rule": "squid:AvoidCycle",
+ "severity": "CRITICAL",
+ "line": 10,
+ "resolution": "FIXED",
+ "status": "OPEN",
+ "assignee": "karadoc",
+ "cost": 4.2,
+ "desc": "the desc",
+ "title": "the title",
+ "userLogin": "perceval",
+ "createdAt": "2013-05-18T12:45:34+0200",
+ "updatedAt": "2013-05-18T13:45:34+0200",
+ "closedAt": "2013-05-18T14:45:34+0200",
+ "attr": {
+ "JIRA": "FOO-1234"
+ }
+ },
+ {
+ "key": "FGHIJ",
+ "component": "Filter.java",
+ "rule": "squid:NullRef",
+ "severity": "BLOCKER",
+ "resolution": "FIXED",
+ "status": "OPEN"
+ }
+ ]
+}
\ No newline at end of file