/*********************************************************************
 * Copyright (c) 2010, 2013 Sony Ericsson/ST Ericsson and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 *  Contributors:
 *      Sony Ericsson/ST Ericsson - initial API and implementation
 *      Tasktop Technologies - improvements
 *      Sascha Scholz (SAP) - improvements
 *      GitHub, Inc. - fixes for bug 354753
 *      Christian Trutz - improvements
 *      Francois Chouinard - Added "LABELS" option on selected queries
 *      Jacques Bouthillier - Bug 414253 Add support for Gerrit Dashboard
 *      Jacques Bouthillier (Ericsson) - Bug 426505 Add Starred functionality
 *      Guy Perron (Ericsson) Bug 423242 Add ability to edit comment from compare navigator popup
 *      Guy Perron/Jacques Bouthillier Bug 437825  support Gerrit 2.9 with API changes
 *********************************************************************/
package org.eclipse.mylyn.internal.gerrit.core.client;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipInputStream;

import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.util.URIUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.commons.net.AbstractWebLocation;
import org.eclipse.mylyn.commons.net.WebUtil;
import org.eclipse.mylyn.internal.gerrit.core.GerritCorePlugin;
import org.eclipse.mylyn.internal.gerrit.core.GerritUtil;
import org.eclipse.mylyn.internal.gerrit.core.client.GerritHttpClient.ErrorHandler;
import org.eclipse.mylyn.internal.gerrit.core.client.GerritHttpClient.Request;
import org.eclipse.mylyn.internal.gerrit.core.client.GerritService.GerritRequest;
import org.eclipse.mylyn.internal.gerrit.core.client.compat.ChangeDetailService;
import org.eclipse.mylyn.internal.gerrit.core.client.compat.ChangeDetailX;
import org.eclipse.mylyn.internal.gerrit.core.client.compat.ChangeManageService;
import org.eclipse.mylyn.internal.gerrit.core.client.compat.GerritConfigX;
import org.eclipse.mylyn.internal.gerrit.core.client.compat.GerritSystemAccount;
import org.eclipse.mylyn.internal.gerrit.core.client.compat.PatchDetailService;
import org.eclipse.mylyn.internal.gerrit.core.client.compat.PatchScriptX;
import org.eclipse.mylyn.internal.gerrit.core.client.compat.PatchSetPublishDetailX;
import org.eclipse.mylyn.internal.gerrit.core.client.compat.ProjectAdminService;
import org.eclipse.mylyn.internal.gerrit.core.client.compat.ProjectDetailX;
import org.eclipse.mylyn.internal.gerrit.core.client.compat.SubmitRecord;
import org.eclipse.mylyn.internal.gerrit.core.client.data.GerritQueryResult;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.AbandonInput;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.ActionInfo;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.AddReviewerResult;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.ChangeInfo;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.ChangeInfo29;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.ChangeMessageInfo;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.CommentInfo;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.CommentInput;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.ProjectInfo;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.RelatedChangeAndCommitInfo;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.RelatedChangesInfo;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.RestoreInput;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.ReviewInfo;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.ReviewInput;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.ReviewerInfo;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.ReviewerInput;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.RevisionInfo;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.SubmitInfo;
import org.eclipse.mylyn.internal.gerrit.core.client.rest.SubmitInput;
import org.eclipse.mylyn.internal.gerrit.core.remote.GerritRemoteFactoryProvider;
import org.eclipse.mylyn.reviews.core.model.IRepository;
import org.eclipse.mylyn.reviews.core.model.IReview;
import org.eclipse.mylyn.reviews.core.spi.ReviewsClient;
import org.eclipse.mylyn.reviews.core.spi.remote.emf.AbstractRemoteEmfFactoryProvider;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Version;

import com.google.gerrit.common.data.AccountDashboardInfo;
import com.google.gerrit.common.data.AccountInfo;
import com.google.gerrit.common.data.AccountInfoCache;
import com.google.gerrit.common.data.AccountService;
import com.google.gerrit.common.data.ApprovalDetail;
import com.google.gerrit.common.data.ChangeDetail;
import com.google.gerrit.common.data.ChangeListService;
import com.google.gerrit.common.data.GerritConfig;
import com.google.gerrit.common.data.PatchSetDetail;
import com.google.gerrit.common.data.ReviewerResult;
import com.google.gerrit.common.data.SingleListChangeInfo;
import com.google.gerrit.common.data.ToggleStarRequest;
import com.google.gerrit.reviewdb.Account;
import com.google.gerrit.reviewdb.AccountDiffPreference;
import com.google.gerrit.reviewdb.AccountDiffPreference.Whitespace;
import com.google.gerrit.reviewdb.ApprovalCategoryValue;
import com.google.gerrit.reviewdb.Branch;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.ChangeMessage;
import com.google.gerrit.reviewdb.ContributorAgreement;
import com.google.gerrit.reviewdb.Patch;
import com.google.gerrit.reviewdb.Patch.ChangeType;
import com.google.gerrit.reviewdb.PatchLineComment;
import com.google.gerrit.reviewdb.PatchSet;
import com.google.gerrit.reviewdb.PatchSet.Id;
import com.google.gerrit.reviewdb.PatchSetInfo;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.Project.NameKey;
import com.google.gerrit.reviewdb.UserIdentity;
import com.google.gson.reflect.TypeToken;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwtjsonrpc.client.RemoteJsonService;
import com.google.gwtjsonrpc.client.VoidResult;

/**
 * Facade to the Gerrit RPC API.
 * 
 * @author Mikael Kober
 * @author Thomas Westling
 * @author Steffen Pingel
 * @author Christian Trutz
 * @author Sascha Scholz
 * @author Miles Parker
 * @author Francois Chouinard
 * @author Jacques Bouthillier
 * @author Guy Perron
 */
public class GerritClient extends ReviewsClient {

	private static final Pattern GERRIT_VERSION_PATTERN = Pattern.compile("Powered by Gerrit Code Review (.+)</p>"); //$NON-NLS-1$

	private static final String GET_LABELS_OPTION = "LABELS"; //$NON-NLS-1$

	private final String NOT_SIGNED_IN = "Not Signed In"; //$NON-NLS-1$

	private final String OK = "OK"; //$NON-NLS-1$

	private final String NEED = "NEED"; //$NON-NLS-1$

	private final String REJECT = "REJECT"; //$NON-NLS-1$

	final String MAY = "MAY"; //$NON-NLS-1$

	private abstract class Operation<T> implements AsyncCallback<T> {

		private Throwable exception;

		private T result;

		public abstract void execute(IProgressMonitor monitor) throws GerritException;

		public Throwable getException() {
			return exception;
		}

		public T getResult() {
			return result;
		}

		public void onFailure(Throwable exception) {
			if (isAuthenticationException(exception)) {
				// invalidate login cookie to force re-authentication
				client.setXsrfCookie(null);
			}
			this.exception = exception;
		}

		public void onSuccess(T result) {
			setResult(result);
		}

		protected void setResult(T result) {
			this.result = result;
		}

		public void reset() {
			this.result = null;
			this.exception = null;
		}

	}

	public boolean isAuthenticationException(Throwable exception) {
		if (exception instanceof GerritException) {
			return ((GerritException) exception).getCode() == -32603
					&& "Invalid xsrfKey in request".equals(((GerritException) exception).getMessage()); //$NON-NLS-1$
		}
		return false;
	}

	public boolean isNotSignedInException(Throwable exception) {
		if (exception instanceof GerritException) {
			return ((GerritException) exception).getCode() == -32603
					&& NOT_SIGNED_IN.equalsIgnoreCase(((GerritException) exception).getMessage());
		}
		return false;
	}

	// XXX belongs in GerritConnector
	public static GerritAuthenticationState authStateFromString(String token) {
		try {
			JSonSupport support = new JSonSupport();
			return support.parseResponse(token, GerritAuthenticationState.class);
		} catch (Exception e) {
			// ignore
			return null;
		}
	}

	// XXX belongs in GerritConnector
	public static String authStateToString(GerritAuthenticationState authState) {
		if (authState == null) {
			return null;
		}
		try {
			JSonSupport support = new JSonSupport();
			return support.toJson(authState);
		} catch (Exception e) {
			// ignore
			return null;
		}
	}

	private final GerritHttpClient client;

	private volatile GerritConfiguration config;

	private Account myAcount;

	private Version myVersion;

	private final Map<Class<? extends RemoteJsonService>, RemoteJsonService> serviceByClass;

	private volatile boolean configRefreshed;

	/**
	 * The GWT query API was removed in Gerrit 2.5 and replaced with a REST API. If this flag is true, the REST API is
	 * used.
	 */
	private boolean restQueryAPIEnabled;

	public GerritClient(TaskRepository repository, AbstractWebLocation location) {
		this(repository, location, null, null, null);
	}

	public GerritClient(TaskRepository repository, AbstractWebLocation location, GerritConfiguration config,
			GerritAuthenticationState authState) {
		this(repository, location, config, authState, null);
	}

	public GerritClient(TaskRepository repository, AbstractWebLocation location, GerritConfiguration config,
			GerritAuthenticationState authState, String xsrfKey) {
		super(repository);
		this.client = new GerritHttpClient(location) {
			@Override
			protected void sessionChanged(Cookie cookie) {
				GerritAuthenticationState authState = new GerritAuthenticationState();
				authState.setCookie(cookie);
				authStateChanged(authState);
			}
		};
		if (authState != null) {
			client.setXsrfCookie(authState.getCookie());
		}
		if (xsrfKey != null) {
			client.setXsrfKey(xsrfKey);
		}
		this.serviceByClass = new HashMap<Class<? extends RemoteJsonService>, RemoteJsonService>();
		this.config = config;
	}

	public PatchLineComment saveDraft(Patch.Key patchKey, String message, int line, short side, String parentUuid,
			String uuid, IProgressMonitor monitor) throws GerritException {
		PatchLineComment.Key id = new PatchLineComment.Key(patchKey, uuid);
		final PatchLineComment comment = new PatchLineComment(id, line, getAccount(monitor).getId(), parentUuid);
		comment.setMessage(message);
		comment.setSide(side);
		if (isVersion29OrLater(monitor)) {
			if (uuid == null) {
				uuid = ""; //$NON-NLS-1$
			}
			CommentInput commentInput = new CommentInput();
			commentInput.setLine(line);
			commentInput.setMessage(message);
			commentInput.setPath(patchKey.getFileName());
			if (side == 0) {
				commentInput.setSide("PARENT"); //$NON-NLS-1$
			} else {
				commentInput.setSide("REVISION"); //$NON-NLS-1$
			}

			String uri = "/changes/" + Integer.toString(patchKey.getParentKey().getParentKey().get()) //$NON-NLS-1$
					+ "/revisions/" + patchKey.getParentKey().get() + "/drafts"; //$NON-NLS-1$ //$NON-NLS-2$
			if (!uuid.isEmpty()) {
				uri = uri.concat("/" + uuid); //$NON-NLS-1$
			}

			executePutRestRequest(uri, commentInput, CommentInput.class, null/*no error handler*/, monitor);

			return comment;
		} else {
			return execute(monitor, new Operation<PatchLineComment>() {
				@Override
				public void execute(IProgressMonitor monitor) throws GerritException {
					getPatchDetailService(monitor).saveDraft(comment, this);
				}
			});
		}
	}

	public VoidResult deleteDraft(Patch.Key patchkey, String uuid, IProgressMonitor monitor) throws GerritException {
		final PatchLineComment.Key id = new PatchLineComment.Key(patchkey, uuid);
		if (isVersion29OrLater(monitor)) {
			CommentInput commentInput = new CommentInput();
			String uri = "/changes/" + Integer.toString(patchkey.getParentKey().getParentKey().get()) //$NON-NLS-1$
					+ "/revisions/" + patchkey.getParentKey().get() + "/drafts/" + uuid; //$NON-NLS-1$ //$NON-NLS-2$

			executeDeleteRestRequest(uri, commentInput, CommentInput.class, null/*no error handler*/, monitor);
			return null;
		} else {
			return execute(monitor, new Operation<VoidResult>() {
				@Override
				public void execute(IProgressMonitor monitor) throws GerritException {
					getPatchDetailService(monitor).deleteDraft(id, this);
				}
			});
		}
	}

	public ChangeDetail abandon(String reviewId, int patchSetId, final String message, IProgressMonitor monitor)
			throws GerritException {
		final PatchSet.Id id = new PatchSet.Id(new Change.Id(id(reviewId)), patchSetId);
		if (hasJsonRpcApi(monitor)) {
			return execute(monitor, new Operation<ChangeDetail>() {
				@Override
				public void execute(IProgressMonitor monitor) throws GerritException {
					getChangeManageService(monitor).abandonChange(id, message, this);
				}
			});
		} else {
			final String uri = "/a/changes/" + id.getParentKey().get() + "/abandon"; //$NON-NLS-1$ //$NON-NLS-2$
			executePostRestRequest(uri, new AbandonInput(message), ChangeInfo.class, null/*no error handler*/, monitor);
			return getChangeDetail(id.getParentKey().get(), monitor);
		}
	}

	public Object getChangeInfo29(String query, Class returnClass, IProgressMonitor monitor) throws GerritException {
		return executeGetRestRequest(query, returnClass, monitor);
	}

	private List<PatchSet> getPatchSets29(final String changeInfoId, int reviewId, IProgressMonitor monitor)
			throws GerritException {

		List<PatchSet> patchSets = new ArrayList<PatchSet>();
		String query = "/changes/?q=" + changeInfoId + "+change:" + reviewId + "&o=ALL_REVISIONS"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		ChangeInfo29[] changeInfo = (ChangeInfo29[]) getChangeInfo29(query, ChangeInfo29[].class, monitor);

		for (ChangeInfo element : changeInfo) {
			for (Entry<String, RevisionInfo> revisionInfo : element.getRevisions().entrySet()) {
				PatchSet.Id patchSetId = new PatchSet.Id(new Change.Id(reviewId), revisionInfo.getValue().getNumber());
				patchSets.add(new PatchSet(patchSetId));
			}

		}
		Collections.sort(patchSets, new Comparator<PatchSet>() {

			@Override
			public int compare(PatchSet p1, PatchSet p2) {
				return p1.getPatchSetId() - p2.getPatchSetId();
			}

		});
		return patchSets;
	}

	public RelatedChangesInfo getRelatedChanges(final int reviewId, String revisionId, IProgressMonitor monitor)
			throws GerritException {
		String query = "/changes/" + Integer.toString(reviewId) + "/revisions/" + revisionId + "/related"; //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
		RelatedChangesInfo relatedChangesInfo = (RelatedChangesInfo) getChangeInfo29(query, RelatedChangesInfo.class,
				monitor);
		return relatedChangesInfo;
	}

	private ChangeMessage convertChangeMessage(int reviewId, ChangeInfo changeInfo, ChangeMessageInfo changeMessageInfo) {
		Change.Id changeId = new Change.Id(reviewId);
		ChangeMessage.Key changeMessageKey = new ChangeMessage.Key(changeId, changeInfo.getId());
		org.eclipse.mylyn.internal.gerrit.core.client.rest.AccountInfo author = changeMessageInfo.getAuthor();
		if (author == null) {
			//if Author is not set, the ChangeMessageInfo was created by the Gerrit system
			author = GerritSystemAccount.GERRIT_SYSTEM;
		}
		Account.Id accountId = new Account.Id(author.getId());
		ChangeMessage changeMessage = new ChangeMessage(changeMessageKey, accountId, changeMessageInfo.getDate());
		changeMessage.setMessage(changeMessageInfo.getMesssage());
		return changeMessage;
	}

	private Branch.NameKey getBranchKey(ChangeInfo changeInfo) {
		Project.NameKey projectKey = new Project.NameKey(changeInfo.getProject());
		Branch.NameKey branchKey = new Branch.NameKey(projectKey, changeInfo.getBranch());
		return branchKey;
	}

	private Change createChange(String keyString, int changeIdValue, AccountInfo accountInfo, Branch.NameKey branchKey) {
		Change.Key key = new Change.Key(keyString);
		Change.Id changeId = new Change.Id(changeIdValue);
		Change change = new Change(key, changeId, accountInfo.getId(), branchKey);
		return change;
	}

	private PatchSetInfo getPatchSetInfo(PatchSet.Id patchsetId, String subject) {
		PatchSetInfo patchSetInfo = new PatchSetInfo(patchsetId);
		patchSetInfo.setSubject(subject);
		return patchSetInfo;
	}

	private com.google.gerrit.common.data.ChangeInfo convertToGoogleChangeInfo(RelatedChangeAndCommitInfo info,
			AccountInfo accountInfo, Branch.NameKey branchKey) {

		Change change = createChange(info.getChangeId(), info.getChangeNumber(), accountInfo, branchKey);
		PatchSet.Id patchsetId = new PatchSet.Id(change.getId(), info.getCurrentRevisionNumbe());

		PatchSetInfo patchSetInfo = getPatchSetInfo(patchsetId, info.getCommitInfo().getSubject());
		change.setCurrentPatchSet(patchSetInfo);
		com.google.gerrit.common.data.ChangeInfo googleChangeInfo = new com.google.gerrit.common.data.ChangeInfo(change);

		return googleChangeInfo;
	}

	public ChangeDetailX getChangeDetail29(int reviewId, IProgressMonitor monitor) throws GerritException {
		ChangeDetailX changeDetail = null;
		String query = "/changes/" + Integer.toString(reviewId) + "/detail/?o=ALL_REVISIONS&o=MESSAGES"; //$NON-NLS-1$//$NON-NLS-2$
		ChangeInfo29 changeInfo = (ChangeInfo29) getChangeInfo29(query, ChangeInfo29.class, monitor);

		List<PatchSet> patchSets = getPatchSets29(changeInfo.getChangeId(), reviewId, monitor);

		List<ChangeMessage> listChangeMessage = new ArrayList<ChangeMessage>();
		List<ChangeMessageInfo> listChangeMessageInfo = changeInfo.getMessages();

		boolean containsMessageFromGerritSystem = false;
		for (ChangeMessageInfo changeMessageInfo : listChangeMessageInfo) {

			if (changeMessageInfo.getAuthor() == null) {
				//if Author is not set, the ChangeMessageInfo was created by the Gerrit system
				containsMessageFromGerritSystem = true;
			}
			ChangeMessage changeMessage = convertChangeMessage(reviewId, changeInfo, changeMessageInfo);
			listChangeMessage.add(changeMessage);
		}

		List<AccountInfo> listAccountInfo = new ArrayList<AccountInfo>();

		AccountInfo accountInfo = convertAuthorFrom29ToAccountInfo(changeInfo);
		listAccountInfo.add(accountInfo);

		if (containsMessageFromGerritSystem) {
			//add Gerrit system if there was a ChangeMessageInfo that was created by the Gerrit system
			listAccountInfo.add(org.eclipse.mylyn.internal.gerrit.core.client.compat.GerritSystemAccount.GERRIT_SYSTEM.getGerritSystemAccountInfo());
		}

		AccountInfoCache accountInfoCache = new AccountInfoCache(listAccountInfo);

		changeDetail = new ChangeDetailX();
		changeDetail.setDateCreated(changeInfo.getCreated());
		changeDetail.setLastModified(changeInfo.getUpdated());
		changeDetail.setStarred(changeInfo.getStarred() != null ? true : false);
		changeDetail.setAccounts(accountInfoCache);
		changeDetail.setMessages(listChangeMessage);

		Branch.NameKey branchKey = getBranchKey(changeInfo);

		setChangeDetailDependency(reviewId, changeInfo, changeDetail, accountInfo, monitor);
		PatchSetInfo patchSetInfo = getPatchSetInfo(changeInfo.getCurrentPatchSetId(), changeInfo.getSubject());

		changeDetail.setApprovals(changeInfo.convertToApprovalDetails());
		changeDetail.setApprovalTypes(changeInfo.convertToApprovalTypes());

		//Fill the submit records
		String querysubmit = "/changes/" + Integer.toString(reviewId) + "/revisions/current/test.submit_rule?filters=SKIP"; //$NON-NLS-1$//$NON-NLS-2$
		List<SubmitRecord> submitRecord = currentSubmitRecord29(querysubmit, monitor);
		changeDetail.setSubmitRecords(submitRecord);
		if (changeDetail.getApprovalTypes() == null && getGerritConfig() != null) {
			changeDetail.convertSubmitRecordsToApprovalTypes(getGerritConfig().getApprovalTypes());
		}

		changeDetail.setPatchSets(patchSets);
		List<ReviewerInfo> reviewers = listReviewers(reviewId, monitor);
		if (!hasAllReviewers(changeDetail.getAccounts(), reviewers)) {
			merge(changeDetail.getAccounts(), reviewers);
		}

		Change initialChange = createChange(changeInfo.getChangeId(), reviewId, accountInfo, branchKey);

		initialChange.setCurrentPatchSet(patchSetInfo);

		initialChange.setStatus(changeInfo.getStatus());
		changeDetail.setChange(initialChange);
		setActions29(reviewId, changeDetail, monitor);
		return changeDetail;
	}

	private List<SubmitRecord> currentSubmitRecord29(String uri, IProgressMonitor monitor) throws GerritException {
		List<SubmitRecord> submitRecordList = new ArrayList<SubmitRecord>();
		SubmitRecord[] submitRecordArray = executePostRestRequest(uri, new SubmitRecord(), SubmitRecord[].class,
				new ErrorHandler() {
					@Override
					public void handleError(HttpMethodBase method) throws GerritException {
						String errorMsg = getResponseBodyAsString(method);
						if (isNotPermitted(method, errorMsg) || isConflict(method)) {
							throw new GerritException(NLS.bind("Cannot get submit change: {0}", errorMsg)); //$NON-NLS-1$
						}
					}

					private String getResponseBodyAsString(HttpMethodBase method) {
						try {
							return method.getResponseBodyAsString();
						} catch (IOException e) {
							return null;
						}
					}

					private boolean isNotPermitted(HttpMethodBase method, String msg) {
						return method.getStatusCode() == HttpURLConnection.HTTP_FORBIDDEN
								&& "submit not permitted\n".equals(msg); //$NON-NLS-1$
					}

					private boolean isConflict(HttpMethodBase method) {
						return method.getStatusCode() == HttpURLConnection.HTTP_CONFLICT;
					}
				}, monitor);
		for (SubmitRecord element : submitRecordArray) {
			List<SubmitRecord.Label> list = null;
			if (element.getStatus().equalsIgnoreCase("OK")) { //$NON-NLS-1$
				list = element.createLabel(element, element.getOkMap(), OK);
			} else if (element.getStatus().equalsIgnoreCase("NOT_READY")) { //$NON-NLS-1$
				list = element.createLabel(element, element.getNeedMap(), NEED);
			} else if (element.getStatus().equalsIgnoreCase("REJECT")) { //$NON-NLS-1$
				list = element.createLabel(element, element.getRejectMap(), REJECT);
			} else if (element.getStatus().equalsIgnoreCase("MAY")) { //$NON-NLS-1$
				list = element.createLabel(element, element.getMayMap(), MAY);
			}
			element.setLabels(list);
			submitRecordList.add(element);
		}

		return submitRecordList;
	}

	private void setChangeDetailDependency(int reviewId, ChangeInfo29 changeInfo29, ChangeDetailX changeDetail,
			AccountInfo accountInfo, IProgressMonitor monitor) throws GerritException {
		List<com.google.gerrit.common.data.ChangeInfo> dependsOn = new ArrayList<com.google.gerrit.common.data.ChangeInfo>();
		List<com.google.gerrit.common.data.ChangeInfo> neededBy = new ArrayList<com.google.gerrit.common.data.ChangeInfo>();
		Branch.NameKey branchKey = getBranchKey(changeInfo29);

		RelatedChangesInfo relatedChangesInfo = getRelatedChanges(reviewId, changeInfo29.getCurrentRevision(), monitor);
		List<RelatedChangeAndCommitInfo> listCommitInfo = relatedChangesInfo.getCommitInfo();
		boolean needed = true;
		for (RelatedChangeAndCommitInfo relatedChangeAndCommitInfo : listCommitInfo) {
			if (relatedChangeAndCommitInfo.getCommitInfo()
					.getCommit()
					.equalsIgnoreCase(changeInfo29.getCurrentRevision())) {
				needed = false;
			} else {
				if (relatedChangeAndCommitInfo.getChangeNumber() > 0) {
					com.google.gerrit.common.data.ChangeInfo googleChangeInfo = convertToGoogleChangeInfo(
							relatedChangeAndCommitInfo, accountInfo, branchKey);
					if (needed) {
						neededBy.add(googleChangeInfo);
					} else {
						dependsOn.add(googleChangeInfo);
					}
				}
			}
		}
		changeDetail.setNeededBy(neededBy);
		changeDetail.setDependsOn(dependsOn);
	}

	/**
	 * Returns the details for a specific review.
	 */
	public ChangeDetailX getChangeDetail(int reviewId, IProgressMonitor monitor) throws GerritException {
		final Change.Id changeId = new Change.Id(reviewId);
		ChangeDetailX changeDetail = null;

		if (isVersion29OrLater(monitor)) {
			changeDetail = getChangeDetail29(reviewId, monitor);
		} else {
			changeDetail = execute(monitor, new Operation<ChangeDetailX>() {
				@Override
				public void execute(IProgressMonitor monitor) throws GerritException {
					getChangeDetailService(monitor).changeDetailX(changeId, this);
				}
			});
			if (isVersion26OrLater(monitor)) {
				if (changeDetail.getApprovals() == null) {
					ChangeInfo changeInfo = getChangeInfo(reviewId, monitor);
					changeDetail.setApprovals(changeInfo.convertToApprovalDetails());
					changeDetail.setApprovalTypes(changeInfo.convertToApprovalTypes());
				}
				List<ReviewerInfo> reviewers = listReviewers(reviewId, monitor);
				if (!hasAllReviewers(changeDetail.getAccounts(), reviewers)) {
					merge(changeDetail.getAccounts(), reviewers);
				}
			} else if (changeDetail.getApprovalTypes() == null && getGerritConfig() != null) {
				changeDetail.convertSubmitRecordsToApprovalTypes(getGerritConfig().getApprovalTypes());
			}
			changeDetail.setDateCreated(changeDetail.getChange().getCreatedOn());
			changeDetail.setLastModified(changeDetail.getChange().getLastUpdatedOn());

		}
		return changeDetail;
	}

	private AccountInfo convertAuthorFrom29ToAccountInfo(ChangeInfo changeInfo) {
		AccountInfo accountInfo;
		Account account;
		account = new Account(new Account.Id(changeInfo.getOwner().getId()));
		account.setFullName(changeInfo.getOwner().getName());
		account.setUserName(changeInfo.getOwner().getUsername());
		account.setPreferredEmail(changeInfo.getOwner().getEmail());
		accountInfo = new AccountInfo(account);

		return accountInfo;
	}

	private org.eclipse.mylyn.internal.gerrit.core.client.rest.AccountInfo getAccountInfo(String account,
			IProgressMonitor monitor) throws GerritException, URIException {
		if (GerritSystemAccount.GERRIT_SYSTEM_NAME.equals(account)) {
			return GerritSystemAccount.GERRIT_SYSTEM;
		}
		String st = URIUtil.encodeQuery(account);
		final String uri = "/accounts/" + st; //$NON-NLS-1$
		org.eclipse.mylyn.internal.gerrit.core.client.rest.AccountInfo accountInfo = executeGetRestRequest(uri,
				org.eclipse.mylyn.internal.gerrit.core.client.rest.AccountInfo.class, monitor);
		return accountInfo;
	}

	private void setActions29(int reviewId, ChangeDetailX changeDetail, IProgressMonitor monitor) {
		ChangeInfo29 changeInfo29 = null;
		try {
			changeInfo29 = executeGetRestRequest("/changes/" + Integer.toString(reviewId) //$NON-NLS-1$
					+ "/?o=CURRENT_REVISION&o=CURRENT_ACTIONS", ChangeInfo29.class, monitor); //$NON-NLS-1$
		} catch (GerritException e) {
			StatusHandler.log(new Status(IStatus.ERROR, GerritCorePlugin.PLUGIN_ID,
					"ChangeDetailX GerritException running rest query", e)); //$NON-NLS-1$
		}

		if (changeInfo29 != null) {
			if (changeInfo29.getRevisions() != null) {
				setRevisionActions29(changeInfo29, changeDetail);
			}

			if (changeInfo29.getActions() != null) {
				setGlobalActions29(changeInfo29, changeDetail);
			}
		}
	}

	private void setRevisionActions29(ChangeInfo29 changeInfo29, ChangeDetailX changeDetail) {
		for (Entry<String, RevisionInfo> mapRevisions : changeInfo29.getRevisions().entrySet()) {
			if (mapRevisions.getValue().getActions() != null) {
				for (Entry<String, ActionInfo> mapActions : mapRevisions.getValue().getActions().entrySet()) {
					if (mapActions.getKey().equalsIgnoreCase("submit")) { //$NON-NLS-1$
						changeDetail.setCanSubmit(mapActions.getValue().getEnabled());
					} else if (mapActions.getKey().equalsIgnoreCase("rebase")) { //$NON-NLS-1$
						changeDetail.setCanRebase(mapActions.getValue().getEnabled());
					}
				}
			}
		}
	}

	private void setGlobalActions29(ChangeInfo29 changeInfo29, ChangeDetailX changeDetail) {
		for (Entry<String, ActionInfo> mapActions : changeInfo29.getActions().entrySet()) {
			if (mapActions.getKey().equalsIgnoreCase("abandon")) { //$NON-NLS-1$
				changeDetail.setCanAbandon(mapActions.getValue().getEnabled());
				changeDetail.setCanRestore(!mapActions.getValue().getEnabled());
			} else if (mapActions.getKey().equalsIgnoreCase("restore")) { //$NON-NLS-1$
				changeDetail.setCanAbandon(!mapActions.getValue().getEnabled());
				changeDetail.setCanRestore(mapActions.getValue().getEnabled());
			}
		}
	}

	private List<ReviewerInfo> listReviewers(final int reviewId, IProgressMonitor monitor) throws GerritException {
		final String uri = "/changes/" + reviewId + "/reviewers/"; //$NON-NLS-1$ //$NON-NLS-2$
		TypeToken<List<ReviewerInfo>> reviewersListType = new TypeToken<List<ReviewerInfo>>() {
		};
		return executeGetRestRequest(uri, reviewersListType.getType(), monitor);
	}

	private boolean hasAllReviewers(AccountInfoCache accounts, List<ReviewerInfo> reviewers) {
		for (ReviewerInfo reviewer : reviewers) {
			AccountInfo cachedAccount = accounts.get(new Account.Id(reviewer.getId()));
			if (cachedAccount == null || isAnonymous(cachedAccount)) {
				return false;
			}
		}
		return true;
	}

	private boolean isAnonymous(AccountInfo accountInfo) {
		return accountInfo.getFullName() == null && accountInfo.getPreferredEmail() == null;
	}

	private void merge(AccountInfoCache accounts, List<ReviewerInfo> reviewers) {
		Set<com.google.gerrit.common.data.AccountInfo> accountInfos = new HashSet<com.google.gerrit.common.data.AccountInfo>(
				reviewers.size());
		for (ReviewerInfo reviewer : reviewers) {
			accountInfos.add(reviewer.toAccountInfo());
		}
		AccountInfoCache accountInfoCache = new AccountInfoCache(accountInfos);
		accounts.merge(accountInfoCache);
	}

	public ChangeInfo getChangeInfo(final int reviewId, IProgressMonitor monitor) throws GerritException {
		final String uri = "/changes/" + reviewId + "/revisions/current/review"; //$NON-NLS-1$ //$NON-NLS-2$
		return executeGetRestRequest(uri, ChangeInfo.class, monitor);
	}

	public void loadPatchSetContent(PatchSetContent patchSetContent, IProgressMonitor monitor) throws GerritException {
		Id baseId = (patchSetContent.getBase() != null) ? patchSetContent.getBase().getId() : null;
		Id targetId = patchSetContent.getTarget().getId();
		if (patchSetContent.getTargetDetail() == null) {
			PatchSetDetail targetDetail = getPatchSetDetail(baseId, targetId, monitor);
			patchSetContent.setTargetDetail(targetDetail);
		}
		for (Patch patch : patchSetContent.getTargetDetail().getPatches()) {
			PatchScriptX patchScript = getPatchScript(patch.getKey(), baseId, targetId, monitor);
			if (patchScript != null) {
				patchSetContent.putPatchScriptByPatchKey(patch.getKey(), patchScript);
			}
		}
	}

	public GerritConfigX getGerritConfig() {
		return config == null ? null : config.getGerritConfig();
	}

	public GerritConfiguration getConfiguration() {
		return config;
	}

	public GerritSystemInfo getInfo(IProgressMonitor monitor) throws GerritException {
		Version version = getCachedVersion(monitor);
		List<ContributorAgreement> contributorAgreements = null;
		Account account = null;
		if (!isAnonymous()) {
			account = getAccount(monitor);
		} else {
			// XXX should run some more meaningful validation as anonymous, for now any call is good to validate the URL etc.
			executeQuery(monitor, "status:open"); //$NON-NLS-1$
		}
		refreshConfigOnce(monitor);
		return new GerritSystemInfo(version, contributorAgreements, account);
	}

	PatchScriptX getPatchScript(final Patch.Key key, final PatchSet.Id leftId, final PatchSet.Id rightId,
			final IProgressMonitor monitor) throws GerritException {
		final AccountDiffPreference diffPrefs = createAccountDiffPreference();
		final PatchScriptX patchScript = execute(monitor, new Operation<PatchScriptX>() {
			@Override
			public void execute(IProgressMonitor monitor) throws GerritException {
				getPatchDetailService(monitor).patchScriptX(key, leftId, rightId, diffPrefs, this);
			}
		});
		if (patchScript.isBinary()) {
			fetchLeftBinaryContent(patchScript, key, leftId, monitor);
			fetchRightBinaryContent(patchScript, key, rightId, monitor);
		}
		return patchScript;
	}

	protected void fetchLeftBinaryContent(final PatchScriptX patchScript, final Patch.Key key,
			final PatchSet.Id leftId, final IProgressMonitor monitor) throws GerritException {
		if (patchScript.getChangeType() != ChangeType.ADDED) {
			byte[] binaryContent = fetchBinaryContent(getUrlForPatchSetOrBase(key, leftId), monitor);
			patchScript.setBinaryA(binaryContent);
		}
	}

	protected void fetchRightBinaryContent(final PatchScriptX patchScript, final Patch.Key key,
			final PatchSet.Id rightId, final IProgressMonitor monitor) throws GerritException {
		if (patchScript.getChangeType() != ChangeType.DELETED) {
			byte[] binaryContent = fetchBinaryContent(getUrlForPatchSet(key, rightId), monitor);
			patchScript.setBinaryB(binaryContent);
		}
	}

	protected String getUrlForPatchSetOrBase(final Patch.Key key, final PatchSet.Id id) throws GerritException {
		if (id == null) {
			return getUrlForBase(key);
		} else {
			return getUrlForPatchSet(key, id);
		}
	}

	private String getUrlForBase(final Patch.Key key) throws GerritException {
		return encode(key.toString() + "^1"); //$NON-NLS-1$
	}

	protected String getUrlForPatchSet(final Patch.Key key, final PatchSet.Id id) throws GerritException {
		return encode(id + "," + key.getFileName() + "^0"); //$NON-NLS-1$//$NON-NLS-2$
	}

	protected byte[] fetchBinaryContent(String url, IProgressMonitor monitor) throws GerritException {
		final TypeToken<Byte[]> byteArrayType = new TypeToken<Byte[]>() {
		};
		byte[] bin = executeGetRestRequest("/cat/" + url, byteArrayType.getType(), monitor); //$NON-NLS-1$
		if (isZippedContent(bin)) {
			return unzip(bin);
		} else {
			return bin;
		}
	}

	/**
	 * Checks for the 4 byte header that identifies a ZIP file
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public static boolean isZippedContent(byte[] bin) {
		return bin != null && bin.length > 4 && bin[0] == 'P' && bin[1] == 'K' && bin[2] == 3 && bin[3] == 4;
	}

	/**
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public static byte[] unzip(byte[] zip) throws GerritException {
		ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zip));
		try {
			zis.getNextEntry(); // expecting a single entry
			return IOUtils.toByteArray(zis);
		} catch (IOException e) {
			throw new GerritException(e);
		} finally {
			IOUtils.closeQuietly(zis);
		}
	}

	private AccountDiffPreference createAccountDiffPreference() {
		AccountDiffPreference diffPrefs = new AccountDiffPreference((Account.Id) null);
		diffPrefs.setLineLength(Integer.MAX_VALUE);
		diffPrefs.setTabSize(4);
		diffPrefs.setContext(AccountDiffPreference.WHOLE_FILE_CONTEXT);
		diffPrefs.setIgnoreWhitespace(Whitespace.IGNORE_NONE);
		diffPrefs.setIntralineDifference(false);
		return diffPrefs;
	}

	private PatchSetDetail getPatchSetDetail(final PatchSet.Id idBase, final PatchSet.Id idTarget,
			IProgressMonitor monitor) throws GerritException {
		PatchSetDetail patchSetDetail = null;
		try {
			// Gerrit 2.4+
			patchSetDetail = execute(monitor, new Operation<PatchSetDetail>() {
				@Override
				public void execute(IProgressMonitor monitor) throws GerritException {
					getChangeDetailService(monitor).patchSetDetail2(idBase, idTarget, createAccountDiffPreference(),
							this);
				}
			});
		} catch (GerritException e) {
			try {
				// fallback for Gerrit < 2.1.7
				if (isNoSuchServiceError(e)) {
					patchSetDetail = execute(monitor, new Operation<PatchSetDetail>() {
						@Override
						public void execute(IProgressMonitor monitor) throws GerritException {
							getChangeDetailService(monitor).patchSetDetail(idTarget, this);
						}
					});
				} else {
					throw e;
				}
			} catch (GerritException e2) {
				// fallback for Gerrit 2.1.7
				String message = e2.getMessage();
				if (message != null && message.contains("Error parsing request")) { //$NON-NLS-1$
					patchSetDetail = execute(monitor, new Operation<PatchSetDetail>() {
						@Override
						public void execute(IProgressMonitor monitor) throws GerritException {
							getChangeDetailService(monitor).patchSetDetail(idBase, idTarget,
									createAccountDiffPreference(), this);
						}
					});
				} else {
					throw e2;
				}
			}
		}
		return patchSetDetail;
	}

	boolean isNoSuchServiceError(GerritException e) {
		String message = e.getMessage();
		return message != null && message.contains("No such service method"); //$NON-NLS-1$
	}

	public PatchSetPublishDetailX getPatchSetPublishDetail29(final PatchSet.Id id, IProgressMonitor monitor)
			throws GerritException {
		PatchSetPublishDetailX publishDetail = null;
		publishDetail = new PatchSetPublishDetailX();
		ChangeInfo changeInfo = getChangeInfo(id.getParentKey().get(), monitor);

		List<AccountInfo> listAccountInfo = new ArrayList<AccountInfo>();

		AccountInfo accountInfo = convertAuthorFrom29ToAccountInfo(changeInfo);
		listAccountInfo.add(accountInfo);
		AccountInfoCache accountInfoCache = new AccountInfoCache(listAccountInfo);
		publishDetail.setAccounts(accountInfoCache);

		Branch.NameKey branchKey = getBranchKey(changeInfo);
		Change currentChange = createChange(changeInfo.getChangeId(), id.getParentKey().get(), accountInfo, branchKey);
		currentChange.setStatus(changeInfo.getStatus());

		publishDetail.setChange(currentChange);

		PatchSetInfo patchSetInfo = getPatchSetInfo(changeInfo.getCurrentPatchSetId(), changeInfo.getSubject());
		publishDetail.setPatchSetInfo(patchSetInfo);
		publishDetail.setLabels(changeInfo.convertToPermissionLabels());

		if (publishDetail.getGiven() == null) {
			publishDetail.setGiven(changeInfo.convertToPatchSetApprovals(id, getAccount(monitor)));
		}
		return publishDetail;
	}

	public PatchSetPublishDetailX getPatchSetPublishDetail(final PatchSet.Id id, IProgressMonitor monitor)
			throws GerritException {
		PatchSetPublishDetailX publishDetail = null;
		if (isVersion29OrLater(monitor)) {
			publishDetail = getPatchSetPublishDetail29(id, monitor);
		} else {
			publishDetail = execute(monitor, new Operation<PatchSetPublishDetailX>() {
				@Override
				public void execute(IProgressMonitor monitor) throws GerritException {
					getChangeDetailService(monitor).patchSetPublishDetailX(id, this);
				}
			});
			if (publishDetail.getLabels() == null && isVersion26OrLater(monitor)) {
				ChangeInfo changeInfo = getChangeInfo(id.getParentKey().get(), monitor);
				publishDetail.setLabels(changeInfo.convertToPermissionLabels());
				if (publishDetail.getGiven() == null) {
					publishDetail.setGiven(changeInfo.convertToPatchSetApprovals(id, getAccount(monitor)));
				}
			}

		}
		return publishDetail;
	}

	public GerritChange getChange(String reviewId, IProgressMonitor monitor) throws GerritException {
		GerritChange gerritChange = new GerritChange();
		int id;
		try {
			id = id(reviewId);
		} catch (GerritException e) {
			List<GerritQueryResult> result = executeQuery(monitor, reviewId);
			if (result.size() == 1) {
				id = result.get(0).getNumber();
			} else {
				throw e;
			}
		}
		ChangeDetailX changeDetail = getChangeDetail(id, monitor);
		List<PatchSetDetail> patchSets = new ArrayList<PatchSetDetail>(changeDetail.getPatchSets().size());
		Map<PatchSet.Id, PatchSetPublishDetailX> patchSetPublishDetailByPatchSetId = new HashMap<PatchSet.Id, PatchSetPublishDetailX>();
		for (PatchSet patchSet : changeDetail.getPatchSets()) {
			try {
				PatchSetDetail patchSetDetail = getPatchSetDetail(null, patchSet.getId(), monitor);
				patchSets.add(patchSetDetail);
				if (!isAnonymous()) {
					PatchSetPublishDetailX patchSetPublishDetail = getPatchSetPublishDetail(patchSet.getId(), monitor);

					if (isVersion29OrLater(monitor)) {
						//To add the AccountId if available
						patchSetPublishDetail.setPatchSetInfo(setAccountPatchSetInfo(patchSetDetail.getInfo(), monitor));
					}
					patchSetPublishDetailByPatchSetId.put(patchSet.getId(), patchSetPublishDetail);
					changeDetail.setCurrentPatchSetDetail(patchSetDetail);
				}
			} catch (GerritException e) {
				handleMissingPatchSet(
						NLS.bind("Patch Set {0} items for Review {1}", patchSet.getPatchSetId(), reviewId), e); //$NON-NLS-1$
			}
		}
		gerritChange.setChangeDetail(changeDetail);
		gerritChange.setPatchSets(patchSets);
		gerritChange.setPatchSetPublishDetailByPatchSetId(patchSetPublishDetailByPatchSetId);

		return gerritChange;
	}

	private PatchSetInfo setAccountPatchSetInfo(PatchSetInfo patchSetInfo, IProgressMonitor monitor) {
		if (patchSetInfo.getAuthor().getAccount() == null) {
			patchSetInfo.setAuthor(setUserIdentity(patchSetInfo.getAuthor().getName(), patchSetInfo.getAuthor(),
					"Author", monitor)); //$NON-NLS-1$
		}
		if (patchSetInfo.getCommitter().getAccount() == null) {
			patchSetInfo.setCommitter(setUserIdentity(patchSetInfo.getCommitter().getName(),
					patchSetInfo.getCommitter(), "Committer", monitor)); //$NON-NLS-1$
		}
		return patchSetInfo;
	}

	private UserIdentity setUserIdentity(String name, UserIdentity userIdentity, String user, IProgressMonitor monitor) {
		org.eclipse.mylyn.internal.gerrit.core.client.rest.AccountInfo accountInfo = null;
		try {
			accountInfo = getAccountInfo(name, monitor);
			Account.Id accountId = new Account.Id(accountInfo.getId());
			userIdentity.setAccount(accountId);
		} catch (GerritException gerritException) {
			if (gerritException.getMessage().indexOf(HttpStatus.SC_NOT_FOUND) != 0) {
				StatusHandler.log(new Status(IStatus.WARNING, GerritCorePlugin.PLUGIN_ID, NLS.bind(
						"GerritException {0} not found", user), gerritException)); //$NON-NLS-1$
			}
		} catch (URIException uriException) {
			StatusHandler.log(new Status(IStatus.ERROR, GerritCorePlugin.PLUGIN_ID,
					NLS.bind("{0} URIException: ", user), uriException)); //$NON-NLS-1$
		}
		return userIdentity;
	}

	private void handleMissingPatchSet(String desc, GerritException e) {
		GerritCorePlugin.logWarning(
				NLS.bind("Couldn't load {0}. (Perhaps the Patch Set has been removed from repository?)", desc), e); //$NON-NLS-1$
	}

	public int id(String id) throws GerritException {
		if (id == null) {
			throw new GerritException("Invalid ID (null)"); //$NON-NLS-1$
		}
		try {
			return Integer.parseInt(id);
		} catch (NumberFormatException e) {
			throw new GerritException(NLS.bind("Invalid ID (''{0}'')", id)); //$NON-NLS-1$
		}
	}

	public void publishComments(String reviewId, int patchSetId, final String message,
			final Set<ApprovalCategoryValue.Id> approvals, IProgressMonitor monitor) throws GerritException {
		final PatchSet.Id id = new PatchSet.Id(new Change.Id(id(reviewId)), patchSetId);
		if (hasJsonRpcApi(monitor)) {
			execute(monitor, new Operation<VoidResult>() {
				@Override
				public void execute(IProgressMonitor monitor) throws GerritException {
					getPatchDetailService(monitor).publishComments(id, message, approvals, this);
				}
			});
		} else {
			ReviewInput reviewInput = new ReviewInput(message);
			Map<String, CommentInfo[]> drafts = listDrafts(id, monitor);
			Map<String, CommentInput[]> comments = convert(drafts);
			if (!comments.isEmpty()) {
				reviewInput.setComments(comments);
			}
			reviewInput.setApprovals(approvals);
			final String uri = "/a/changes/" + id.getParentKey().get() + "/revisions/" + id.get() + "/review"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			executePostRestRequest(uri, reviewInput, ReviewInfo.class, new ErrorHandler() {

				@Override
				public void handleError(HttpMethodBase method) throws GerritException {
					if (method.getStatusCode() == HttpURLConnection.HTTP_FORBIDDEN) {
						String msg = getResponseBodyAsString(method);
						if (msg.startsWith("Applying label") && msg.endsWith("is restricted")) { //$NON-NLS-1$ //$NON-NLS-2$
							throw new GerritException(msg);
						}
					}
				}

				private String getResponseBodyAsString(HttpMethodBase method) {
					try {
						String msg = method.getResponseBodyAsString();
						return msg.trim();
					} catch (IOException e) {
						// ignore
					}
					return null;
				}
			}, monitor);
		}
	}

	private Map<String, CommentInfo[]> listDrafts(final PatchSet.Id id, IProgressMonitor monitor)
			throws GerritException {
		String uri = "/changes/" + id.getParentKey().get() + "/revisions/" + id.get() + "/drafts/"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		TypeToken<Map<String, CommentInfo[]>> resultType = new TypeToken<Map<String, CommentInfo[]>>() {
		};

		return executeGetRestRequest(uri, resultType.getType(), monitor);
	}

	private Map<String, CommentInput[]> convert(Map<String, CommentInfo[]> commentInfos) {
		if (commentInfos == null || commentInfos.isEmpty()) {
			return Collections.<String, CommentInput[]> emptyMap();
		}
		Map<String, CommentInput[]> commentInputs = new HashMap<String, CommentInput[]>(commentInfos.size());
		Set<Entry<String, CommentInfo[]>> entrySet = commentInfos.entrySet();
		for (Entry<String, CommentInfo[]> entry : entrySet) {
			CommentInfo[] infos = entry.getValue();
			List<CommentInput> inputs = new ArrayList<CommentInput>(infos.length);
			for (CommentInfo info : infos) {
				inputs.add(new CommentInput(info));
			}
			commentInputs.put(entry.getKey(), inputs.toArray(new CommentInput[inputs.size()]));
		}
		return commentInputs;
	}

	public ReviewerResult addReviewers(String reviewId, final List<String> reviewers, IProgressMonitor monitor)
			throws GerritException {
		Assert.isLegal(reviewers != null, "reviewers cannot be null"); //$NON-NLS-1$
		final Change.Id id = new Change.Id(id(reviewId));
		if (hasJsonRpcApi(monitor)) {
			try {
				return execute(monitor, new Operation<ReviewerResult>() {
					@Override
					public void execute(IProgressMonitor monitor) throws GerritException {
						getPatchDetailService(monitor).addReviewers(id, reviewers, this);
					}
				});
			} catch (GerritException e) {
				// Gerrit 2.2
				String message = e.getMessage();
				if (message != null && message.contains("Error parsing request")) { //$NON-NLS-1$
					return execute(monitor, new Operation<ReviewerResult>() {
						@Override
						public void execute(IProgressMonitor monitor) throws GerritException {
							getPatchDetailService(monitor).addReviewers(id, reviewers, false, this);
						}
					});
				} else {
					throw e;
				}
			}
		} else {
			final String uri;
			uri = "/a/changes/" + id.get() + "/reviewers"; //$NON-NLS-1$ //$NON-NLS-2$

			Set<ReviewerInfo> reviewerInfos = new HashSet<ReviewerInfo>(reviewers.size());
			ReviewerResult reviewerResult = new ReviewerResult();
			for (final String reviewerId : reviewers) {
				try {
					AddReviewerResult addReviewerResult = executePostRestRequest(uri, new ReviewerInput(reviewerId),
							AddReviewerResult.class, null /*no error handler*/, monitor);
					reviewerInfos.addAll(addReviewerResult.getReviewers());
				} catch (GerritHttpException e) {
					if (e.getResponseCode() == HttpStatus.SC_UNPROCESSABLE_ENTITY) {
						reviewerResult.addError(new ReviewerResult.Error(null /* no type*/, reviewerId));
					}
				}
			}

			ChangeDetail changeDetail = getChangeDetail(id.get(), monitor);

			List<ApprovalDetail> approvalDetails = new ArrayList<ApprovalDetail>(reviewerInfos.size());
			for (ReviewerInfo reviewerInfo : reviewerInfos) {
				approvalDetails.add(reviewerInfo.toApprovalDetail(changeDetail.getCurrentPatchSet()));
			}
			changeDetail.setApprovals(approvalDetails);
			reviewerResult.setChange(changeDetail);
			return reviewerResult;
		}
	}

	/**
	 * Returns the latest 25 reviews.
	 */
	public List<GerritQueryResult> queryAllReviews(IProgressMonitor monitor) throws GerritException {
		return executeQuery(monitor, "status:open"); //$NON-NLS-1$
	}

	/**
	 * Returns the latest 25 reviews for the given project.
	 */
	public List<GerritQueryResult> queryByProject(IProgressMonitor monitor, final String project)
			throws GerritException {
		return executeQuery(monitor, "status:open project:" + project); //$NON-NLS-1$
	}

	/**
	 * Returns changes associated with the logged in user. This includes all open, closed and review requests for the
	 * user. On Gerrit 2.4 and earlier closed reviews are not included.
	 */
	public List<GerritQueryResult> queryMyReviews(IProgressMonitor monitor) throws GerritException {
		if (hasJsonRpcApi(monitor) && !restQueryAPIEnabled) {
			try {
				final Account account = getAccount(monitor);
				AccountDashboardInfo ad = execute(monitor, new Operation<AccountDashboardInfo>() {
					@Override
					public void execute(IProgressMonitor monitor) throws GerritException {
						getChangeListService(monitor).forAccount(account.getId(), this);
					}
				});

				List<com.google.gerrit.common.data.ChangeInfo> allMyChanges = ad.getByOwner();
				allMyChanges.addAll(ad.getForReview());
				allMyChanges.addAll(ad.getClosed());
				return convert(allMyChanges);
			} catch (GerritException e) {
				if (isNoSuchServiceError(e)) {
					restQueryAPIEnabled = true;
				} else {
					throw e;
				}
			}
		}
		// the "self" alias is only supported in Gerrit 2.5 and later
		return executeQueryRest(monitor, "owner:self OR reviewer:self", GET_LABELS_OPTION); //$NON-NLS-1$
	}

	private boolean hasJsonRpcApi(IProgressMonitor monitor) throws GerritException {
		return !isVersion26OrLater(monitor);
	}

	private boolean isVersion26OrLater(IProgressMonitor monitor) throws GerritException {
		Version version = getCachedVersion(monitor);
		return GerritVersion.isVersion26OrLater(version);
	}

	private boolean isVersion27OrLater(IProgressMonitor monitor) throws GerritException {
		Version version = getCachedVersion(monitor);
		return GerritVersion.isVersion27OrLater(version);
	}

	private boolean isVersion28OrLater(IProgressMonitor monitor) throws GerritException {
		Version version = getCachedVersion(monitor);
		return GerritVersion.isVersion28OrLater(version);
	}

	public boolean isVersion29OrLater(IProgressMonitor monitor) throws GerritException {
		Version version = getCachedVersion(monitor);
		return GerritVersion.isVersion29OrLater(version);
	}

	/**
	 * Returns watched changes of the currently logged in user
	 */
	public List<GerritQueryResult> queryWatchedReviews(IProgressMonitor monitor) throws GerritException {
		return executeQuery(monitor, "is:watched status:open"); //$NON-NLS-1$
	}

	/**
	 * Retrieves the root URL for the Gerrit instance and attempts to parse the configuration from the JavaScript
	 * portion of the page.
	 */
	private GerritConfigX refreshGerritConfig(final IProgressMonitor monitor) throws GerritException {
		try {
			GerritConfigX gerritConfig = client.execute(new Request<GerritConfigX>() {
				@Override
				public HttpMethodBase createMethod() throws IOException {
					return new GetMethod(client.getUrl() + "/"); //$NON-NLS-1$
				}

				@Override
				public GerritConfigX process(HttpMethodBase method) throws IOException {
					InputStream in = WebUtil.getResponseBodyAsStream(method, monitor);
					try {
						GerritHtmlProcessor processor = new GerritHtmlProcessor();
						processor.parse(in, method.getResponseCharSet());
						return processor.getConfig();
					} finally {
						in.close();
					}
				}
			}, monitor);

			if (gerritConfig == null) {
				throw new GerritException("Failed to obtain Gerrit configuration"); //$NON-NLS-1$
			}
			return gerritConfig;
		} catch (UnknownHostException cause) {
			GerritException e = new GerritException("Unknown host: " + cause.getMessage()); //$NON-NLS-1$
			e.initCause(cause);
			throw e;
		} catch (IOException cause) {
			GerritException e = new GerritException(cause.getMessage());
			e.initCause(cause);
			throw e;
		}
	}

	public GerritConfiguration refreshConfig(IProgressMonitor monitor) throws GerritException {
		configRefreshed = true;
		GerritConfigX gerritConfig = refreshGerritConfig(monitor);
		List<Project> projects = getVisibleProjects(monitor, gerritConfig);
		Account account = null;
		try {
			account = getAccount(monitor);
		} catch (GerritException e) {
			if (!isNotSignedInException(e)) {
				throw e;
			}
		}
		config = new GerritConfiguration(gerritConfig, projects, account);
		configurationChanged(config);
		return config;
	}

	public GerritConfiguration refreshConfigOnce(IProgressMonitor monitor) throws GerritException {
		if (!configRefreshed && config == null) {
			try {
				refreshConfig(monitor);
			} catch (GerritException e) {
				// don't fail validation in case config parsing fails
			}
		}
		return getConfiguration();
	}

	public ChangeDetail rebase(String reviewId, int patchSetId, IProgressMonitor monitor) throws GerritException {
		final PatchSet.Id id = new PatchSet.Id(new Change.Id(id(reviewId)), patchSetId);
		if (isVersion29OrLater(monitor)) {
			return rebaseRest(id, monitor);
		} else {
			return execute(monitor, new Operation<ChangeDetail>() {
				@Override
				public void execute(IProgressMonitor monitor) throws GerritException {
					getChangeManageService(monitor).rebaseChange(id, this);
				}
			});
		}
	}

	private ChangeDetail rebaseRest(final PatchSet.Id id, IProgressMonitor monitor) throws GerritException {
		final String uri = "/a/changes/" + id.getParentKey().get() + "/revisions/" + id.get() + "/rebase"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

		executePostRestRequest(uri, new ChangeInfo29(), ChangeInfo29.class, new ErrorHandler() {
			@Override
			public void handleError(HttpMethodBase method) throws GerritException {
				String errorMsg = getResponseBodyAsString(method);
				if (isConflict(method)) {
					throw new GerritException(errorMsg);
				}
			}

			private String getResponseBodyAsString(HttpMethodBase method) {
				try {
					return method.getResponseBodyAsString();
				} catch (IOException e) {
					return null;
				}
			}

			private boolean isConflict(HttpMethodBase method) {
				return method.getStatusCode() == HttpURLConnection.HTTP_CONFLICT;
			}
		}, monitor);
		return getChangeDetail(id.getParentKey().get(), monitor);
	}

	public ChangeDetail restore(String reviewId, int patchSetId, final String message, IProgressMonitor monitor)
			throws GerritException {
		final PatchSet.Id id = new PatchSet.Id(new Change.Id(id(reviewId)), patchSetId);
		if (hasJsonRpcApi(monitor)) {
			return execute(monitor, new Operation<ChangeDetail>() {
				@Override
				public void execute(IProgressMonitor monitor) throws GerritException {
					getChangeManageService(monitor).restoreChange(id, message, this);
				}
			});
		} else {
			final String uri = "/a/changes/" + id.getParentKey().get() + "/restore"; //$NON-NLS-1$ //$NON-NLS-2$
			try {
				executePostRestRequest(uri, new RestoreInput(message), ChangeInfo.class, null/*no error handler*/,
						monitor);
			} catch (GerritHttpException e) {
				if (e.getResponseCode() == HttpURLConnection.HTTP_CONFLICT) {
					throw new GerritException("Not Found", e); //$NON-NLS-1$
				}
			}
			return getChangeDetail(id.getParentKey().get(), monitor);
		}
	}

	public ChangeDetail submit(String reviewId, int patchSetId, IProgressMonitor monitor) throws GerritException {
		final PatchSet.Id id = new PatchSet.Id(new Change.Id(id(reviewId)), patchSetId);
		if (hasJsonRpcApi(monitor)) {
			return execute(monitor, new Operation<ChangeDetail>() {
				@Override
				public void execute(IProgressMonitor monitor) throws GerritException {
					getChangeManageService(monitor).submit(id, this);
				}
			});
		} else {
			return submitRest(id, monitor);
		}
	}

	private ChangeDetail submitRest(PatchSet.Id id, IProgressMonitor monitor) throws GerritException {
		final String uri = "/a/changes/" + id.getParentKey().get() + "/revisions/" + id.get() + "/submit"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		executePostRestRequest(uri, new SubmitInput(true), SubmitInfo.class, new ErrorHandler() {
			@Override
			public void handleError(HttpMethodBase method) throws GerritException {
				String errorMsg = getResponseBodyAsString(method);
				if (isNotPermitted(method, errorMsg) || isConflict(method)) {
					throw new GerritException(NLS.bind("Cannot submit change: {0}", errorMsg)); //$NON-NLS-1$
				}
			}

			private String getResponseBodyAsString(HttpMethodBase method) {
				try {
					return method.getResponseBodyAsString();
				} catch (IOException e) {
					return null;
				}
			}

			private boolean isNotPermitted(HttpMethodBase method, String msg) {
				return method.getStatusCode() == HttpURLConnection.HTTP_FORBIDDEN
						&& "submit not permitted\n".equals(msg); //$NON-NLS-1$
			}

			private boolean isConflict(HttpMethodBase method) {
				return method.getStatusCode() == HttpURLConnection.HTTP_CONFLICT;
			}
		}, monitor);
		return getChangeDetail(id.getParentKey().get(), monitor);
	}

	/**
	 * Sends a query for the changes visible to the caller to the gerrit server.
	 *
	 * @param monitor
	 *            A progress monitor
	 * @param queryString
	 *            The specific gerrit change query
	 * @return a list of GerritQueryResults built from the parsed query result (ChangeInfo:s)
	 * @throws GerritException
	 */
	public List<GerritQueryResult> executeQuery(IProgressMonitor monitor, final String queryString)
			throws GerritException {
		return executeQuery(monitor, queryString, GET_LABELS_OPTION);
	}

	/**
	 * Sends a query for the changes visible to the caller to the gerrit server with the possibility of adding options
	 * to the query.
	 *
	 * @param monitor
	 *            A progress monitor
	 * @param queryString
	 *            The specific gerrit change query
	 * @param optionString
	 *            Query options ("&o=" parameter). Only applicable for the REST API, ignored otherwise. May be null.
	 * @return a list of GerritQueryResults built from the parsed query result (ChangeInfo:s)
	 * @throws GerritException
	 */
	public List<GerritQueryResult> executeQuery(IProgressMonitor monitor, final String queryString, String optionString)
			throws GerritException {
		if (hasJsonRpcApi(monitor) && !restQueryAPIEnabled) {
			try {
				SingleListChangeInfo sl = execute(monitor, new Operation<SingleListChangeInfo>() {
					@Override
					public void execute(IProgressMonitor monitor) throws GerritException {
						getChangeListService(monitor).allQueryNext(queryString, "z", -1, this); //$NON-NLS-1$
					}
				});
				return convert(sl.getChanges());
			} catch (GerritException e) {
				if (isNoSuchServiceError(e)) {
					restQueryAPIEnabled = true;
				} else {
					throw e;
				}
			}
		}

		return executeQueryRest(monitor, queryString, optionString);
	}

	private List<GerritQueryResult> convert(List<com.google.gerrit.common.data.ChangeInfo> changes) {
		List<GerritQueryResult> results = new ArrayList<GerritQueryResult>(changes.size());
		for (com.google.gerrit.common.data.ChangeInfo changeInfo : changes) {
			GerritQueryResult result = new GerritQueryResult(changeInfo);
			results.add(result);
		}
		return results;
	}

	/**
	 * Sends a query for the changes visible to the caller to the gerrit server. Uses the gerrit REST API.
	 *
	 * @param monitor
	 *            A progress monitor
	 * @param queryString
	 *            The specific gerrit change query
	 * @return a list of GerritQueryResults built from the parsed query result (ChangeInfo:s)
	 * @throws GerritException
	 */
	public List<GerritQueryResult> executeQueryRest(IProgressMonitor monitor, final String queryString)
			throws GerritException {
		return executeQueryRest(monitor, queryString, null);
	}

	/**
	 * Sends a query for the changes visible to the caller to the gerrit server with the possibility of adding options
	 * to the query. Uses the gerrit REST API.
	 *
	 * @param monitor
	 *            A progress monitor
	 * @param queryString
	 *            The specific gerrit change query
	 * @param optionString
	 *            Query options ("&o=" parameter). May be null or empty.
	 * @return a list of GerritQueryResults built from the parsed query result (ChangeInfo:s)
	 * @throws GerritException
	 */
	public List<GerritQueryResult> executeQueryRest(IProgressMonitor monitor, final String queryString,
			String optionString) throws GerritException {
		String uri = "/changes/?q=" + encode(queryString); //$NON-NLS-1$
		if (StringUtils.isNotBlank(optionString)) {
			uri += "&o=" + encode(optionString); //$NON-NLS-1$
		}
		TypeToken<List<GerritQueryResult>> queryResultListType = new TypeToken<List<GerritQueryResult>>() {
		};
		return executeGetRestRequest(uri, queryResultListType.getType(), monitor);
	}

	/**
	 * Returns the (possibly cached) account for this client.
	 */
	public Account getAccount(IProgressMonitor monitor) throws GerritException {

		synchronized (this) {
			if (myAcount != null) {
				return myAcount;
			}
		}
		Account account = executeAccount(monitor);

		synchronized (this) {
			myAcount = account;
		}
		return myAcount;
	}

	private Account executeAccount(IProgressMonitor monitor) throws GerritException {
		if (isVersion29OrLater(monitor)) {
			return getAccount29(monitor);
		} else {
			return execute(monitor, new Operation<Account>() {
				@Override
				public void execute(IProgressMonitor monitor) throws GerritException {
					getAccountService(monitor).myAccount(this);
				}
			});
		}
	}

	private Account getAccount29(IProgressMonitor monitor) throws GerritException {
		if (isAnonymous()) {
			throw new GerritException(NOT_SIGNED_IN, -32603);
		}
		String query = "/accounts/self"; //$NON-NLS-1$/
		org.eclipse.mylyn.internal.gerrit.core.client.rest.AccountInfo accountInfo = executeGetRestRequest(query,
				org.eclipse.mylyn.internal.gerrit.core.client.rest.AccountInfo.class, monitor);

		Account account = new Account(new Account.Id(accountInfo.getId()));
		account.setFullName(accountInfo.getName());
		account.setUserName(accountInfo.getUsername());
		account.setPreferredEmail(accountInfo.getEmail());
		return account;
	}

	private AccountService getAccountService(IProgressMonitor monitor) {
		return getService(AccountService.class, monitor);
	}

	private ChangeDetailService getChangeDetailService(IProgressMonitor monitor) {
		return getService(ChangeDetailService.class, monitor);
	}

	private ChangeListService getChangeListService(IProgressMonitor monitor) {
		return getService(ChangeListService.class, monitor);
	}

	private ChangeManageService getChangeManageService(IProgressMonitor monitor) {
		return getService(ChangeManageService.class, monitor);
	}

	private PatchDetailService getPatchDetailService(IProgressMonitor monitor) {
		return getService(PatchDetailService.class, monitor);
	}

	private List<Project> getVisibleProjects(IProgressMonitor monitor, GerritConfig gerritConfig)
			throws GerritException {
		List<Project> result = new ArrayList<Project>();
		try {
			List<ProjectDetailX> projectDetails = execute(monitor, new Operation<List<ProjectDetailX>>() {
				@Override
				public void execute(IProgressMonitor monitor) throws GerritException {
					getProjectAdminService(monitor).visibleProjectDetails(this);
				}
			});
			for (ProjectDetailX projectDetail : projectDetails) {
				if (!GerritUtil.isPermissionOnlyProject(projectDetail, gerritConfig)) {
					result.add(projectDetail.project);
				}
			}
		} catch (GerritException e) {
			if (isNoSuchServiceError(e)) {
				if (isVersion27OrLater(monitor)) {
					Map<String, ProjectInfo> projects = listProjects(monitor);
					for (String projectName : projects.keySet()) {
						result.add(new Project(new NameKey(projectName)));
					}
				} else {
					// Gerrit <= 2.2.1
					List<Project> projects = execute(monitor, new Operation<List<Project>>() {
						@Override
						public void execute(IProgressMonitor monitor) throws GerritException {
							getProjectAdminService(monitor).visibleProjects(this);
						}
					});
					for (Project project : projects) {
						ProjectDetailX projectDetail = new ProjectDetailX();
						projectDetail.setProject(project);
						if (!GerritUtil.isPermissionOnlyProject(projectDetail, gerritConfig)) {
							result.add(project);
						}
					}
				}
			} else {
				throw e;
			}
		}
		Collections.sort(result, new ProjectByNameComparator());
		return result;
	}

	private Map<String, ProjectInfo> listProjects(IProgressMonitor monitor) throws GerritException {
		final String uri = "/projects/"; //$NON-NLS-1$
		TypeToken<Map<String, ProjectInfo>> resultType = new TypeToken<Map<String, ProjectInfo>>() {
		};
		return executeGetRestRequest(uri, resultType.getType(), monitor);
	}

	private ProjectAdminService getProjectAdminService(IProgressMonitor monitor) {
		return getService(ProjectAdminService.class, monitor);
	}

	public boolean isAnonymous() {
		return client.isAnonymous();
	}

	protected void configurationChanged(GerritConfiguration config) {
	}

	protected void authStateChanged(GerritAuthenticationState config) {
	}

	protected <T> T execute(IProgressMonitor monitor, Operation<T> operation) throws GerritException {
		try {
			GerritRequest.setCurrentRequest(new GerritRequest(monitor));
			try {
				return executeOnce(monitor, operation);
			} catch (GerritException e) {
				if (isAuthenticationException(e)) {
					operation.reset();
					return executeOnce(monitor, operation);
				}
				throw e;
			}
		} finally {
			GerritRequest.setCurrentRequest(null);
		}
	}

	private <T> T executePostRestRequest(final String url, final Object input, final Type resultType,
			final ErrorHandler handler, IProgressMonitor monitor) throws GerritException {
		return execute(monitor, new Operation<T>() {
			@Override
			public void execute(IProgressMonitor monitor) throws GerritException {
				try {
					setResult(client.<T> postRestRequest(url, input, resultType, handler, monitor));
				} catch (IOException e) {
					throw new GerritException(e);
				}
			}
		});
	}

	private <T> T executeGetRestRequest(final String url, final Type resultType, IProgressMonitor monitor)
			throws GerritException {
		return execute(monitor, new Operation<T>() {
			@Override
			public void execute(IProgressMonitor monitor) throws GerritException {
				try {
					setResult(client.<T> getRestRequest(url, resultType, monitor));
				} catch (IOException e) {
					throw new GerritException(e);
				}
			}
		});
	}

	private <T> T executePutRestRequest(final String url, final Object input, final Type resultType,
			final ErrorHandler handler, IProgressMonitor monitor) throws GerritException {
		return execute(monitor, new Operation<T>() {
			@Override
			public void execute(IProgressMonitor monitor) throws GerritException {
				try {
					setResult(client.<T> putRestRequest(url, input, resultType, handler, monitor));
				} catch (IOException e) {
					throw new GerritException(e);
				}
			}
		});
	}

	private <T> T executeDeleteRestRequest(final String url, final Object input, final Type resultType,
			final ErrorHandler handler, IProgressMonitor monitor) throws GerritException {
		return execute(monitor, new Operation<T>() {
			@Override
			public void execute(IProgressMonitor monitor) throws GerritException {
				try {
					setResult(client.<T> deleteRestRequest(url, input, resultType, handler, monitor));
				} catch (IOException e) {
					throw new GerritException(e);
				}
			}
		});
	}

	private <T> T executeOnce(IProgressMonitor monitor, Operation<T> operation) throws GerritException {
		operation.execute(monitor);
		if (operation.getException() instanceof GerritException) {
			throw (GerritException) operation.getException();
		} else if (operation.getException() instanceof OperationCanceledException) {
			throw (OperationCanceledException) operation.getException();
		} else if (operation.getException() instanceof RuntimeException) {
			throw (RuntimeException) operation.getException();
		} else if (operation.getException() != null) {
			GerritException e = new GerritException();
			e.initCause(operation.getException());
			throw e;
		}
		return operation.getResult();
	}

	protected synchronized <T extends RemoteJsonService> T getService(Class<T> clazz, IProgressMonitor monitor) {
		Version version = Version.emptyVersion;
		try {
			version = getCachedVersion(monitor);
		} catch (GerritException e) {
			// ignore, continue with emptyVersion
		}
		RemoteJsonService service = serviceByClass.get(clazz);
		if (service == null) {
			service = GerritService.create(clazz, client, version);
			serviceByClass.put(clazz, service);
		}
		return clazz.cast(service);
	}

	@Override
	public AbstractRemoteEmfFactoryProvider<IRepository, IReview> createFactoryProvider() {
		return new GerritRemoteFactoryProvider(this);
	}

	private Version getCachedVersion(IProgressMonitor monitor) throws GerritException {
		synchronized (this) {
			if (myVersion != null) {
				return myVersion;
			}
		}
		Version version = getVersion(monitor);

		synchronized (this) {
			myVersion = version;
		}
		return myVersion;
	}

	public Version getVersion(IProgressMonitor monitor) throws GerritException {
		return execute(monitor, new Operation<Version>() {
			@Override
			public void execute(IProgressMonitor monitor) throws GerritException {
				try {
					Request<String> request = new Request<String>() {
						@Override
						public HttpMethodBase createMethod() throws IOException {
							return new GetMethod(client.getUrl() + "/tools/hooks/"); //$NON-NLS-1$
						}

						@Override
						public String process(HttpMethodBase method) throws IOException {
							String content = method.getResponseBodyAsString();
							Matcher matcher = GERRIT_VERSION_PATTERN.matcher(content);
							if (matcher.find()) {
								return matcher.group(1);
							}
							return null;
						}
					};
					String result = client.execute(request, false, monitor);
					Version version = GerritVersion.parseGerritVersion(result);
					onSuccess(version);
				} catch (Exception e) {
					onFailure(e);
				}
			}
		});
	}

	public String toReviewId(String id, IProgressMonitor monitor) throws GerritException {
		try {
			Integer.parseInt(id);
			return id;
		} catch (NumberFormatException e) {
			try {
				List<GerritQueryResult> results = executeQuery(monitor, id);
				if (results.size() != 1) {
					throw new GerritException(NLS.bind("{0} is not a valid review ID", id)); //$NON-NLS-1$
				}
				return Integer.toString(results.get(0).getNumber());
			} catch (GerritException e2) {
				throw new GerritException(NLS.bind("{0} is not a valid review ID", id), e2); //$NON-NLS-1$
			}
		}
	}

	private static String encode(String string) throws GerritException {
		try {
			return URLEncoder.encode(string, "UTF-8"); //$NON-NLS-1$
		} catch (UnsupportedEncodingException e) {
			throw new GerritException(e);
		}
	}

	public VoidResult setStarred(final String reviewId, final boolean starred, IProgressMonitor monitor)
			throws GerritException {
		final Change.Id id = new Change.Id(id(reviewId));
		final ToggleStarRequest req = new ToggleStarRequest();
		req.toggle(id, starred);
		if (isVersion28OrLater(monitor)) {
			final String uri = "/a/accounts/self/starred.changes/" + id.get(); //$NON-NLS-1$

			return execute(monitor, new Operation<VoidResult>() {
				@Override
				public void execute(IProgressMonitor monitor) throws GerritException {

					if (starred) {
						executePutRestRequest(uri, req, ToggleStarRequest.class, createErrorHandler(), monitor);
					} else {
						executeDeleteRestRequest(uri, req, ToggleStarRequest.class, createErrorHandler(), monitor);
					}
				}
			});

		} else {
			return execute(monitor, new Operation<VoidResult>() {
				@Override
				public void execute(IProgressMonitor monitor) throws GerritException {
					getChangeListService(monitor).toggleStars(req, this);
				}
			});
		}
	}

	private ErrorHandler createErrorHandler() {
		return new ErrorHandler() {
			@Override
			public void handleError(HttpMethodBase method) throws GerritException {
				throw new GerritException(method.getStatusLine().getReasonPhrase());
			}
		};
	}
}
