]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-4323 add Java client to WS /api/users/search
authorSimon Brandhof <simon.brandhof@gmail.com>
Mon, 13 May 2013 15:16:09 +0000 (17:16 +0200)
committerSimon Brandhof <simon.brandhof@gmail.com>
Mon, 13 May 2013 15:17:36 +0000 (17:17 +0200)
sonar-plugin-api/src/main/java/org/sonar/api/user/RubyUserService.java
sonar-server/src/main/java/org/sonar/server/user/DefaultRubyUserService.java
sonar-server/src/main/webapp/WEB-INF/app/models/action_plan.rb
sonar-ws-client/src/main/java/org/sonar/wsclient/SonarClient.java
sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java
sonar-ws-client/src/main/java/org/sonar/wsclient/user/DefaultUserClient.java [new file with mode: 0644]
sonar-ws-client/src/main/java/org/sonar/wsclient/user/UserClient.java [new file with mode: 0644]
sonar-ws-client/src/main/java/org/sonar/wsclient/user/UserQuery.java [new file with mode: 0644]
sonar-ws-client/src/test/java/org/sonar/wsclient/SonarClientTest.java
sonar-ws-client/src/test/java/org/sonar/wsclient/user/DefaultUserClientTest.java [new file with mode: 0644]

index 5247f6b1efa45aecff7c5ce82c9115b55185530c..a1e7180a4531b22dbf9b19d73905e0bf753b2953 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.api.user;
 
 import org.sonar.api.ServerComponent;
 
+import javax.annotation.CheckForNull;
 import java.util.List;
 import java.util.Map;
 
@@ -29,6 +30,9 @@ import java.util.Map;
  */
 public interface RubyUserService extends ServerComponent {
 
+  @CheckForNull
+  User findByLogin(String login);
+
   /**
    * Search for users
    * <p/>
index 96905d535d67867c8f89ecf9ff27a33f17c8e124..db042c5a8d5ea30fbff63c6eb4a385835a115456 100644 (file)
@@ -35,6 +35,11 @@ public class DefaultRubyUserService implements RubyUserService {
     this.finder = finder;
   }
 
+  @Override
+  public User findByLogin(String login) {
+    return finder.findByLogin(login);
+  }
+
   @Override
   public List<User> find(Map<String, Object> params) {
     UserQuery query = parseQuery(params);
@@ -43,7 +48,7 @@ public class DefaultRubyUserService implements RubyUserService {
 
   private UserQuery parseQuery(Map<String, Object> params) {
     UserQuery.Builder builder = UserQuery.builder();
-    if (RubyUtils.toBoolean(params.get("includeDeactivated"))==Boolean.TRUE) {
+    if (RubyUtils.toBoolean(params.get("includeDeactivated")) == Boolean.TRUE) {
       builder.includeDeactivated();
     }
     builder.logins(RubyUtils.toStrings(params.get("logins")));
index 5f64e06db3e3e462c5f7abdf1e951cbc2d1c2721..52dc70752345153d2a59ce30b7a8e8cf8349a351 100644 (file)
@@ -77,13 +77,14 @@ class ActionPlan < ActiveRecord::Base
     deadline ? status==STATUS_OPEN && deadline.past? : false
   end
 
-  def self.to_hash(action_plan)
-    hash = {:key => action_plan.key(), :name => action_plan.name(), :status => action_plan.status()}
-    hash[:desc] = action_plan.description() if action_plan.description() && !action_plan.description().blank?
-    hash[:userLogin] = action_plan.userLogin() if action_plan.userLogin()
-    hash[:deadLine] = Api::Utils.format_datetime(action_plan.deadLine()) if action_plan.deadLine()
-    hash[:creationDate] = Api::Utils.format_datetime(action_plan.creationDate()) if action_plan.creationDate()
-    hash[:updateDate] = Api::Utils.format_datetime(action_plan.updateDate()) if action_plan.updateDate()
+  # since 3.6
+  def self.to_hash(java_action_plan)
+    hash = {:key => java_action_plan.key(), :name => java_action_plan.name(), :status => java_action_plan.status()}
+    hash[:desc] = java_action_plan.description() if java_action_plan.description() && !java_action_plan.description().blank?
+    hash[:userLogin] = java_action_plan.userLogin() if java_action_plan.userLogin()
+    hash[:deadLine] = Api::Utils.format_datetime(java_action_plan.deadLine()) if java_action_plan.deadLine()
+    hash[:createdAt] = Api::Utils.format_datetime(java_action_plan.createdAt()) if java_action_plan.createdAt()
+    hash[:updatedAt] = Api::Utils.format_datetime(java_action_plan.updatedAt()) if java_action_plan.updatedAt()
     hash
   end
 
index e84e75c77806d46551194aba0223d22d9f42f7f8..b8ee9cdd5f10543d6d0d5e5add6e3a8a08d03654 100644 (file)
@@ -22,6 +22,8 @@ package org.sonar.wsclient;
 import org.sonar.wsclient.internal.HttpRequestFactory;
 import org.sonar.wsclient.issue.DefaultIssueClient;
 import org.sonar.wsclient.issue.IssueClient;
+import org.sonar.wsclient.user.DefaultUserClient;
+import org.sonar.wsclient.user.UserClient;
 
 /**
  * @since 3.6
@@ -38,6 +40,10 @@ public class SonarClient {
     return new DefaultIssueClient(requestFactory);
   }
 
+  public UserClient userClient() {
+    return new DefaultUserClient(requestFactory);
+  }
+
   public static Builder builder() {
     return new Builder();
   }
index 3a1036f18cd5a427e710720c4eb067137e24ead9..3fe7ed6a18c4243762638e4af2b708154081fb13 100644 (file)
@@ -127,6 +127,8 @@ public class IssueQuery {
   private IssueQuery addParam(String key, String[] values) {
     if (values != null) {
       params.put(key, EncodingUtils.toQueryParam(values));
+    } else {
+      params.remove(key);
     }
     return this;
   }
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/user/DefaultUserClient.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/user/DefaultUserClient.java
new file mode 100644 (file)
index 0000000..fd842df
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+package org.sonar.wsclient.user;
+
+import com.github.kevinsawicki.http.HttpRequest;
+import org.json.simple.JSONValue;
+import org.sonar.wsclient.internal.HttpRequestFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Do not instantiate this class, but use {@link org.sonar.wsclient.SonarClient#userClient()}.
+ */
+public class DefaultUserClient implements UserClient {
+
+  private final HttpRequestFactory requestFactory;
+
+  /**
+   * For internal use. Use {@link org.sonar.wsclient.SonarClient} to get an instance.
+   */
+  public DefaultUserClient(HttpRequestFactory requestFactory) {
+    this.requestFactory = requestFactory;
+  }
+
+  @Override
+  public List<User> find(UserQuery query) {
+    HttpRequest request = requestFactory.get(UserQuery.BASE_URL, query.urlParams());
+    if (!request.ok()) {
+      throw new IllegalStateException("Fail to search for users. Bad HTTP response status: " + request.code());
+    }
+    List<User> result = new ArrayList<User>();
+    String json = request.body("UTF-8");
+    Map jsonRoot = (Map) JSONValue.parse(json);
+    List<Map> jsonUsers = (List) jsonRoot.get("users");
+    if (jsonUsers != null) {
+      for (Map jsonUser : jsonUsers) {
+        result.add(new User(jsonUser));
+      }
+    }
+    return result;
+  }
+
+}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/user/UserClient.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/user/UserClient.java
new file mode 100644 (file)
index 0000000..d3893f8
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+package org.sonar.wsclient.user;
+
+import java.util.List;
+
+/**
+ * @since 3.6
+ */
+public interface UserClient {
+
+  List<User> find(UserQuery query);
+
+}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/user/UserQuery.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/user/UserQuery.java
new file mode 100644 (file)
index 0000000..b148e1a
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.sonar.wsclient.user;
+
+import org.sonar.wsclient.internal.EncodingUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @since 3.6
+ */
+public class UserQuery {
+  static final String BASE_URL = "/api/users/search";
+
+  private final Map<String, Object> params = new HashMap<String, Object>();
+
+  private UserQuery() {
+  }
+
+  public static UserQuery create() {
+    return new UserQuery();
+  }
+
+  public UserQuery includeDeactivated() {
+    params.put("includeDeactivated", "true");
+    return this;
+  }
+
+  public UserQuery logins(String... s) {
+    if (s != null) {
+      params.put("logins", EncodingUtils.toQueryParam(s));
+    } else {
+      params.remove("logins");
+    }
+    return this;
+  }
+
+  Map<String, Object> urlParams() {
+    return params;
+  }
+}
index eb50d795426ae9f3b29bc8d5c06c7fa2afe01dc2..03ae927b15dd34d2188cd4ed43d6024a70312a8c 100644 (file)
@@ -21,15 +21,17 @@ package org.sonar.wsclient;
 
 import org.junit.Test;
 import org.sonar.wsclient.issue.DefaultIssueClient;
+import org.sonar.wsclient.user.DefaultUserClient;
 
 import static org.fest.assertions.Assertions.assertThat;
 import static org.fest.assertions.Fail.fail;
 
 public class SonarClientTest {
   @Test
-  public void should_build_client() {
+  public void should_build_clients() {
     SonarClient client = SonarClient.builder().url("http://localhost:9000").build();
     assertThat(client.issueClient()).isNotNull().isInstanceOf(DefaultIssueClient.class);
+    assertThat(client.userClient()).isNotNull().isInstanceOf(DefaultUserClient.class);
   }
 
   @Test
diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/user/DefaultUserClientTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/user/DefaultUserClientTest.java
new file mode 100644 (file)
index 0000000..795edf4
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.sonar.wsclient.user;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.wsclient.MockHttpServerInterceptor;
+import org.sonar.wsclient.internal.HttpRequestFactory;
+
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class DefaultUserClientTest {
+  @Rule
+  public MockHttpServerInterceptor httpServer = new MockHttpServerInterceptor();
+
+  @Test
+  public void should_find_issues() {
+    HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url(), null, null);
+    httpServer.doReturnBody("{\"users\": [{\"login\": \"simon\", \"name\": \"Simon\", \"active\": true}]}");
+
+    UserClient client = new DefaultUserClient(requestFactory);
+    UserQuery query = UserQuery.create().logins("simon", "loic");
+    List<User> users = client.find(query);
+
+    assertThat(httpServer.requestedPath()).isEqualTo("/api/users/search?logins=simon,loic");
+    assertThat(users).hasSize(1);
+    User simon = users.get(0);
+    assertThat(simon.login()).isEqualTo("simon");
+    assertThat(simon.name()).isEqualTo("Simon");
+    assertThat(simon.active()).isTrue();
+  }
+}