| // Copyright (C) 2015 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package com.googlesource.gerrit.plugins.importer; |
| |
| import static com.google.gerrit.extensions.restapi.Url.encode; |
| |
| import com.google.common.collect.Iterables; |
| import com.google.gerrit.extensions.client.ListChangesOption; |
| import com.google.gerrit.extensions.common.ChangeInfo; |
| import com.google.gerrit.extensions.common.CommentInfo; |
| import com.google.gerrit.extensions.common.GroupInfo; |
| import com.google.gerrit.extensions.common.ProjectInfo; |
| import com.google.gerrit.extensions.common.RevisionInfo; |
| import com.google.gerrit.extensions.common.SshKeyInfo; |
| import com.google.gerrit.extensions.restapi.BadRequestException; |
| import com.google.gerrit.server.OutputFormat; |
| import com.google.gson.Gson; |
| import com.google.gson.reflect.TypeToken; |
| import java.io.IOException; |
| import java.net.UnknownHostException; |
| import java.util.EnumSet; |
| import java.util.List; |
| import java.util.Map; |
| import org.apache.http.HttpStatus; |
| |
| class RemoteApi implements GerritApi { |
| |
| private final RestSession restSession; |
| |
| RemoteApi(String url, String user, String pass) { |
| restSession = new RestSession(url, user, pass); |
| } |
| |
| @Override |
| public ProjectInfo getProject(String projectName) throws IOException, BadRequestException { |
| projectName = encode(projectName); |
| String endPoint = "/projects/" + projectName; |
| try (RestResponse r = checkedGet(endPoint)) { |
| return newGson().fromJson(r.getReader(), new TypeToken<ProjectInfo>() {}.getType()); |
| } |
| } |
| |
| @Override |
| public List<ChangeInfo> queryChanges(String projectName, int start, int limit) |
| throws IOException, BadRequestException { |
| String endPoint = |
| "/changes/?S=" |
| + start |
| + ((limit > 0) ? "&n=" + limit : "") |
| + "&q=project:" |
| + projectName |
| + "&O=" |
| + Integer.toHexString( |
| ListChangesOption.toBits( |
| EnumSet.of( |
| ListChangesOption.DETAILED_LABELS, |
| ListChangesOption.DETAILED_ACCOUNTS, |
| ListChangesOption.MESSAGES, |
| ListChangesOption.CURRENT_REVISION, |
| ListChangesOption.ALL_REVISIONS, |
| ListChangesOption.ALL_COMMITS))); |
| |
| List<ChangeInfo> result; |
| try (RestResponse r = checkedGet(endPoint)) { |
| result = newGson().fromJson(r.getReader(), new TypeToken<List<ChangeInfo>>() {}.getType()); |
| } |
| |
| for (ChangeInfo c : result) { |
| for (Map.Entry<String, RevisionInfo> e : c.revisions.entrySet()) { |
| e.getValue().commit.commit = e.getKey(); |
| } |
| } |
| |
| return result; |
| } |
| |
| @Override |
| public GroupInfo getGroup(String groupName) throws IOException, BadRequestException { |
| groupName = encode(groupName); |
| String endPoint = "/groups/" + groupName + "/detail"; |
| try (RestResponse r = checkedGet(endPoint)) { |
| return newGson().fromJson(r.getReader(), new TypeToken<GroupInfo>() {}.getType()); |
| } |
| } |
| |
| @Override |
| public Iterable<CommentInfo> getComments(int changeId, String rev) |
| throws IOException, BadRequestException { |
| String endPoint = "/changes/" + changeId + "/revisions/" + rev + "/comments"; |
| Map<String, List<CommentInfo>> result; |
| try (RestResponse r = restSession.get(endPoint)) { |
| if (r.getStatusCode() == HttpStatus.SC_NOT_FOUND) { |
| return null; |
| } |
| assertOK(HttpMethod.GET, endPoint, r); |
| result = |
| newGson() |
| .fromJson( |
| r.getReader(), new TypeToken<Map<String, List<CommentInfo>>>() {}.getType()); |
| } |
| for (Map.Entry<String, List<CommentInfo>> e : result.entrySet()) { |
| for (CommentInfo i : e.getValue()) { |
| i.path = e.getKey(); |
| } |
| } |
| return Iterables.concat(result.values()); |
| } |
| |
| @Override |
| public List<SshKeyInfo> getSshKeys(String userId) throws BadRequestException, IOException { |
| String endPoint = "/accounts/" + userId + "/sshkeys/"; |
| try (RestResponse r = checkedGet(endPoint)) { |
| return newGson().fromJson(r.getReader(), new TypeToken<List<SshKeyInfo>>() {}.getType()); |
| } |
| } |
| |
| @Override |
| public Version getVersion() throws BadRequestException, IOException { |
| String endPoint = "/config/server/version"; |
| try (RestResponse r = checkedGet(endPoint)) { |
| return new Version( |
| (String) newGson().fromJson(r.getReader(), new TypeToken<String>() {}.getType())); |
| } |
| } |
| |
| private static Gson newGson() { |
| return OutputFormat.JSON_COMPACT.newGson(); |
| } |
| |
| private RestResponse checkedGet(String endPoint) throws IOException, BadRequestException { |
| try { |
| RestResponse r = restSession.get(endPoint); |
| assertOK(HttpMethod.GET, endPoint, r); |
| return r; |
| } catch (UnknownHostException e) { |
| throw new BadRequestException("Unknown host: " + e.getMessage()); |
| } |
| } |
| |
| private static void assertOK(HttpMethod method, String endPoint, RestResponse r) |
| throws IOException, BadRequestException { |
| if (r.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { |
| throw new BadRequestException( |
| "invalid credentials: accessing source system failed with 401 Unauthorized"); |
| } |
| if (r.getStatusCode() == HttpStatus.SC_NOT_FOUND) { |
| throw new BadRequestException( |
| String.format( |
| "missing permissions or invalid import entity identifier: Accessing " |
| + "REST endpoint %s on source system failed with 404 Not found", |
| endPoint)); |
| } |
| |
| if (r.getStatusCode() < 200 || 300 <= r.getStatusCode()) { |
| throw new IOException( |
| String.format( |
| "Unexpected response code for %s on %s : %s", |
| method.name(), endPoint, r.getStatusCode())); |
| } |
| } |
| |
| private static enum HttpMethod { |
| GET |
| } |
| } |