Browse Source

Refactored federation servlet and utils. Started rpc servlet and utils.

tags/v0.7.0
James Moger 12 years ago
parent
commit
93f0b1a11d

+ 6
- 0
distrib/gitblit.properties View File

@@ -87,6 +87,12 @@ web.siteName =
# SINCE 0.5.0
web.allowAdministration = true
# Allows remote clients to list repositories and administer the Gitblit instance
# if they have administrator permissions.
#
# SINCE 0.6.1
web.enableRpcServlet = false
# Allow dynamic zip downloads.
#
# SINCE 0.5.0

+ 19
- 3
src/WEB-INF/web.xml View File

@@ -69,7 +69,21 @@
<url-pattern>/federation/*</url-pattern>
</servlet-mapping>
<!-- Rpc Servlet
<url-pattern> MUST match:
* com.gitblit.Constants.RPC_PATH
* Wicket Filter ignorePaths parameter -->
<servlet>
<servlet-name>RpcServlet</servlet-name>
<servlet-class>com.gitblit.RpcServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RpcServlet</servlet-name>
<url-pattern>/rpc/*</url-pattern>
</servlet-mapping>
<!-- Git Access Restriction Filter
<url-pattern> MUST match:
* GitServlet
@@ -114,6 +128,7 @@
<url-pattern>/zip/*</url-pattern>
</filter-mapping>
<!-- Wicket Filter -->
<filter>
<filter-name>wicketFilter</filter-name>
@@ -136,8 +151,9 @@
* Zipfilter <url-pattern>
* ZipServlet <url-pattern>
* com.gitblit.Constants.ZIP_PATH
* FederationServlet <url-pattern> -->
<param-value>git/,feed/,zip/,federation/</param-value>
* FederationServlet <url-pattern>
* RpcServlet <url-pattern> -->
<param-value>git/,feed/,zip/,federation/,rpc/</param-value>
</init-param>
</filter>
<filter-mapping>

+ 25
- 0
src/com/gitblit/Constants.java View File

@@ -52,6 +52,8 @@ 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 = "***********************************************************";
@@ -193,4 +195,27 @@ public class Constants {
return name();
}
}
/**
* Enumeration representing the possible remote procedure call requests from
* a client.
*/
public static enum RpcRequest {
LIST_REPOSITORIES, CREATE_REPOSITORY, EDIT_REPOSITORY, DELETE_REPOSITORY,
LIST_USERS, CREATE_USER, EDIT_USER, DELETE_USER;
public static RpcRequest fromName(String name) {
for (RpcRequest type : values()) {
if (type.name().equalsIgnoreCase(name)) {
return type;
}
}
return LIST_REPOSITORIES;
}
@Override
public String toString() {
return name();
}
}
}

+ 13
- 109
src/com/gitblit/FederationServlet.java View File

@@ -15,7 +15,6 @@
*/
package com.gitblit;
import java.io.BufferedReader;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
@@ -23,24 +22,16 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.Constants.FederationRequest;
import com.gitblit.Constants.FederationToken;
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.FederationUtils;
import com.gitblit.utils.HttpUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.utils.TimeUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
/**
* Handles federation requests.
@@ -48,67 +39,25 @@ import com.google.gson.GsonBuilder;
* @author James Moger
*
*/
public class FederationServlet extends HttpServlet {
public class FederationServlet extends JsonServlet {
private static final long serialVersionUID = 1L;
private transient Logger logger = LoggerFactory.getLogger(FederationServlet.class);
public FederationServlet() {
super();
}
/**
* Returns an url to this servlet for the specified parameters.
*
* @param sourceURL
* the url of the source gitblit instance
* @param token
* the federation token of the source gitblit instance
* @param req
* the pull type request
*/
public static String asFederationLink(String sourceURL, String token, FederationRequest req) {
return asFederationLink(sourceURL, null, token, req, null);
}
/**
*
* @param remoteURL
* the url of the remote gitblit instance
* @param tokenType
* the type of federation token of a gitblit instance
* @param token
* the federation token of a gitblit instance
* @param req
* the pull type request
* @param myURL
* the url of this gitblit instance
* @return
*/
public static String asFederationLink(String remoteURL, FederationToken tokenType,
String token, FederationRequest req, String myURL) {
if (remoteURL.length() > 0 && remoteURL.charAt(remoteURL.length() - 1) == '/') {
remoteURL = remoteURL.substring(0, remoteURL.length() - 1);
}
if (req == null) {
req = FederationRequest.PULL_REPOSITORIES;
}
return remoteURL + Constants.FEDERATION_PATH + "?req=" + req.name().toLowerCase()
+ (token == null ? "" : ("&token=" + token))
+ (tokenType == null ? "" : ("&tokenType=" + tokenType.name().toLowerCase()))
+ (myURL == null ? "" : ("&url=" + StringUtils.encodeURL(myURL)));
}
/**
* Returns the list of repositories for federation requests.
* Processes a federation request.
*
* @param request
* @param response
* @throws javax.servlet.ServletException
* @throws java.io.IOException
*/
private void processRequest(javax.servlet.http.HttpServletRequest request,
@Override
protected void processRequest(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
java.io.IOException {
FederationRequest reqType = FederationRequest.fromName(request.getParameter("req"));
@@ -137,26 +86,11 @@ public class FederationServlet extends HttpServlet {
if (FederationRequest.PROPOSAL.equals(reqType)) {
// Receive a gitblit federation proposal
BufferedReader reader = request.getReader();
StringBuilder json = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
json.append(line);
}
reader.close();
// check to see if we have proposal data
if (json.length() == 0) {
logger.error(MessageFormat.format("Failed to receive proposal data from {0}",
request.getRemoteAddr()));
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
FederationProposal proposal = deserialize(request, response, FederationProposal.class);
if (proposal == null) {
return;
}
// deserialize the proposal
Gson gson = new Gson();
FederationProposal proposal = gson.fromJson(json.toString(), FederationProposal.class);
// reject proposal, if not receipt prohibited
if (!GitBlit.getBoolean(Keys.federation.allowProposals, false)) {
logger.error(MessageFormat.format("Rejected {0} federation proposal from {1}",
@@ -193,25 +127,13 @@ public class FederationServlet extends HttpServlet {
String remoteId = StringUtils.decodeFromHtml(request.getParameter("url"));
String identification = MessageFormat.format("{0} ({1})", remoteId,
request.getRemoteAddr());
BufferedReader reader = request.getReader();
StringBuilder json = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
json.append(line);
}
reader.close();
// check to see if we have repository data
if (json.length() == 0) {
logger.error(MessageFormat.format(
"Failed to receive pulled repositories list from {0}", identification));
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
// deserialize the status data
FederationModel results = deserialize(request, response, FederationModel.class);
if (results == null) {
return;
}
// deserialize the status data
Gson gson = new Gson();
FederationModel results = gson.fromJson(json.toString(), FederationModel.class);
// setup the last and netx pull dates
results.lastPull = new Date();
int mins = TimeUtils.convertFrequencyToMinutes(results.frequency);
@@ -279,25 +201,7 @@ public class FederationServlet extends HttpServlet {
}
}
if (result != null) {
// Send JSON response
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(result);
response.getWriter().append(json);
}
}
@Override
protected void doPost(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
java.io.IOException {
processRequest(request, response);
}
@Override
protected void doGet(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
java.io.IOException {
processRequest(request, response);
// send the result of the request
serialize(response, result);
}
}

+ 3
- 6
src/com/gitblit/GitBlit.java View File

@@ -63,9 +63,8 @@ import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.FederationUtils;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.JsonUtils;
import com.gitblit.utils.StringUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
/**
* GitBlit is the servlet context listener singleton that acts as the core for
@@ -978,8 +977,7 @@ public class GitBlit implements ServletContextListener {
*/
public boolean submitFederationProposal(FederationProposal proposal, String gitblitUrl) {
// convert proposal to json
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(proposal);
String json = JsonUtils.toJsonString(proposal);
try {
// make the proposals folder
@@ -1025,10 +1023,9 @@ public class GitBlit implements ServletContextListener {
&& file.getName().toLowerCase().endsWith(Constants.PROPOSAL_EXT);
}
});
Gson gson = new Gson();
for (File file : files) {
String json = com.gitblit.utils.FileUtils.readContent(file, null);
FederationProposal proposal = gson.fromJson(json, FederationProposal.class);
FederationProposal proposal = JsonUtils.fromJsonString(json, FederationProposal.class);
list.add(proposal);
}
}

+ 103
- 0
src/com/gitblit/JsonServlet.java View File

@@ -0,0 +1,103 @@
/*
* 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;
import java.io.BufferedReader;
import java.io.IOException;
import java.text.MessageFormat;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
/**
* Servlet class for interpreting json requests.
*
* @author James Moger
*
*/
public abstract class JsonServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected final Logger logger;
public JsonServlet() {
super();
logger = LoggerFactory.getLogger(getClass());
}
/**
* Processes an gson request.
*
* @param request
* @param response
* @throws javax.servlet.ServletException
* @throws java.io.IOException
*/
protected abstract void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, java.io.IOException {
processRequest(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
protected <X> X deserialize(HttpServletRequest request, HttpServletResponse response,
Class<X> clazz) throws IOException {
BufferedReader reader = request.getReader();
StringBuilder json = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
json.append(line);
}
reader.close();
if (json.length() == 0) {
logger.error(MessageFormat.format("Failed to receive json data from {0}",
request.getRemoteAddr()));
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return null;
}
Gson gson = new Gson();
X object = gson.fromJson(json.toString(), clazz);
return object;
}
protected void serialize(HttpServletResponse response, Object o) throws IOException {
if (o != null) {
// Send JSON response
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(o);
response.getWriter().append(json);
}
}
}

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

@@ -0,0 +1,107 @@
/*
* 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;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import com.gitblit.Constants.RpcRequest;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.HttpUtils;
/**
* Handles remote procedure calls.
*
* @author James Moger
*
*/
public class RpcServlet extends JsonServlet {
private static final long serialVersionUID = 1L;
public RpcServlet() {
super();
}
/**
* Processes an rpc request.
*
* @param request
* @param response
* @throws javax.servlet.ServletException
* @throws java.io.IOException
*/
@Override
protected void processRequest(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
java.io.IOException {
RpcRequest reqType = RpcRequest.fromName(request.getParameter("req"));
logger.info(MessageFormat.format("Rpc {0} request from {1}", reqType,
request.getRemoteAddr()));
if (!GitBlit.getBoolean(Keys.web.enableRpcServlet, false)) {
logger.warn(Keys.web.enableRpcServlet + " must be set TRUE for rpc requests.");
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
// TODO user authentication and authorization
UserModel user = null;
Object result = null;
if (RpcRequest.LIST_REPOSITORIES.equals(reqType)) {
// list repositories
// Determine the Gitblit clone url
String gitblitUrl = HttpUtils.getGitblitURL(request);
StringBuilder sb = new StringBuilder();
sb.append(gitblitUrl);
sb.append(Constants.GIT_PATH);
sb.append("{0}");
String cloneUrl = sb.toString();
List<RepositoryModel> list = GitBlit.self().getRepositoryModels(user);
Map<String, RepositoryModel> repositories = new HashMap<String, RepositoryModel>();
for (RepositoryModel model : list) {
String url = MessageFormat.format(cloneUrl, model.name);
repositories.put(url, model);
}
result = repositories;
} else if (RpcRequest.LIST_USERS.equals(reqType)) {
// list users
if (user == null || !user.canAdmin) {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
// user is authorized to retrieve all accounts
List<String> names = GitBlit.self().getAllUsernames();
List<UserModel> users = new ArrayList<UserModel>();
for (String name : names) {
users.add(GitBlit.self().getUserModel(name));
}
result = users;
}
// send the result of the request
serialize(response, result);
}
}

+ 57
- 168
src/com/gitblit/utils/FederationUtils.java View File

@@ -15,17 +15,7 @@
*/
package com.gitblit.utils;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
@@ -34,28 +24,21 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.Constants;
import com.gitblit.Constants.FederationProposalResult;
import com.gitblit.Constants.FederationRequest;
import com.gitblit.FederationServlet;
import com.gitblit.Constants.FederationToken;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
/**
@@ -66,8 +49,6 @@ import com.google.gson.reflect.TypeToken;
*/
public class FederationUtils {
public static final String CHARSET;
public static final Type REPOSITORIES_TYPE = new TypeToken<Map<String, RepositoryModel>>() {
}.getType();
@@ -80,23 +61,48 @@ public class FederationUtils {
public static final Type RESULTS_TYPE = new TypeToken<List<FederationModel>>() {
}.getType();
private static final SSLContext SSL_CONTEXT;
private static final DummyHostnameVerifier HOSTNAME_VERIFIER;
private static final Logger LOGGER = LoggerFactory.getLogger(FederationUtils.class);
static {
SSLContext context = null;
try {
context = SSLContext.getInstance("SSL");
context.init(null, new TrustManager[] { new DummyTrustManager() }, new SecureRandom());
} catch (Throwable t) {
t.printStackTrace();
/**
* Returns an url to this servlet for the specified parameters.
*
* @param sourceURL
* the url of the source gitblit instance
* @param token
* the federation token of the source gitblit instance
* @param req
* the pull type request
*/
public static String asLink(String sourceURL, String token, FederationRequest req) {
return asLink(sourceURL, null, token, req, null);
}
/**
*
* @param remoteURL
* the url of the remote gitblit instance
* @param tokenType
* the type of federation token of a gitblit instance
* @param token
* the federation token of a gitblit instance
* @param req
* the pull type request
* @param myURL
* the url of this gitblit instance
* @return
*/
public static String asLink(String remoteURL, FederationToken tokenType, String token,
FederationRequest req, String myURL) {
if (remoteURL.length() > 0 && remoteURL.charAt(remoteURL.length() - 1) == '/') {
remoteURL = remoteURL.substring(0, remoteURL.length() - 1);
}
if (req == null) {
req = FederationRequest.PULL_REPOSITORIES;
}
SSL_CONTEXT = context;
HOSTNAME_VERIFIER = new DummyHostnameVerifier();
CHARSET = "UTF-8";
return remoteURL + Constants.FEDERATION_PATH + "?req=" + req.name().toLowerCase()
+ (token == null ? "" : ("&token=" + token))
+ (tokenType == null ? "" : ("&tokenType=" + tokenType.name().toLowerCase()))
+ (myURL == null ? "" : ("&url=" + StringUtils.encodeURL(myURL)));
}
/**
@@ -195,10 +201,9 @@ public class FederationUtils {
* @return true if there is a route to the remoteUrl
*/
public static boolean poke(String remoteUrl) throws Exception {
String url = FederationServlet.asFederationLink(remoteUrl, null, FederationRequest.POKE);
Gson gson = new Gson();
String json = gson.toJson("POKE");
int status = writeJson(url, json);
String url = asLink(remoteUrl, null, FederationRequest.POKE);
String json = JsonUtils.toJsonString("POKE");
int status = JsonUtils.sendJsonString(url, json);
return status == HttpServletResponse.SC_OK;
}
@@ -213,11 +218,9 @@ public class FederationUtils {
*/
public static FederationProposalResult propose(String remoteUrl, FederationProposal proposal)
throws Exception {
String url = FederationServlet
.asFederationLink(remoteUrl, null, FederationRequest.PROPOSAL);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(proposal);
int status = writeJson(url, json);
String url = asLink(remoteUrl, null, FederationRequest.PROPOSAL);
String json = JsonUtils.toJsonString(proposal);
int status = JsonUtils.sendJsonString(url, json);
switch (status) {
case HttpServletResponse.SC_FORBIDDEN:
// remote Gitblit Federation disabled
@@ -251,9 +254,9 @@ public class FederationUtils {
*/
public static Map<String, RepositoryModel> getRepositories(FederationModel registration,
boolean checkExclusions) throws Exception {
String url = FederationServlet.asFederationLink(registration.url, registration.token,
String url = asLink(registration.url, registration.token,
FederationRequest.PULL_REPOSITORIES);
Map<String, RepositoryModel> models = readGson(url, REPOSITORIES_TYPE);
Map<String, RepositoryModel> models = JsonUtils.retrieveJson(url, REPOSITORIES_TYPE);
if (checkExclusions) {
Map<String, RepositoryModel> includedModels = new HashMap<String, RepositoryModel>();
for (Map.Entry<String, RepositoryModel> entry : models.entrySet()) {
@@ -274,9 +277,8 @@ public class FederationUtils {
* @throws Exception
*/
public static Collection<UserModel> getUsers(FederationModel registration) throws Exception {
String url = FederationServlet.asFederationLink(registration.url, registration.token,
FederationRequest.PULL_USERS);
Collection<UserModel> models = readGson(url, USERS_TYPE);
String url = asLink(registration.url, registration.token, FederationRequest.PULL_USERS);
Collection<UserModel> models = JsonUtils.retrieveJson(url, USERS_TYPE);
return models;
}
@@ -289,9 +291,8 @@ public class FederationUtils {
* @throws Exception
*/
public static Map<String, String> getSettings(FederationModel registration) throws Exception {
String url = FederationServlet.asFederationLink(registration.url, registration.token,
FederationRequest.PULL_SETTINGS);
Map<String, String> settings = readGson(url, SETTINGS_TYPE);
String url = asLink(registration.url, registration.token, FederationRequest.PULL_SETTINGS);
Map<String, String> settings = JsonUtils.retrieveJson(url, SETTINGS_TYPE);
return settings;
}
@@ -309,122 +310,10 @@ public class FederationUtils {
*/
public static boolean acknowledgeStatus(String identification, FederationModel registration)
throws Exception {
String url = FederationServlet.asFederationLink(registration.url, null, registration.token,
FederationRequest.STATUS, identification);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(registration);
int status = writeJson(url, json);
String url = asLink(registration.url, null, registration.token, FederationRequest.STATUS,
identification);
String json = JsonUtils.toJsonString(registration);
int status = JsonUtils.sendJsonString(url, json);
return status == HttpServletResponse.SC_OK;
}
/**
* Reads a gson object from the specified url.
*
* @param url
* @param type
* @return
* @throws Exception
*/
public static <X> X readGson(String url, Type type) throws Exception {
String json = readJson(url);
if (StringUtils.isEmpty(json)) {
return null;
}
Gson gson = new Gson();
return gson.fromJson(json, type);
}
/**
* Reads a JSON response.
*
* @param url
* @return the JSON response as a string
* @throws Exception
*/
public static String readJson(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);
}
is.close();
return json.toString();
}
/**
* Writes a JSON message to the specified url.
*
* @param url
* the url to write to
* @param json
* the json message to send
* @return the http request result code
* @throws Exception
*/
public static int writeJson(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);
}
// write json body
OutputStream os = conn.getOutputStream();
os.write(jsonBytes);
os.close();
int status = ((HttpURLConnection) conn).getResponseCode();
return status;
}
/**
* DummyTrustManager trusts all certificates.
*/
private static class DummyTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType)
throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
/**
* Trusts all hostnames from a certificate, including self-signed certs.
*/
private static class DummyHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
}

+ 224
- 0
src/com/gitblit/utils/JsonUtils.java View File

@@ -0,0 +1,224 @@
/*
* 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.utils;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
/**
* Utility methods for gson calls to a Gitblit server.
*
* @author James Moger
*
*/
public class JsonUtils {
public static final String CHARSET;
public static final Type REPOSITORIES_TYPE = new TypeToken<Map<String, RepositoryModel>>() {
}.getType();
public static final Type USERS_TYPE = new TypeToken<Collection<UserModel>>() {
}.getType();
private static final SSLContext SSL_CONTEXT;
private static final DummyHostnameVerifier HOSTNAME_VERIFIER;
static {
SSLContext context = null;
try {
context = SSLContext.getInstance("SSL");
context.init(null, new TrustManager[] { new DummyTrustManager() }, new SecureRandom());
} catch (Throwable t) {
t.printStackTrace();
}
SSL_CONTEXT = context;
HOSTNAME_VERIFIER = new DummyHostnameVerifier();
CHARSET = "UTF-8";
}
/**
* Creates JSON from the specified object.
*
* @param o
* @return json
*/
public static String toJsonString(Object o) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(o);
return json;
}
/**
* Convert a json string to an object of the specified type.
*
* @param json
* @param clazz
* @return an object
*/
public static <X> X fromJsonString(String json, Class<X> clazz) {
Gson gson = new Gson();
return gson.fromJson(json, clazz);
}
/**
* Convert a json string to an object of the specified type.
*
* @param json
* @param clazz
* @return an object
*/
public static <X> X fromJsonString(String json, Type type) {
Gson gson = new Gson();
return gson.fromJson(json, type);
}
/**
* Reads a gson object from the specified url.
*
* @param url
* @param type
* @return
* @throws Exception
*/
public static <X> X retrieveJson(String url, Type type) throws Exception {
String json = retrieveJsonString(url);
if (StringUtils.isEmpty(json)) {
return null;
}
Gson gson = new Gson();
return gson.fromJson(json, type);
}
/**
* Retrieves a JSON message.
*
* @param url
* @return the JSON message as a string
* @throws Exception
*/
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);
}
is.close();
return json.toString();
}
/**
* Sends a JSON message.
*
* @param url
* the url to write to
* @param json
* the json message to send
* @return the http request result code
* @throws Exception
*/
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);
}
// write json body
OutputStream os = conn.getOutputStream();
os.write(jsonBytes);
os.close();
int status = ((HttpURLConnection) conn).getResponseCode();
return status;
}
/**
* DummyTrustManager trusts all certificates.
*/
private static class DummyTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType)
throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
/**
* Trusts all hostnames from a certificate, including self-signed certs.
*/
private static class DummyHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
}

+ 86
- 0
src/com/gitblit/utils/RpcUtils.java View File

@@ -0,0 +1,86 @@
/*
* 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.utils;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Map;
import com.gitblit.Constants;
import com.gitblit.Constants.RpcRequest;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.google.gson.reflect.TypeToken;
/**
* Utility methods for rpc calls.
*
* @author James Moger
*
*/
public class RpcUtils {
public static final Type REPOSITORIES_TYPE = new TypeToken<Map<String, RepositoryModel>>() {
}.getType();
public static final Type USERS_TYPE = new TypeToken<Collection<UserModel>>() {
}.getType();
/**
*
* @param remoteURL
* the url of the remote gitblit instance
* @param req
* the rpc request type
* @return
*/
public static String asLink(String remoteURL, RpcRequest req) {
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();
}
/**
* Retrieves a map of the repositories at the remote gitblit instance keyed
* by the repository clone url.
*
* @param serverUrl
* @return a map of cloneable repositories
* @throws Exception
*/
public static Map<String, RepositoryModel> getRepositories(String serverUrl) throws Exception {
String url = asLink(serverUrl, RpcRequest.LIST_REPOSITORIES);
Map<String, RepositoryModel> models = JsonUtils.retrieveJson(url, REPOSITORIES_TYPE);
return models;
}
/**
* Tries to pull the gitblit user accounts from the remote gitblit instance.
*
* @param serverUrl
* @return a collection of UserModel objects
* @throws Exception
*/
public static Collection<UserModel> getUsers(String serverUrl) throws Exception {
String url = asLink(serverUrl, RpcRequest.LIST_USERS);
Collection<UserModel> models = JsonUtils.retrieveJson(url, USERS_TYPE);
return models;
}
}

+ 4
- 4
src/com/gitblit/wicket/panels/FederationTokensPanel.java View File

@@ -28,9 +28,9 @@ import org.apache.wicket.markup.repeater.data.ListDataProvider;
import com.gitblit.Constants.FederationRequest;
import com.gitblit.Constants.FederationToken;
import com.gitblit.FederationServlet;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.utils.FederationUtils;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.pages.SendProposalPage;
@@ -42,11 +42,11 @@ public class FederationTokensPanel extends BasePanel {
super(wicketId);
final String baseUrl = WicketUtils.getGitblitURL(getRequest());
add(new ExternalLink("federatedUsers", FederationServlet.asFederationLink(baseUrl, GitBlit.self()
add(new ExternalLink("federatedUsers", FederationUtils.asLink(baseUrl, GitBlit.self()
.getFederationToken(FederationToken.USERS_AND_REPOSITORIES),
FederationRequest.PULL_USERS)));
add(new ExternalLink("federatedSettings", FederationServlet.asFederationLink(baseUrl, GitBlit
add(new ExternalLink("federatedSettings", FederationUtils.asLink(baseUrl, GitBlit
.self().getFederationToken(FederationToken.ALL), FederationRequest.PULL_SETTINGS)));
final List<String[]> data = new ArrayList<String[]>();
@@ -83,7 +83,7 @@ public class FederationTokensPanel extends BasePanel {
}
item.add(new Label("value", entry[1]));
item.add(new ExternalLink("repositoryDefinitions", FederationServlet.asFederationLink(
item.add(new ExternalLink("repositoryDefinitions", FederationUtils.asLink(
baseUrl, entry[1], FederationRequest.PULL_REPOSITORIES)));
item.add(new BookmarkablePageLink<Void>("send",

+ 5
- 8
tests/com/gitblit/tests/FederationTests.java View File

@@ -27,12 +27,11 @@ import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.FederationProposalResult;
import com.gitblit.Constants.FederationRequest;
import com.gitblit.Constants.FederationToken;
import com.gitblit.FederationServlet;
import com.gitblit.GitBlitServer;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.RepositoryModel;
import com.gitblit.utils.FederationUtils;
import com.google.gson.Gson;
import com.gitblit.utils.JsonUtils;
public class FederationTests extends TestCase {
@@ -66,10 +65,8 @@ public class FederationTests extends TestCase {
}
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}}";
Gson gson = new Gson();
Map<String, RepositoryModel> models = gson
.fromJson(json, FederationUtils.REPOSITORIES_TYPE);
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());
}
@@ -99,9 +96,9 @@ public class FederationTests extends TestCase {
public void testPullRepositories() throws Exception {
try {
String url = FederationServlet.asFederationLink("http://localhost:" + port,
String url = FederationUtils.asLink("http://localhost:" + port,
"testtoken", FederationRequest.PULL_REPOSITORIES);
String json = FederationUtils.readJson(url);
String json = JsonUtils.retrieveJsonString(url);
} catch (IOException e) {
if (!e.getMessage().contains("403")) {
throw e;

+ 40
- 0
tests/com/gitblit/tests/RpcTests.java View File

@@ -0,0 +1,40 @@
/*
* 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.tests;
import java.io.IOException;
import java.util.Map;
import junit.framework.TestCase;
import com.gitblit.models.RepositoryModel;
import com.gitblit.utils.RpcUtils;
public class RpcTests extends TestCase {
public void testListRepositories() throws Exception {
Map<String, RepositoryModel> map = null;
try {
map = RpcUtils.getRepositories("https://localhost:8443");
} catch (IOException e) {
if (!e.getMessage().contains("403")) {
throw e;
}
}
assertTrue("Repository list is null!", map != null);
assertTrue("Repository list is empty!", map.size() > 0);
}
}

Loading…
Cancel
Save