Browse Source

Fairly complete json rpc interface to view/control Gitblit data objects.

tags/v0.7.0
James Moger 12 years ago
parent
commit
31abc26dd0

+ 7
- 5
src/com/gitblit/Constants.java View File

@@ -52,7 +52,7 @@ public class Constants {
public static final String SYNDICATION_PATH = "/feed/";
public static final String FEDERATION_PATH = "/federation/";
public static final String RPC_PATH = "/rpc/";
public static final String BORDER = "***********************************************************";
@@ -202,8 +202,10 @@ public class Constants {
*/
public static enum RpcRequest {
LIST_REPOSITORIES, CREATE_REPOSITORY, EDIT_REPOSITORY, DELETE_REPOSITORY,
LIST_USERS, CREATE_USER, EDIT_USER, DELETE_USER;
LIST_USERS, CREATE_USER, EDIT_USER, DELETE_USER, LIST_REPOSITORY_MEMBERS,
SET_REPOSITORY_MEMBERS, LIST_FEDERATION_REGISTRATIONS, LIST_FEDERATION_RESULTS,
LIST_FEDERATION_PROPOSALS, LIST_FEDERATION_SETS;
public static RpcRequest fromName(String name) {
for (RpcRequest type : values()) {
if (type.name().equalsIgnoreCase(name)) {
@@ -212,11 +214,11 @@ public class Constants {
}
return LIST_REPOSITORIES;
}
public boolean exceeds(RpcRequest type) {
return this.ordinal() > type.ordinal();
}
@Override
public String toString() {
return name();

+ 23
- 21
src/com/gitblit/FederationPullExecutor.java View File

@@ -19,6 +19,7 @@ import static org.eclipse.jgit.lib.Constants.DOT_GIT_EXT;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.text.MessageFormat;
import java.util.ArrayList;
@@ -43,6 +44,7 @@ import org.slf4j.LoggerFactory;
import com.gitblit.Constants.FederationPullStatus;
import com.gitblit.Constants.FederationStrategy;
import com.gitblit.GitBlitException.ForbiddenException;
import com.gitblit.models.FederationModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
@@ -81,8 +83,8 @@ public class FederationPullExecutor implements Runnable {
*
* @param registrations
* @param isDaemon
* if true, registrations are rescheduled in perpetuity. if false,
* the federation pull operation is executed once.
* if true, registrations are rescheduled in perpetuity. if
* false, the federation pull operation is executed once.
*/
public FederationPullExecutor(List<FederationModel> registrations, boolean isDaemon) {
this.registrations = registrations;
@@ -169,7 +171,7 @@ public class FederationPullExecutor implements Runnable {
} else {
repositoryName = registrationFolder + "/" + repository.name;
}
if (registration.bare) {
// bare repository, ensure .git suffix
if (!repositoryName.toLowerCase().endsWith(DOT_GIT_EXT)) {
@@ -178,7 +180,8 @@ public class FederationPullExecutor implements Runnable {
} else {
// normal repository, strip .git suffix
if (repositoryName.toLowerCase().endsWith(DOT_GIT_EXT)) {
repositoryName = repositoryName.substring(0, repositoryName.indexOf(DOT_GIT_EXT));
repositoryName = repositoryName.substring(0,
repositoryName.indexOf(DOT_GIT_EXT));
}
}
@@ -190,7 +193,8 @@ public class FederationPullExecutor implements Runnable {
StoredConfig config = existingRepository.getConfig();
config.load();
String origin = config.getString("remote", "origin", "url");
RevCommit commit = JGitUtils.getCommit(existingRepository, "refs/remotes/origin/master");
RevCommit commit = JGitUtils.getCommit(existingRepository,
"refs/remotes/origin/master");
if (commit != null) {
fetchHead = commit.getName();
}
@@ -209,7 +213,7 @@ public class FederationPullExecutor implements Runnable {
Constants.FEDERATION_USER, registration.token);
logger.info(MessageFormat.format("Pulling federated repository {0} from {1} @ {2}",
repository.name, registration.name, registration.url));
CloneResult result = JGitUtils.cloneRepository(registrationFolderFile, repository.name,
cloneUrl, registration.bare, credentials);
Repository r = GitBlit.self().getRepository(repositoryName);
@@ -255,7 +259,7 @@ public class FederationPullExecutor implements Runnable {
// preserve local settings
repository.isFrozen = rm.isFrozen;
repository.federationStrategy = rm.federationStrategy;
// merge federation sets
Set<String> federationSets = new HashSet<String>();
if (rm.federationSets != null) {
@@ -317,13 +321,12 @@ public class FederationPullExecutor implements Runnable {
}
}
}
} catch (Exception e) {
// a 403 error code is normal for a PULL_REPOSITORIES token
if (!e.getMessage().contains("403")) {
logger.warn(MessageFormat.format(
"Failed to retrieve USERS from federated gitblit ({0} @ {1})",
registration.name, registration.url), e);
}
} catch (ForbiddenException e) {
// ignore forbidden exceptions
} catch (IOException e) {
logger.warn(MessageFormat.format(
"Failed to retrieve USERS from federated gitblit ({0} @ {1})",
registration.name, registration.url), e);
}
try {
@@ -337,13 +340,12 @@ public class FederationPullExecutor implements Runnable {
properties.store(os, null);
os.close();
}
} catch (Exception e) {
// a 403 error code is normal for a PULL_REPOSITORIES token
if (!e.getMessage().contains("403")) {
logger.warn(MessageFormat.format(
"Failed to retrieve SETTINGS from federated gitblit ({0} @ {1})",
registration.name, registration.url), e);
}
} catch (ForbiddenException e) {
// ignore forbidden exceptions
} catch (IOException e) {
logger.warn(MessageFormat.format(
"Failed to retrieve SETTINGS from federated gitblit ({0} @ {1})",
registration.name, registration.url), e);
}
}

+ 26
- 1
src/com/gitblit/GitBlit.java View File

@@ -59,6 +59,7 @@ import com.gitblit.Constants.FederationStrategy;
import com.gitblit.Constants.FederationToken;
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.FederationSet;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.FederationUtils;
@@ -873,6 +874,29 @@ public class GitBlit implements ServletContextListener {
return null;
}
/**
* Returns the list of federation sets.
*
* @return list of federation sets
*/
public List<FederationSet> getFederationSets(String gitblitUrl) {
List<FederationSet> list = new ArrayList<FederationSet>();
// generate standard tokens
for (FederationToken type : FederationToken.values()) {
FederationSet fset = new FederationSet(type.toString(), type, getFederationToken(type));
fset.repositories = getRepositories(gitblitUrl, fset.token);
list.add(fset);
}
// generate tokens for federation sets
for (String set : settings.getStrings(Keys.federation.sets)) {
FederationSet fset = new FederationSet(set, FederationToken.REPOSITORIES,
getFederationToken(set));
fset.repositories = getRepositories(gitblitUrl, fset.token);
list.add(fset);
}
return list;
}
/**
* Returns the list of possible federation tokens for this Gitblit instance.
*
@@ -1025,7 +1049,8 @@ public class GitBlit implements ServletContextListener {
});
for (File file : files) {
String json = com.gitblit.utils.FileUtils.readContent(file, null);
FederationProposal proposal = JsonUtils.fromJsonString(json, FederationProposal.class);
FederationProposal proposal = JsonUtils.fromJsonString(json,
FederationProposal.class);
list.add(proposal);
}
}

+ 29
- 1
src/com/gitblit/GitBlitException.java View File

@@ -15,17 +15,45 @@
*/
package com.gitblit;
import java.io.IOException;
/**
* GitBlitException is a marginally useful class. :)
*
* @author James Moger
*
*/
public class GitBlitException extends Exception {
public class GitBlitException extends IOException {
private static final long serialVersionUID = 1L;
public GitBlitException(String message) {
super(message);
}
/**
* Exception to indicate that the client should prompt for credentials
* because the requested action requires authentication.
*/
public static class UnauthorizedException extends GitBlitException {
private static final long serialVersionUID = 1L;
public UnauthorizedException(String message) {
super(message);
}
}
/**
* Exception to indicate that the requested action can not be executed by
* the specified user.
*/
public static class ForbiddenException extends GitBlitException {
private static final long serialVersionUID = 1L;
public ForbiddenException(String message) {
super(message);
}
}
}

+ 27
- 4
src/com/gitblit/JsonServlet.java View File

@@ -17,6 +17,7 @@ package com.gitblit;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Type;
import java.text.MessageFormat;
import javax.servlet.ServletException;
@@ -27,6 +28,7 @@ import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.utils.StringUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -72,6 +74,30 @@ public abstract class JsonServlet extends HttpServlet {
protected <X> X deserialize(HttpServletRequest request, HttpServletResponse response,
Class<X> clazz) throws IOException {
String json = readJson(request, response);
if (StringUtils.isEmpty(json)) {
return null;
}
Gson gson = new Gson();
X object = gson.fromJson(json.toString(), clazz);
return object;
}
protected <X> X deserialize(HttpServletRequest request, HttpServletResponse response, Type type)
throws IOException {
String json = readJson(request, response);
if (StringUtils.isEmpty(json)) {
return null;
}
Gson gson = new Gson();
X object = gson.fromJson(json.toString(), type);
return object;
}
private String readJson(HttpServletRequest request, HttpServletResponse response)
throws IOException {
BufferedReader reader = request.getReader();
StringBuilder json = new StringBuilder();
String line = null;
@@ -86,10 +112,7 @@ public abstract class JsonServlet extends HttpServlet {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return null;
}
Gson gson = new Gson();
X object = gson.fromJson(json.toString(), clazz);
return object;
return json.toString();
}
protected void serialize(HttpServletResponse response, Object o) throws IOException {

+ 75
- 0
src/com/gitblit/RpcServlet.java View File

@@ -18,6 +18,7 @@ package com.gitblit;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -30,6 +31,7 @@ import com.gitblit.Constants.RpcRequest;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.HttpUtils;
import com.gitblit.utils.RpcUtils;
/**
* Handles remote procedure calls.
@@ -57,6 +59,7 @@ public class RpcServlet extends JsonServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RpcRequest reqType = RpcRequest.fromName(request.getParameter("req"));
String objectName = request.getParameter("name");
logger.info(MessageFormat.format("Rpc {0} request from {1}", reqType,
request.getRemoteAddr()));
@@ -88,6 +91,78 @@ public class RpcServlet extends JsonServlet {
users.add(GitBlit.self().getUserModel(name));
}
result = users;
} else if (RpcRequest.CREATE_REPOSITORY.equals(reqType)) {
// create repository
RepositoryModel model = deserialize(request, response, RepositoryModel.class);
GitBlit.self().updateRepositoryModel(model.name, model, true);
} else if (RpcRequest.EDIT_REPOSITORY.equals(reqType)) {
// edit repository
RepositoryModel model = deserialize(request, response, RepositoryModel.class);
// name parameter specifies original repository name in event of
// rename
String repoName = objectName;
if (repoName == null) {
repoName = model.name;
}
GitBlit.self().updateRepositoryModel(repoName, model, false);
} else if (RpcRequest.DELETE_REPOSITORY.equals(reqType)) {
// delete repository
RepositoryModel model = deserialize(request, response, RepositoryModel.class);
GitBlit.self().deleteRepositoryModel(model);
} else if (RpcRequest.CREATE_USER.equals(reqType)) {
// create user
UserModel model = deserialize(request, response, UserModel.class);
GitBlit.self().updateUserModel(model.username, model, true);
} else if (RpcRequest.EDIT_USER.equals(reqType)) {
// edit user
UserModel model = deserialize(request, response, UserModel.class);
// name parameter specifies original user name in event of rename
String username = objectName;
if (username == null) {
username = model.username;
}
GitBlit.self().updateUserModel(username, model, false);
} else if (RpcRequest.DELETE_USER.equals(reqType)) {
// delete user
UserModel model = deserialize(request, response, UserModel.class);
GitBlit.self().deleteUser(model.username);
} else if (RpcRequest.LIST_REPOSITORY_MEMBERS.equals(reqType)) {
// get repository members
RepositoryModel model = GitBlit.self().getRepositoryModel(objectName);
result = GitBlit.self().getRepositoryUsers(model);
} else if (RpcRequest.SET_REPOSITORY_MEMBERS.equals(reqType)) {
// update repository access list
RepositoryModel model = GitBlit.self().getRepositoryModel(objectName);
Collection<String> names = deserialize(request, response, RpcUtils.NAMES_TYPE);
List<String> users = new ArrayList<String>(names);
if (!GitBlit.self().setRepositoryUsers(model, users)) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
}
} else if (RpcRequest.LIST_FEDERATION_REGISTRATIONS.equals(reqType)) {
// return the list of federation registrations
result = GitBlit.self().getFederationRegistrations();
} else if (RpcRequest.LIST_FEDERATION_RESULTS.equals(reqType)) {
// return the list of federation result registrations
if (GitBlit.canFederate()) {
result = GitBlit.self().getFederationResultRegistrations();
} else {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
}
} else if (RpcRequest.LIST_FEDERATION_PROPOSALS.equals(reqType)) {
// return the list of federation proposals
if (GitBlit.canFederate()) {
result = GitBlit.self().getPendingFederationProposals();
} else {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
}
} else if (RpcRequest.LIST_FEDERATION_SETS.equals(reqType)) {
// return the list of federation sets
if (GitBlit.canFederate()) {
String gitblitUrl = HttpUtils.getGitblitURL(request);
result = GitBlit.self().getFederationSets(gitblitUrl);
} else {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
}
}
// send the result of the request

+ 58
- 0
src/com/gitblit/models/FederationSet.java View File

@@ -0,0 +1,58 @@
/*
* Copyright 2011 gitblit.com.
*
* 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.gitblit.models;
import java.io.Serializable;
import java.util.Map;
import com.gitblit.Constants.FederationToken;
/**
* Represents a group of repositories.
*/
public class FederationSet implements Serializable {
private static final long serialVersionUID = 1L;
public String name;
public String token;
public FederationToken tokenType;
public Map<String, RepositoryModel> repositories;
/**
* The constructor for a federation set.
*
* @param name
* the name of this federation set
* @param tokenType
* the type of token of this federation set
* @param token
* the federation token
*/
public FederationSet(String name, FederationToken tokenType, String token) {
this.name = name;
this.tokenType = tokenType;
this.token = token;
}
@Override
public String toString() {
return "Federation Set (" + name + ")";
}
}

+ 6
- 8
src/com/gitblit/utils/FederationUtils.java View File

@@ -49,16 +49,13 @@ import com.google.gson.reflect.TypeToken;
*/
public class FederationUtils {
public static final Type REPOSITORIES_TYPE = new TypeToken<Map<String, RepositoryModel>>() {
private static final Type REPOSITORIES_TYPE = new TypeToken<Map<String, RepositoryModel>>() {
}.getType();
public static final Type SETTINGS_TYPE = new TypeToken<Map<String, String>>() {
private static final Type SETTINGS_TYPE = new TypeToken<Map<String, String>>() {
}.getType();
public static final Type USERS_TYPE = new TypeToken<Collection<UserModel>>() {
}.getType();
public static final Type RESULTS_TYPE = new TypeToken<List<FederationModel>>() {
private static final Type USERS_TYPE = new TypeToken<Collection<UserModel>>() {
}.getType();
private static final Logger LOGGER = LoggerFactory.getLogger(FederationUtils.class);
@@ -276,10 +273,11 @@ public class FederationUtils {
* @return a collection of UserModel objects
* @throws Exception
*/
public static Collection<UserModel> getUsers(FederationModel registration) throws Exception {
public static List<UserModel> getUsers(FederationModel registration) throws Exception {
String url = asLink(registration.url, registration.token, FederationRequest.PULL_USERS);
Collection<UserModel> models = JsonUtils.retrieveJson(url, USERS_TYPE);
return models;
List<UserModel> list = new ArrayList<UserModel>(models);
return list;
}
/**

+ 119
- 47
src/com/gitblit/utils/JsonUtils.java View File

@@ -16,6 +16,7 @@
package com.gitblit.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
@@ -36,6 +37,10 @@ import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.eclipse.jgit.util.Base64;
import com.gitblit.GitBlitException.ForbiddenException;
import com.gitblit.GitBlitException.UnauthorizedException;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.google.gson.Gson;
@@ -43,7 +48,7 @@ import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
/**
* Utility methods for gson calls to a Gitblit server.
* Utility methods for json calls to a Gitblit server.
*
* @author James Moger
*
@@ -98,7 +103,7 @@ public class JsonUtils {
Gson gson = new Gson();
return gson.fromJson(json, clazz);
}
/**
* Convert a json string to an object of the specified type.
*
@@ -116,11 +121,27 @@ public class JsonUtils {
*
* @param url
* @param type
* @return
* @throws Exception
* @return the deserialized object
* @throws {@link IOException}
*/
public static <X> X retrieveJson(String url, Type type) throws Exception {
String json = retrieveJsonString(url);
public static <X> X retrieveJson(String url, Type type) throws IOException,
UnauthorizedException {
return retrieveJson(url, type, null, null);
}
/**
* Reads a gson object from the specified url.
*
* @param url
* @param type
* @param username
* @param password
* @return the deserialized object
* @throws {@link IOException}
*/
public static <X> X retrieveJson(String url, Type type, String username, char[] password)
throws IOException {
String json = retrieveJsonString(url, username, password);
if (StringUtils.isEmpty(json)) {
return null;
}
@@ -133,29 +154,42 @@ public class JsonUtils {
*
* @param url
* @return the JSON message as a string
* @throws Exception
* @throws {@link IOException}
*/
public static String retrieveJsonString(String url) throws Exception {
URL urlObject = new URL(url);
URLConnection conn = urlObject.openConnection();
conn.setRequestProperty("Accept-Charset", CHARSET);
conn.setUseCaches(false);
conn.setDoInput(true);
if (conn instanceof HttpsURLConnection) {
HttpsURLConnection secureConn = (HttpsURLConnection) conn;
secureConn.setSSLSocketFactory(SSL_CONTEXT.getSocketFactory());
secureConn.setHostnameVerifier(HOSTNAME_VERIFIER);
}
InputStream is = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is, CHARSET));
StringBuilder json = new StringBuilder();
char[] buffer = new char[4096];
int len = 0;
while ((len = reader.read(buffer)) > -1) {
json.append(buffer, 0, len);
public static String retrieveJsonString(String url, String username, char[] password)
throws IOException {
try {
URL urlObject = new URL(url);
URLConnection conn = urlObject.openConnection();
conn.setRequestProperty("Accept-Charset", CHARSET);
setAuthorization(conn, username, password);
conn.setUseCaches(false);
conn.setDoInput(true);
if (conn instanceof HttpsURLConnection) {
HttpsURLConnection secureConn = (HttpsURLConnection) conn;
secureConn.setSSLSocketFactory(SSL_CONTEXT.getSocketFactory());
secureConn.setHostnameVerifier(HOSTNAME_VERIFIER);
}
InputStream is = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is, CHARSET));
StringBuilder json = new StringBuilder();
char[] buffer = new char[4096];
int len = 0;
while ((len = reader.read(buffer)) > -1) {
json.append(buffer, 0, len);
}
is.close();
return json.toString();
} catch (IOException e) {
if (e.getMessage().indexOf("401") > -1) {
// unauthorized
throw new UnauthorizedException(url);
} else if (e.getMessage().indexOf("403") > -1) {
// requested url is forbidden by the requesting user
throw new ForbiddenException(url);
}
throw e;
}
is.close();
return json.toString();
}
/**
@@ -166,29 +200,67 @@ public class JsonUtils {
* @param json
* the json message to send
* @return the http request result code
* @throws Exception
* @throws {@link IOException}
*/
public static int sendJsonString(String url, String json) throws Exception {
byte[] jsonBytes = json.getBytes(CHARSET);
URL urlObject = new URL(url);
URLConnection conn = urlObject.openConnection();
conn.setRequestProperty("Content-Type", "text/plain;charset=" + CHARSET);
conn.setRequestProperty("Content-Length", "" + jsonBytes.length);
conn.setUseCaches(false);
conn.setDoOutput(true);
if (conn instanceof HttpsURLConnection) {
HttpsURLConnection secureConn = (HttpsURLConnection) conn;
secureConn.setSSLSocketFactory(SSL_CONTEXT.getSocketFactory());
secureConn.setHostnameVerifier(HOSTNAME_VERIFIER);
}
public static int sendJsonString(String url, String json) throws IOException {
return sendJsonString(url, json, null, null);
}
// write json body
OutputStream os = conn.getOutputStream();
os.write(jsonBytes);
os.close();
/**
* Sends a JSON message.
*
* @param url
* the url to write to
* @param json
* the json message to send
* @param username
* @param password
* @return the http request result code
* @throws {@link IOException}
*/
public static int sendJsonString(String url, String json, String username, char[] password)
throws IOException {
try {
byte[] jsonBytes = json.getBytes(CHARSET);
URL urlObject = new URL(url);
URLConnection conn = urlObject.openConnection();
conn.setRequestProperty("Content-Type", "text/plain;charset=" + CHARSET);
conn.setRequestProperty("Content-Length", "" + jsonBytes.length);
setAuthorization(conn, username, password);
conn.setUseCaches(false);
conn.setDoOutput(true);
if (conn instanceof HttpsURLConnection) {
HttpsURLConnection secureConn = (HttpsURLConnection) conn;
secureConn.setSSLSocketFactory(SSL_CONTEXT.getSocketFactory());
secureConn.setHostnameVerifier(HOSTNAME_VERIFIER);
}
int status = ((HttpURLConnection) conn).getResponseCode();
return status;
// write json body
OutputStream os = conn.getOutputStream();
os.write(jsonBytes);
os.close();
int status = ((HttpURLConnection) conn).getResponseCode();
return status;
} catch (IOException e) {
if (e.getMessage().indexOf("401") > -1) {
// unauthorized
throw new UnauthorizedException(url);
} else if (e.getMessage().indexOf("403") > -1) {
// requested url is forbidden by the requesting user
throw new ForbiddenException(url);
}
throw e;
}
}
private static void setAuthorization(URLConnection conn, String username, char[] password) {
if (!StringUtils.isEmpty(username) && (password != null && password.length > 0)) {
conn.setRequestProperty(
"Authorization",
"Basic "
+ Base64.encodeBytes((username + ":" + new String(password)).getBytes()));
}
}
/**

+ 279
- 11
src/com/gitblit/utils/RpcUtils.java View File

@@ -15,12 +15,18 @@
*/
package com.gitblit.utils;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import com.gitblit.Constants;
import com.gitblit.Constants.RpcRequest;
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.FederationSet;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.google.gson.reflect.TypeToken;
@@ -33,10 +39,22 @@ import com.google.gson.reflect.TypeToken;
*/
public class RpcUtils {
public static final Type REPOSITORIES_TYPE = new TypeToken<Map<String, RepositoryModel>>() {
public static final Type NAMES_TYPE = new TypeToken<Collection<String>>() {
}.getType();
public static final Type USERS_TYPE = new TypeToken<Collection<UserModel>>() {
private static final Type REPOSITORIES_TYPE = new TypeToken<Map<String, RepositoryModel>>() {
}.getType();
private static final Type USERS_TYPE = new TypeToken<Collection<UserModel>>() {
}.getType();
private static final Type REGISTRATIONS_TYPE = new TypeToken<Collection<FederationModel>>() {
}.getType();
private static final Type PROPOSALS_TYPE = new TypeToken<Collection<FederationProposal>>() {
}.getType();
private static final Type SETS_TYPE = new TypeToken<Collection<FederationSet>>() {
}.getType();
/**
@@ -48,26 +66,45 @@ public class RpcUtils {
* @return
*/
public static String asLink(String remoteURL, RpcRequest req) {
return asLink(remoteURL, req, null);
}
/**
*
* @param remoteURL
* the url of the remote gitblit instance
* @param req
* the rpc request type
* @param name
* the name of the actionable object
* @return
*/
public static String asLink(String remoteURL, RpcRequest req, String name) {
if (remoteURL.length() > 0 && remoteURL.charAt(remoteURL.length() - 1) == '/') {
remoteURL = remoteURL.substring(0, remoteURL.length() - 1);
}
if (req == null) {
req = RpcRequest.LIST_REPOSITORIES;
}
return remoteURL + Constants.RPC_PATH + "?req=" + req.name().toLowerCase();
return remoteURL + Constants.RPC_PATH + "?req=" + req.name().toLowerCase()
+ (name == null ? "" : ("&name=" + name));
}
/**
* Retrieves a map of the repositories at the remote gitblit instance keyed
* by the repository clone url.
*
* @param serverUrl
* @param account
* @param password
* @return a map of cloneable repositories
* @throws Exception
* @throws IOException
*/
public static Map<String, RepositoryModel> getRepositories(String serverUrl) throws Exception {
public static Map<String, RepositoryModel> getRepositories(String serverUrl, String account,
char[] password) throws IOException {
String url = asLink(serverUrl, RpcRequest.LIST_REPOSITORIES);
Map<String, RepositoryModel> models = JsonUtils.retrieveJson(url, REPOSITORIES_TYPE);
Map<String, RepositoryModel> models = JsonUtils.retrieveJson(url, REPOSITORIES_TYPE,
account, password);
return models;
}
@@ -75,12 +112,243 @@ public class RpcUtils {
* Tries to pull the gitblit user accounts from the remote gitblit instance.
*
* @param serverUrl
* @param account
* @param password
* @return a collection of UserModel objects
* @throws Exception
* @throws IOException
*/
public static Collection<UserModel> getUsers(String serverUrl) throws Exception {
public static List<UserModel> getUsers(String serverUrl, String account, char[] password)
throws IOException {
String url = asLink(serverUrl, RpcRequest.LIST_USERS);
Collection<UserModel> models = JsonUtils.retrieveJson(url, USERS_TYPE);
return models;
Collection<UserModel> models = JsonUtils.retrieveJson(url, USERS_TYPE, account, password);
List<UserModel> list = new ArrayList<UserModel>(models);
return list;
}
/**
* Create a repository on the Gitblit server.
*
* @param repository
* @param serverUrl
* @param account
* @param password
* @return true if the action succeeded
* @throws IOException
*/
public static boolean createRepository(RepositoryModel repository, String serverUrl,
String account, char[] password) throws IOException {
return doAction(RpcRequest.CREATE_REPOSITORY, null, repository, serverUrl, account,
password);
}
/**
* Send a revised version of the repository model to the Gitblit server.
*
* @param repository
* @param serverUrl
* @param account
* @param password
* @return true if the action succeeded
* @throws IOException
*/
public static boolean updateRepository(String repositoryName, RepositoryModel repository,
String serverUrl, String account, char[] password) throws IOException {
return doAction(RpcRequest.EDIT_REPOSITORY, repositoryName, repository, serverUrl, account,
password);
}
/**
* Delete a repository from the Gitblit server.
*
* @param repository
* @param serverUrl
* @param account
* @param password
* @return true if the action succeeded
* @throws IOException
*/
public static boolean deleteRepository(RepositoryModel repository, String serverUrl,
String account, char[] password) throws IOException {
return doAction(RpcRequest.DELETE_REPOSITORY, null, repository, serverUrl, account,
password);
}
/**
* Create a user on the Gitblit server.
*
* @param user
* @param serverUrl
* @param account
* @param password
* @return true if the action succeeded
* @throws IOException
*/
public static boolean createUser(UserModel user, String serverUrl, String account,
char[] password) throws IOException {
return doAction(RpcRequest.CREATE_USER, null, user, serverUrl, account, password);
}
/**
* Send a revised version of the user model to the Gitblit server.
*
* @param user
* @param serverUrl
* @param account
* @param password
* @return true if the action succeeded
* @throws IOException
*/
public static boolean updateUser(String username, UserModel user, String serverUrl,
String account, char[] password) throws IOException {
return doAction(RpcRequest.EDIT_USER, username, user, serverUrl, account, password);
}
/**
* Deletes a user from the Gitblit server.
*
* @param user
* @param serverUrl
* @param account
* @param password
* @return true if the action succeeded
* @throws IOException
*/
public static boolean deleteUser(UserModel user, String serverUrl, String account,
char[] password) throws IOException {
return doAction(RpcRequest.DELETE_USER, null, user, serverUrl, account, password);
}
/**
* Retrieves the list of users that can access the specified repository.
*
* @param repository
* @param serverUrl
* @param account
* @param password
* @return list of members
* @throws IOException
*/
public static List<String> getRepositoryMembers(RepositoryModel repository, String serverUrl,
String account, char[] password) throws IOException {
String url = asLink(serverUrl, RpcRequest.LIST_REPOSITORY_MEMBERS, repository.name);
Collection<String> list = JsonUtils.retrieveJson(url, NAMES_TYPE, account, password);
return new ArrayList<String>(list);
}
/**
* Sets the repository membership list.
*
* @param repository
* @param memberships
* @param serverUrl
* @param account
* @param password
* @return true if the action succeeded
* @throws IOException
*/
public static boolean setRepositoryMembers(RepositoryModel repository,
List<String> memberships, String serverUrl, String account, char[] password)
throws IOException {
return doAction(RpcRequest.SET_REPOSITORY_MEMBERS, repository.name, memberships, serverUrl,
account, password);
}
/**
* Retrieves the list of federation registrations. These are the list of
* registrations that this Gitblit instance is pulling from.
*
* @param serverUrl
* @param account
* @param password
* @return a collection of FederationRegistration objects
* @throws IOException
*/
public static List<FederationModel> getFederationRegistrations(String serverUrl,
String account, char[] password) throws IOException {
String url = asLink(serverUrl, RpcRequest.LIST_FEDERATION_REGISTRATIONS);
Collection<FederationModel> registrations = JsonUtils.retrieveJson(url, REGISTRATIONS_TYPE,
account, password);
List<FederationModel> list = new ArrayList<FederationModel>(registrations);
return list;
}
/**
* Retrieves the list of federation result registrations. These are the
* results reported back to this Gitblit instance from a federation client.
*
* @param serverUrl
* @param account
* @param password
* @return a collection of FederationRegistration objects
* @throws IOException
*/
public static List<FederationModel> getFederationResultRegistrations(String serverUrl,
String account, char[] password) throws IOException {
String url = asLink(serverUrl, RpcRequest.LIST_FEDERATION_RESULTS);
Collection<FederationModel> registrations = JsonUtils.retrieveJson(url, REGISTRATIONS_TYPE,
account, password);
List<FederationModel> list = new ArrayList<FederationModel>(registrations);
return list;
}
/**
* Retrieves the list of federation proposals.
*
* @param serverUrl
* @param account
* @param password
* @return a collection of FederationProposal objects
* @throws IOException
*/
public static List<FederationProposal> getFederationProposals(String serverUrl,
String account, char[] password) throws IOException {
String url = asLink(serverUrl, RpcRequest.LIST_FEDERATION_PROPOSALS);
Collection<FederationProposal> proposals = JsonUtils.retrieveJson(url, PROPOSALS_TYPE,
account, password);
List<FederationProposal> list = new ArrayList<FederationProposal>(proposals);
return list;
}
/**
* Retrieves the list of federation repository sets.
*
* @param serverUrl
* @param account
* @param password
* @return a collection of FederationSet objects
* @throws IOException
*/
public static List<FederationSet> getFederationSets(String serverUrl,
String account, char[] password) throws IOException {
String url = asLink(serverUrl, RpcRequest.LIST_FEDERATION_SETS);
Collection<FederationSet> sets = JsonUtils.retrieveJson(url, SETS_TYPE,
account, password);
List<FederationSet> list = new ArrayList<FederationSet>(sets);
return list;
}
/**
* Do the specified administrative action on the Gitblit server.
*
* @param request
* @param name
* the name of the object (may be null)
* @param object
* @param serverUrl
* @param account
* @param password
* @return true if the action succeeded
* @throws IOException
*/
protected static boolean doAction(RpcRequest request, String name, Object object,
String serverUrl, String account, char[] password) throws IOException {
String url = asLink(serverUrl, request, name);
String json = JsonUtils.toJsonString(object);
int resultCode = JsonUtils.sendJsonString(url, json, account, password);
return resultCode == 200;
}
}

+ 3
- 9
tests/com/gitblit/tests/FederationTests.java View File

@@ -64,12 +64,6 @@ public class FederationTests extends TestCase {
Thread.sleep(2500);
}
public void testDeserialization() throws Exception {
String json = "{\"https://localhost:8443/git/a.b.c.orphan.git\":{\"name\":\"a.b.c.orphan.git\",\"description\":\"\",\"owner\":\"\",\"lastChange\":\"Jul 22, 2011 3:15:07 PM\",\"hasCommits\":true,\"showRemoteBranches\":false,\"useTickets\":false,\"useDocs\":false,\"accessRestriction\":\"NONE\",\"isFrozen\":false,\"showReadme\":false,\"isFederated\":false},\"https://localhost:8443/git/test/jgit.git\":{\"name\":\"test/jgit.git\",\"description\":\"\",\"owner\":\"\",\"lastChange\":\"Jul 13, 2011 9:42:33 AM\",\"hasCommits\":true,\"showRemoteBranches\":true,\"useTickets\":false,\"useDocs\":false,\"accessRestriction\":\"NONE\",\"isFrozen\":false,\"showReadme\":false,\"isFederated\":false},\"https://localhost:8443/git/test/helloworld.git\":{\"name\":\"test/helloworld.git\",\"description\":\"\",\"owner\":\"\",\"lastChange\":\"Jul 15, 2008 7:26:48 PM\",\"hasCommits\":true,\"showRemoteBranches\":false,\"useTickets\":false,\"useDocs\":false,\"accessRestriction\":\"NONE\",\"isFrozen\":false,\"showReadme\":false,\"isFederated\":false},\"https://localhost:8443/git/working/ticgit\":{\"name\":\"working/ticgit\",\"description\":\"\",\"owner\":\"\",\"lastChange\":\"Jul 22, 2011 10:35:27 AM\",\"hasCommits\":true,\"showRemoteBranches\":false,\"useTickets\":false,\"useDocs\":false,\"accessRestriction\":\"NONE\",\"isFrozen\":false,\"showReadme\":false,\"isFederated\":false},\"https://localhost:8443/git/ticgit.git\":{\"name\":\"ticgit.git\",\"description\":\"\",\"owner\":\"\",\"lastChange\":\"Jul 22, 2011 10:35:27 AM\",\"hasCommits\":true,\"showRemoteBranches\":true,\"useTickets\":true,\"useDocs\":true,\"accessRestriction\":\"NONE\",\"isFrozen\":false,\"showReadme\":false,\"isFederated\":false},\"https://localhost:8443/git/helloworld.git\":{\"name\":\"helloworld.git\",\"description\":\"\",\"owner\":\"\",\"lastChange\":\"Jul 15, 2008 7:26:48 PM\",\"hasCommits\":true,\"showRemoteBranches\":false,\"useTickets\":false,\"useDocs\":false,\"accessRestriction\":\"NONE\",\"isFrozen\":false,\"showReadme\":false,\"isFederated\":false},\"https://localhost:8443/git/test/helloworld3.git\":{\"name\":\"test/helloworld3.git\",\"description\":\"\",\"owner\":\"\",\"lastChange\":\"Jul 15, 2008 7:26:48 PM\",\"hasCommits\":true,\"showRemoteBranches\":false,\"useTickets\":false,\"useDocs\":false,\"accessRestriction\":\"NONE\",\"isFrozen\":false,\"showReadme\":false,\"isFederated\":false},\"https://localhost:8443/git/test/bluez-gnome.git\":{\"name\":\"test/bluez-gnome.git\",\"description\":\"\",\"owner\":\"\",\"lastChange\":\"Dec 19, 2008 6:35:33 AM\",\"hasCommits\":true,\"showRemoteBranches\":false,\"useTickets\":false,\"useDocs\":false,\"accessRestriction\":\"NONE\",\"isFrozen\":false,\"showReadme\":false,\"isFederated\":false}}";
Map<String, RepositoryModel> models = JsonUtils.fromJsonString(json, FederationUtils.REPOSITORIES_TYPE);
assertEquals(8, models.size());
}
public void testProposal() throws Exception {
// create dummy repository data
Map<String, RepositoryModel> repositories = new HashMap<String, RepositoryModel>();
@@ -96,9 +90,9 @@ public class FederationTests extends TestCase {
public void testPullRepositories() throws Exception {
try {
String url = FederationUtils.asLink("http://localhost:" + port,
"testtoken", FederationRequest.PULL_REPOSITORIES);
String json = JsonUtils.retrieveJsonString(url);
String url = FederationUtils.asLink("http://localhost:" + port, "testtoken",
FederationRequest.PULL_REPOSITORIES);
String json = JsonUtils.retrieveJsonString(url, null, null);
} catch (IOException e) {
if (!e.getMessage().contains("403")) {
throw e;

+ 168
- 8
tests/com/gitblit/tests/RpcTests.java View File

@@ -16,25 +16,185 @@
package com.gitblit.tests;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import junit.framework.TestCase;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.GitBlitException.UnauthorizedException;
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.FederationSet;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.RpcUtils;
/**
* Tests all the rpc client utility methods, the rpc filter and rpc servlet.
*
* @author James Moger
*
*/
public class RpcTests extends TestCase {
public void testListRepositories() throws Exception {
Map<String, RepositoryModel> map = null;
String url = "https://localhost:8443";
String account = "admin";
String password = "admin";
public void testListRepositories() throws IOException {
Map<String, RepositoryModel> map = RpcUtils.getRepositories(url, null, null);
assertTrue("Repository list is null!", map != null);
assertTrue("Repository list is empty!", map.size() > 0);
}
public void testListUsers() throws IOException {
List<UserModel> list = null;
try {
map = RpcUtils.getRepositories("https://localhost:8443");
} catch (IOException e) {
if (!e.getMessage().contains("403")) {
throw e;
list = RpcUtils.getUsers(url, null, null);
} catch (UnauthorizedException e) {
}
assertTrue("Server allows anyone to admin!", list == null);
list = RpcUtils.getUsers(url, "admin", "admin".toCharArray());
assertTrue("User list is empty!", list.size() > 0);
}
public void testUserAdministration() throws IOException {
UserModel user = new UserModel("garbage");
user.canAdmin = true;
user.password = "whocares";
// create
assertTrue("Failed to create user!",
RpcUtils.createUser(user, url, account, password.toCharArray()));
UserModel retrievedUser = findUser(user.username);
assertTrue("Failed to find " + user.username, retrievedUser != null);
assertTrue("Retrieved user can not administer Gitblit", retrievedUser.canAdmin);
// rename and toggle admin permission
String originalName = user.username;
user.username = "garbage2";
user.canAdmin = false;
assertTrue("Failed to update user!",
RpcUtils.updateUser(originalName, user, url, account, password.toCharArray()));
retrievedUser = findUser(user.username);
assertTrue("Failed to find " + user.username, retrievedUser != null);
assertTrue("Retrieved user did not update", !retrievedUser.canAdmin);
// delete
assertTrue("Failed to delete " + user.username,
RpcUtils.deleteUser(retrievedUser, url, account, password.toCharArray()));
retrievedUser = findUser(user.username);
assertTrue("Failed to delete " + user.username, retrievedUser == null);
}
private UserModel findUser(String name) throws IOException {
List<UserModel> users = RpcUtils.getUsers(url, account, password.toCharArray());
UserModel retrievedUser = null;
for (UserModel model : users) {
if (model.username.equalsIgnoreCase(name)) {
retrievedUser = model;
break;
}
}
assertTrue("Repository list is null!", map != null);
assertTrue("Repository list is empty!", map.size() > 0);
return retrievedUser;
}
public void testRepositoryAdministration() throws IOException {
RepositoryModel model = new RepositoryModel();
model.name = "garbagerepo.git";
model.description = "created by RpcUtils";
model.owner = "garbage";
model.accessRestriction = AccessRestrictionType.VIEW;
// create
assertTrue("Failed to create repository!",
RpcUtils.createRepository(model, url, account, password.toCharArray()));
RepositoryModel retrievedRepository = findRepository(model.name);
assertTrue("Failed to find " + model.name, retrievedRepository != null);
assertTrue("Access retriction type is wrong",
AccessRestrictionType.VIEW.equals(retrievedRepository.accessRestriction));
// rename and change access restriciton
String originalName = model.name;
model.name = "garbagerepo2.git";
model.accessRestriction = AccessRestrictionType.PUSH;
assertTrue("Failed to update repository!", RpcUtils.updateRepository(originalName, model,
url, account, password.toCharArray()));
retrievedRepository = findRepository(model.name);
assertTrue("Failed to find " + model.name, retrievedRepository != null);
assertTrue("Access retriction type is wrong",
AccessRestrictionType.PUSH.equals(retrievedRepository.accessRestriction));
// memberships
String testMember = "justadded";
List<String> members = RpcUtils.getRepositoryMembers(retrievedRepository, url, account,
password.toCharArray());
assertTrue("Membership roster is not empty!", members.size() == 0);
members.add(testMember);
assertTrue(
"Failed to set memberships!",
RpcUtils.setRepositoryMembers(retrievedRepository, members, url, account,
password.toCharArray()));
members = RpcUtils.getRepositoryMembers(retrievedRepository, url, account,
password.toCharArray());
boolean foundMember = false;
for (String member : members) {
if (member.equalsIgnoreCase(testMember)) {
foundMember = true;
break;
}
}
assertTrue("Failed to find member!", foundMember);
// delete
assertTrue("Failed to delete " + model.name, RpcUtils.deleteRepository(retrievedRepository,
url, account, password.toCharArray()));
retrievedRepository = findRepository(model.name);
assertTrue("Failed to delete " + model.name, retrievedRepository == null);
}
private RepositoryModel findRepository(String name) throws IOException {
Map<String, RepositoryModel> repositories = RpcUtils.getRepositories(url, account,
password.toCharArray());
RepositoryModel retrievedRepository = null;
for (RepositoryModel model : repositories.values()) {
if (model.name.equalsIgnoreCase(name)) {
retrievedRepository = model;
break;
}
}
return retrievedRepository;
}
public void testFederationRegistrations() throws Exception {
List<FederationModel> registrations = RpcUtils.getFederationRegistrations(url, account,
password.toCharArray());
assertTrue("No federation registrations wre retrieved!", registrations.size() > 0);
}
public void testFederationResultRegistrations() throws Exception {
List<FederationModel> registrations = RpcUtils.getFederationResultRegistrations(url,
account, password.toCharArray());
assertTrue("No federation result registrations were retrieved!", registrations.size() > 0);
}
public void testFederationProposals() throws Exception {
List<FederationProposal> proposals = RpcUtils.getFederationProposals(url,
account, password.toCharArray());
assertTrue("No federation proposals were retrieved!", proposals.size() > 0);
}
public void testFederationSets() throws Exception {
List<FederationSet> sets = RpcUtils.getFederationSets(url,
account, password.toCharArray());
assertTrue("No federation sets were retrieved!", sets.size() > 0);
}
}

Loading…
Cancel
Save