summaryrefslogtreecommitdiffstats
path: root/src/main/java/com/gitblit/GitBlit.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/gitblit/GitBlit.java')
-rw-r--r--src/main/java/com/gitblit/GitBlit.java1106
1 files changed, 99 insertions, 1007 deletions
diff --git a/src/main/java/com/gitblit/GitBlit.java b/src/main/java/com/gitblit/GitBlit.java
index 493f8fce..ca676ff9 100644
--- a/src/main/java/com/gitblit/GitBlit.java
+++ b/src/main/java/com/gitblit/GitBlit.java
@@ -15,50 +15,25 @@
*/
package com.gitblit;
-import java.io.BufferedReader;
import java.io.File;
-import java.io.FileFilter;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
import java.io.OutputStream;
-import java.lang.reflect.Type;
import java.text.MessageFormat;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
-import javax.servlet.http.HttpServletRequest;
-import org.apache.wicket.resource.ContextRelativeResource;
-import org.apache.wicket.util.resource.ResourceStreamNotFoundException;
-import org.slf4j.Logger;
-
-import com.gitblit.Constants.AccessPermission;
-import com.gitblit.Constants.AccessRestrictionType;
-import com.gitblit.Constants.FederationRequest;
-import com.gitblit.Constants.FederationToken;
import com.gitblit.dagger.DaggerContextListener;
-import com.gitblit.fanout.FanoutNioService;
-import com.gitblit.fanout.FanoutService;
-import com.gitblit.fanout.FanoutSocketService;
-import com.gitblit.git.GitDaemon;
import com.gitblit.git.GitServlet;
import com.gitblit.manager.IFederationManager;
import com.gitblit.manager.IGitblitManager;
@@ -67,80 +42,54 @@ import com.gitblit.manager.INotificationManager;
import com.gitblit.manager.IProjectManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
+import com.gitblit.manager.IServicesManager;
import com.gitblit.manager.ISessionManager;
import com.gitblit.manager.IUserManager;
-import com.gitblit.models.FederationModel;
-import com.gitblit.models.FederationProposal;
-import com.gitblit.models.FederationSet;
-import com.gitblit.models.GitClientApplication;
-import com.gitblit.models.RepositoryModel;
-import com.gitblit.models.RepositoryUrl;
-import com.gitblit.models.ServerSettings;
-import com.gitblit.models.SettingModel;
-import com.gitblit.models.TeamModel;
-import com.gitblit.models.UserModel;
-import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.ContainerUtils;
-import com.gitblit.utils.FederationUtils;
-import com.gitblit.utils.HttpUtils;
-import com.gitblit.utils.JGitUtils;
-import com.gitblit.utils.JsonUtils;
-import com.gitblit.utils.ObjectCache;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitblitWicketFilter;
-import com.gitblit.wicket.WicketUtils;
-import com.google.gson.Gson;
-import com.google.gson.JsonIOException;
-import com.google.gson.JsonSyntaxException;
-import com.google.gson.reflect.TypeToken;
import dagger.ObjectGraph;
/**
- * GitBlit is the servlet context listener singleton that acts as the core for
- * the web ui and the servlets. This class is either directly instantiated by
- * the GitBlitServer class (Gitblit GO) or is reflectively instantiated by the
- * servlet 3 container (Gitblit WAR or Express).
+ * This class is the main entry point for the entire webapp. It is a singleton
+ * created manually by Gitblit GO or dynamically by the WAR/Express servlet
+ * container. This class instantiates and starts all managers followed by
+ * instantiating and registering all servlets and filters.
*
- * This class is the central logic processor for Gitblit. All settings, user
- * object, and repository object operations pass through this class.
+ * Leveraging Servlet 3 and Dagger static dependency injection allows Gitblit to
+ * be modular and completely code-driven rather then relying on the fragility of
+ * a web.xml descriptor and the static & monolithic design previously used.
*
* @author James Moger
*
*/
@WebListener
-public class GitBlit extends DaggerContextListener
- implements IFederationManager,
- IGitblitManager {
+public class GitBlit extends DaggerContextListener {
private static GitBlit gitblit;
- private final IStoredSettings goSettings;
-
- private final File goBaseFolder;
-
private final List<IManager> managers = new ArrayList<IManager>();
- private final ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(10);
-
- private final List<FederationModel> federationRegistrations = Collections
- .synchronizedList(new ArrayList<FederationModel>());
-
- private final ObjectCache<Collection<GitClientApplication>> clientApplications = new ObjectCache<Collection<GitClientApplication>>();
-
- private final Map<String, FederationModel> federationPullResults = new ConcurrentHashMap<String, FederationModel>();
-
- private IStoredSettings settings;
-
- private FanoutService fanoutService;
+ private final IStoredSettings goSettings;
- private GitDaemon gitDaemon;
+ private final File goBaseFolder;
+ /**
+ * Construct a Gitblit WAR/Express context.
+ */
public GitBlit() {
this.goSettings = null;
this.goBaseFolder = null;
+ gitblit = this;
}
+ /**
+ * Construct a Gitblit GO context.
+ *
+ * @param settings
+ * @param baseFolder
+ */
public GitBlit(IStoredSettings settings, File baseFolder) {
this.goSettings = settings;
this.goBaseFolder = baseFolder;
@@ -148,20 +97,13 @@ public class GitBlit extends DaggerContextListener
}
/**
- * Returns the Gitblit singleton.
+ * This method is only used for unit and integration testing.
*
- * @return gitblit singleton
+ * @param managerClass
+ * @return a manager
*/
- public static GitBlit self() {
- return gitblit;
- }
-
@SuppressWarnings("unchecked")
- public static <X> X getManager(Class<X> managerClass) {
- if (managerClass.isAssignableFrom(GitBlit.class)) {
- return (X) gitblit;
- }
-
+ public static <X extends IManager> X getManager(Class<X> managerClass) {
for (IManager manager : gitblit.managers) {
if (managerClass.isAssignableFrom(manager.getClass())) {
return (X) manager;
@@ -171,786 +113,15 @@ public class GitBlit extends DaggerContextListener
}
/**
- * Returns the path of the proposals folder. This method checks to see if
- * Gitblit is running on a cloud service and may return an adjusted path.
- *
- * @return the proposals folder path
- */
- @Override
- public File getProposalsFolder() {
- return getManager(IRuntimeManager.class).getFileOrFolder(Keys.federation.proposalsFolder, "${baseFolder}/proposals");
- }
-
- /**
- * Returns a list of repository URLs and the user access permission.
- *
- * @param request
- * @param user
- * @param repository
- * @return a list of repository urls
- */
- @Override
- public List<RepositoryUrl> getRepositoryUrls(HttpServletRequest request, UserModel user, RepositoryModel repository) {
- if (user == null) {
- user = UserModel.ANONYMOUS;
- }
- String username = StringUtils.encodeUsername(UserModel.ANONYMOUS.equals(user) ? "" : user.username);
-
- List<RepositoryUrl> list = new ArrayList<RepositoryUrl>();
- // http/https url
- if (settings.getBoolean(Keys.git.enableGitServlet, true)) {
- AccessPermission permission = user.getRepositoryPermission(repository).permission;
- if (permission.exceeds(AccessPermission.NONE)) {
- list.add(new RepositoryUrl(getRepositoryUrl(request, username, repository), permission));
- }
- }
-
- // git daemon url
- String gitDaemonUrl = getGitDaemonUrl(request, user, repository);
- if (!StringUtils.isEmpty(gitDaemonUrl)) {
- AccessPermission permission = getGitDaemonAccessPermission(user, repository);
- if (permission.exceeds(AccessPermission.NONE)) {
- list.add(new RepositoryUrl(gitDaemonUrl, permission));
- }
- }
-
- // add all other urls
- // {0} = repository
- // {1} = username
- for (String url : settings.getStrings(Keys.web.otherUrls)) {
- if (url.contains("{1}")) {
- // external url requires username, only add url IF we have one
- if(!StringUtils.isEmpty(username)) {
- list.add(new RepositoryUrl(MessageFormat.format(url, repository.name, username), null));
- }
- } else {
- // external url does not require username
- list.add(new RepositoryUrl(MessageFormat.format(url, repository.name), null));
- }
- }
- return list;
- }
-
- protected String getRepositoryUrl(HttpServletRequest request, String username, RepositoryModel repository) {
- StringBuilder sb = new StringBuilder();
- sb.append(HttpUtils.getGitblitURL(request));
- sb.append(Constants.GIT_PATH);
- sb.append(repository.name);
-
- // inject username into repository url if authentication is required
- if (repository.accessRestriction.exceeds(AccessRestrictionType.NONE)
- && !StringUtils.isEmpty(username)) {
- sb.insert(sb.indexOf("://") + 3, username + "@");
- }
- return sb.toString();
- }
-
- protected String getGitDaemonUrl(HttpServletRequest request, UserModel user, RepositoryModel repository) {
- if (gitDaemon != null) {
- String bindInterface = settings.getString(Keys.git.daemonBindInterface, "localhost");
- if (bindInterface.equals("localhost")
- && (!request.getServerName().equals("localhost") && !request.getServerName().equals("127.0.0.1"))) {
- // git daemon is bound to localhost and the request is from elsewhere
- return null;
- }
- if (user.canClone(repository)) {
- String servername = request.getServerName();
- String url = gitDaemon.formatUrl(servername, repository.name);
- return url;
- }
- }
- return null;
- }
-
- protected AccessPermission getGitDaemonAccessPermission(UserModel user, RepositoryModel repository) {
- if (gitDaemon != null && user.canClone(repository)) {
- AccessPermission gitDaemonPermission = user.getRepositoryPermission(repository).permission;
- if (gitDaemonPermission.atLeast(AccessPermission.CLONE)) {
- if (repository.accessRestriction.atLeast(AccessRestrictionType.CLONE)) {
- // can not authenticate clone via anonymous git protocol
- gitDaemonPermission = AccessPermission.NONE;
- } else if (repository.accessRestriction.atLeast(AccessRestrictionType.PUSH)) {
- // can not authenticate push via anonymous git protocol
- gitDaemonPermission = AccessPermission.CLONE;
- } else {
- // normal user permission
- }
- }
- return gitDaemonPermission;
- }
- return AccessPermission.NONE;
- }
-
- /**
- * Returns the list of custom client applications to be used for the
- * repository url panel;
- *
- * @return a collection of client applications
- */
- @Override
- public Collection<GitClientApplication> getClientApplications() {
- // prefer user definitions, if they exist
- File userDefs = new File(getManager(IRuntimeManager.class).getBaseFolder(), "clientapps.json");
- if (userDefs.exists()) {
- Date lastModified = new Date(userDefs.lastModified());
- if (clientApplications.hasCurrent("user", lastModified)) {
- return clientApplications.getObject("user");
- } else {
- // (re)load user definitions
- try {
- InputStream is = new FileInputStream(userDefs);
- Collection<GitClientApplication> clients = readClientApplications(is);
- is.close();
- if (clients != null) {
- clientApplications.updateObject("user", lastModified, clients);
- return clients;
- }
- } catch (IOException e) {
- logger.error("Failed to deserialize " + userDefs.getAbsolutePath(), e);
- }
- }
- }
-
- // no user definitions, use system definitions
- if (!clientApplications.hasCurrent("system", new Date(0))) {
- try {
- InputStream is = getClass().getResourceAsStream("/clientapps.json");
- Collection<GitClientApplication> clients = readClientApplications(is);
- is.close();
- if (clients != null) {
- clientApplications.updateObject("system", new Date(0), clients);
- }
- } catch (IOException e) {
- logger.error("Failed to deserialize clientapps.json resource!", e);
- }
- }
-
- return clientApplications.getObject("system");
- }
-
- private Collection<GitClientApplication> readClientApplications(InputStream is) {
- try {
- Type type = new TypeToken<Collection<GitClientApplication>>() {
- }.getType();
- InputStreamReader reader = new InputStreamReader(is);
- Gson gson = JsonUtils.gson();
- Collection<GitClientApplication> links = gson.fromJson(reader, type);
- return links;
- } catch (JsonIOException e) {
- logger.error("Error deserializing client applications!", e);
- } catch (JsonSyntaxException e) {
- logger.error("Error deserializing client applications!", e);
- }
- return null;
- }
-
- /**
- * Open a file resource using the Servlet container.
- * @param file to open
- * @return InputStream of the opened file
- * @throws ResourceStreamNotFoundException
- */
- public InputStream getResourceAsStream(String file) throws ResourceStreamNotFoundException {
- ContextRelativeResource res = WicketUtils.getResource(file);
- return res.getResourceStream().getInputStream();
- }
-
- @Override
- public UserModel getFederationUser() {
- // the federation user is an administrator
- UserModel federationUser = new UserModel(Constants.FEDERATION_USER);
- federationUser.canAdmin = true;
- return federationUser;
- }
-
- /**
- * Adds/updates a complete user object keyed by username. This method allows
- * for renaming a user.
- *
- * @see IUserService.updateUserModel(String, UserModel)
- * @param username
- * @param user
- * @param isCreate
- * @throws GitBlitException
- */
- @Override
- public void updateUserModel(String username, UserModel user, boolean isCreate)
- throws GitBlitException {
- if (!username.equalsIgnoreCase(user.username)) {
- if (getManager(IUserManager.class).getUserModel(user.username) != null) {
- throw new GitBlitException(MessageFormat.format(
- "Failed to rename ''{0}'' because ''{1}'' already exists.", username,
- user.username));
- }
-
- // rename repositories and owner fields for all repositories
- for (RepositoryModel model : getManager(IRepositoryManager.class).getRepositoryModels(user)) {
- if (model.isUsersPersonalRepository(username)) {
- // personal repository
- model.addOwner(user.username);
- String oldRepositoryName = model.name;
- model.name = user.getPersonalPath() + model.name.substring(model.projectPath.length());
- model.projectPath = user.getPersonalPath();
- getManager(IRepositoryManager.class).updateRepositoryModel(oldRepositoryName, model, false);
- } else if (model.isOwner(username)) {
- // common/shared repo
- model.addOwner(user.username);
- getManager(IRepositoryManager.class).updateRepositoryModel(model.name, model, false);
- }
- }
- }
- if (!getManager(IUserManager.class).updateUserModel(username, user)) {
- throw new GitBlitException(isCreate ? "Failed to add user!" : "Failed to update user!");
- }
- }
-
- /**
- * Updates the TeamModel object for the specified name.
- *
- * @param teamname
- * @param team
- * @param isCreate
- */
- @Override
- public void updateTeamModel(String teamname, TeamModel team, boolean isCreate)
- throws GitBlitException {
- if (!teamname.equalsIgnoreCase(team.name)) {
- if (getManager(IUserManager.class).getTeamModel(team.name) != null) {
- throw new GitBlitException(MessageFormat.format(
- "Failed to rename ''{0}'' because ''{1}'' already exists.", teamname,
- team.name));
- }
- }
- if (!getManager(IUserManager.class).updateTeamModel(teamname, team)) {
- throw new GitBlitException(isCreate ? "Failed to add team!" : "Failed to update team!");
- }
- }
-
-
- /**
- * Returns Gitblit's scheduled executor service for scheduling tasks.
- *
- * @return scheduledExecutor
- */
- public ScheduledExecutorService executor() {
- return scheduledExecutor;
- }
-
- @Override
- public boolean canFederate() {
- String passphrase = settings.getString(Keys.federation.passphrase, "");
- return !StringUtils.isEmpty(passphrase);
- }
-
- /**
- * Configures this Gitblit instance to pull any registered federated gitblit
- * instances.
- */
- private void configureFederation() {
- boolean validPassphrase = true;
- String passphrase = settings.getString(Keys.federation.passphrase, "");
- if (StringUtils.isEmpty(passphrase)) {
- logger.warn("Federation passphrase is blank! This server can not be PULLED from.");
- validPassphrase = false;
- }
- if (validPassphrase) {
- // standard tokens
- for (FederationToken tokenType : FederationToken.values()) {
- logger.info(MessageFormat.format("Federation {0} token = {1}", tokenType.name(),
- getFederationToken(tokenType)));
- }
-
- // federation set tokens
- for (String set : settings.getStrings(Keys.federation.sets)) {
- logger.info(MessageFormat.format("Federation Set {0} token = {1}", set,
- getFederationToken(set)));
- }
- }
-
- // Schedule the federation executor
- List<FederationModel> registrations = getFederationRegistrations();
- if (registrations.size() > 0) {
- FederationPullExecutor executor = new FederationPullExecutor(registrations, true);
- scheduledExecutor.schedule(executor, 1, TimeUnit.MINUTES);
- }
- }
-
- /**
- * Returns the list of federated gitblit instances that this instance will
- * try to pull.
- *
- * @return list of registered gitblit instances
- */
- @Override
- public List<FederationModel> getFederationRegistrations() {
- if (federationRegistrations.isEmpty()) {
- federationRegistrations.addAll(FederationUtils.getFederationRegistrations(settings));
- }
- return federationRegistrations;
- }
-
- /**
- * Retrieve the specified federation registration.
- *
- * @param name
- * the name of the registration
- * @return a federation registration
- */
- @Override
- public FederationModel getFederationRegistration(String url, String name) {
- // check registrations
- for (FederationModel r : getFederationRegistrations()) {
- if (r.name.equals(name) && r.url.equals(url)) {
- return r;
- }
- }
-
- // check the results
- for (FederationModel r : getFederationResultRegistrations()) {
- if (r.name.equals(name) && r.url.equals(url)) {
- return r;
- }
- }
- return null;
- }
-
- /**
- * Returns the list of federation sets.
- *
- * @return list of federation sets
- */
- @Override
- 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.
- *
- * @return list of federation tokens
- */
- @Override
- public List<String> getFederationTokens() {
- List<String> tokens = new ArrayList<String>();
- // generate standard tokens
- for (FederationToken type : FederationToken.values()) {
- tokens.add(getFederationToken(type));
- }
- // generate tokens for federation sets
- for (String set : settings.getStrings(Keys.federation.sets)) {
- tokens.add(getFederationToken(set));
- }
- return tokens;
- }
-
- /**
- * Returns the specified federation token for this Gitblit instance.
- *
- * @param type
- * @return a federation token
- */
- @Override
- public String getFederationToken(FederationToken type) {
- return getFederationToken(type.name());
- }
-
- /**
- * Returns the specified federation token for this Gitblit instance.
- *
- * @param value
- * @return a federation token
- */
- @Override
- public String getFederationToken(String value) {
- String passphrase = settings.getString(Keys.federation.passphrase, "");
- return StringUtils.getSHA1(passphrase + "-" + value);
- }
-
- /**
- * Compares the provided token with this Gitblit instance's tokens and
- * determines if the requested permission may be granted to the token.
- *
- * @param req
- * @param token
- * @return true if the request can be executed
- */
- @Override
- public boolean validateFederationRequest(FederationRequest req, String token) {
- String all = getFederationToken(FederationToken.ALL);
- String unr = getFederationToken(FederationToken.USERS_AND_REPOSITORIES);
- String jur = getFederationToken(FederationToken.REPOSITORIES);
- switch (req) {
- case PULL_REPOSITORIES:
- return token.equals(all) || token.equals(unr) || token.equals(jur);
- case PULL_USERS:
- case PULL_TEAMS:
- return token.equals(all) || token.equals(unr);
- case PULL_SETTINGS:
- case PULL_SCRIPTS:
- return token.equals(all);
- default:
- break;
- }
- return false;
- }
-
- /**
- * Acknowledge and cache the status of a remote Gitblit instance.
- *
- * @param identification
- * the identification of the pulling Gitblit instance
- * @param registration
- * the registration from the pulling Gitblit instance
- * @return true if acknowledged
- */
- @Override
- public boolean acknowledgeFederationStatus(String identification, FederationModel registration) {
- // reset the url to the identification of the pulling Gitblit instance
- registration.url = identification;
- String id = identification;
- if (!StringUtils.isEmpty(registration.folder)) {
- id += "-" + registration.folder;
- }
- federationPullResults.put(id, registration);
- return true;
- }
-
- /**
- * Returns the list of registration results.
- *
- * @return the list of registration results
- */
- @Override
- public List<FederationModel> getFederationResultRegistrations() {
- return new ArrayList<FederationModel>(federationPullResults.values());
- }
-
- /**
- * Submit a federation proposal. The proposal is cached locally and the
- * Gitblit administrator(s) are notified via email.
- *
- * @param proposal
- * the proposal
- * @param gitblitUrl
- * the url of your gitblit instance to send an email to
- * administrators
- * @return true if the proposal was submitted
- */
- @Override
- public boolean submitFederationProposal(FederationProposal proposal, String gitblitUrl) {
- // convert proposal to json
- String json = JsonUtils.toJsonString(proposal);
-
- try {
- // make the proposals folder
- File proposalsFolder = getProposalsFolder();
- proposalsFolder.mkdirs();
-
- // cache json to a file
- File file = new File(proposalsFolder, proposal.token + Constants.PROPOSAL_EXT);
- com.gitblit.utils.FileUtils.writeContent(file, json);
- } catch (Exception e) {
- logger.error(MessageFormat.format("Failed to cache proposal from {0}", proposal.url), e);
- }
-
- // send an email, if possible
- getManager(INotificationManager.class).sendMailToAdministrators("Federation proposal from " + proposal.url,
- "Please review the proposal @ " + gitblitUrl + "/proposal/" + proposal.token);
- return true;
- }
-
- /**
- * Returns the list of pending federation proposals
- *
- * @return list of federation proposals
- */
- @Override
- public List<FederationProposal> getPendingFederationProposals() {
- List<FederationProposal> list = new ArrayList<FederationProposal>();
- File folder = getProposalsFolder();
- if (folder.exists()) {
- File[] files = folder.listFiles(new FileFilter() {
- @Override
- public boolean accept(File file) {
- return file.isFile()
- && file.getName().toLowerCase().endsWith(Constants.PROPOSAL_EXT);
- }
- });
- for (File file : files) {
- String json = com.gitblit.utils.FileUtils.readContent(file, null);
- FederationProposal proposal = JsonUtils.fromJsonString(json,
- FederationProposal.class);
- list.add(proposal);
- }
- }
- return list;
- }
-
- /**
- * Get repositories for the specified token.
- *
- * @param gitblitUrl
- * the base url of this gitblit instance
- * @param token
- * the federation token
- * @return a map of <cloneurl, RepositoryModel>
- */
- @Override
- public Map<String, RepositoryModel> getRepositories(String gitblitUrl, String token) {
- Map<String, String> federationSets = new HashMap<String, String>();
- for (String set : settings.getStrings(Keys.federation.sets)) {
- federationSets.put(getFederationToken(set), set);
- }
-
- // Determine the Gitblit clone url
- StringBuilder sb = new StringBuilder();
- sb.append(gitblitUrl);
- sb.append(Constants.GIT_PATH);
- sb.append("{0}");
- String cloneUrl = sb.toString();
-
- // Retrieve all available repositories
- UserModel user = getFederationUser();
- List<RepositoryModel> list = getManager(IRepositoryManager.class).getRepositoryModels(user);
-
- // create the [cloneurl, repositoryModel] map
- Map<String, RepositoryModel> repositories = new HashMap<String, RepositoryModel>();
- for (RepositoryModel model : list) {
- // by default, setup the url for THIS repository
- String url = MessageFormat.format(cloneUrl, model.name);
- switch (model.federationStrategy) {
- case EXCLUDE:
- // skip this repository
- continue;
- case FEDERATE_ORIGIN:
- // federate the origin, if it is defined
- if (!StringUtils.isEmpty(model.origin)) {
- url = model.origin;
- }
- break;
- default:
- break;
- }
-
- if (federationSets.containsKey(token)) {
- // include repositories only for federation set
- String set = federationSets.get(token);
- if (model.federationSets.contains(set)) {
- repositories.put(url, model);
- }
- } else {
- // standard federation token for ALL
- repositories.put(url, model);
- }
- }
- return repositories;
- }
-
- /**
- * Creates a proposal from the token.
- *
- * @param gitblitUrl
- * the url of this Gitblit instance
- * @param token
- * @return a potential proposal
- */
- @Override
- public FederationProposal createFederationProposal(String gitblitUrl, String token) {
- FederationToken tokenType = FederationToken.REPOSITORIES;
- for (FederationToken type : FederationToken.values()) {
- if (token.equals(getFederationToken(type))) {
- tokenType = type;
- break;
- }
- }
- Map<String, RepositoryModel> repositories = getRepositories(gitblitUrl, token);
- FederationProposal proposal = new FederationProposal(gitblitUrl, tokenType, token,
- repositories);
- return proposal;
- }
-
- /**
- * Returns the proposal identified by the supplied token.
- *
- * @param token
- * @return the specified proposal or null
- */
- @Override
- public FederationProposal getPendingFederationProposal(String token) {
- List<FederationProposal> list = getPendingFederationProposals();
- for (FederationProposal proposal : list) {
- if (proposal.token.equals(token)) {
- return proposal;
- }
- }
- return null;
- }
-
- /**
- * Deletes a pending federation proposal.
- *
- * @param a
- * proposal
- * @return true if the proposal was deleted
+ * Returns Gitblit's Dagger injection modules.
*/
@Override
- public boolean deletePendingFederationProposal(FederationProposal proposal) {
- File folder = getProposalsFolder();
- File file = new File(folder, proposal.token + Constants.PROPOSAL_EXT);
- return file.delete();
- }
-
- /**
- * Parse the properties file and aggregate all the comments by the setting
- * key. A setting model tracks the current value, the default value, the
- * description of the setting and and directives about the setting.
- *
- * @return Map<String, SettingModel>
- */
- private ServerSettings loadSettingModels(ServerSettings settingsModel) {
- // this entire "supports" concept will go away with user service refactoring
- UserModel externalUser = new UserModel(Constants.EXTERNAL_ACCOUNT);
- externalUser.password = Constants.EXTERNAL_ACCOUNT;
- IUserManager userManager = getManager(IUserManager.class);
- settingsModel.supportsCredentialChanges = userManager.supportsCredentialChanges(externalUser);
- settingsModel.supportsDisplayNameChanges = userManager.supportsDisplayNameChanges(externalUser);
- settingsModel.supportsEmailAddressChanges = userManager.supportsEmailAddressChanges(externalUser);
- settingsModel.supportsTeamMembershipChanges = userManager.supportsTeamMembershipChanges(externalUser);
- try {
- // Read bundled Gitblit properties to extract setting descriptions.
- // This copy is pristine and only used for populating the setting
- // models map.
- InputStream is = getClass().getResourceAsStream("/reference.properties");
- BufferedReader propertiesReader = new BufferedReader(new InputStreamReader(is));
- StringBuilder description = new StringBuilder();
- SettingModel setting = new SettingModel();
- String line = null;
- while ((line = propertiesReader.readLine()) != null) {
- if (line.length() == 0) {
- description.setLength(0);
- setting = new SettingModel();
- } else {
- if (line.charAt(0) == '#') {
- if (line.length() > 1) {
- String text = line.substring(1).trim();
- if (SettingModel.CASE_SENSITIVE.equals(text)) {
- setting.caseSensitive = true;
- } else if (SettingModel.RESTART_REQUIRED.equals(text)) {
- setting.restartRequired = true;
- } else if (SettingModel.SPACE_DELIMITED.equals(text)) {
- setting.spaceDelimited = true;
- } else if (text.startsWith(SettingModel.SINCE)) {
- try {
- setting.since = text.split(" ")[1];
- } catch (Exception e) {
- setting.since = text;
- }
- } else {
- description.append(text);
- description.append('\n');
- }
- }
- } else {
- String[] kvp = line.split("=", 2);
- String key = kvp[0].trim();
- setting.name = key;
- setting.defaultValue = kvp[1].trim();
- setting.currentValue = setting.defaultValue;
- setting.description = description.toString().trim();
- settingsModel.add(setting);
- description.setLength(0);
- setting = new SettingModel();
- }
- }
- }
- propertiesReader.close();
- } catch (NullPointerException e) {
- logger.error("Failed to find resource copy of gitblit.properties");
- } catch (IOException e) {
- logger.error("Failed to load resource copy of gitblit.properties");
- }
- return settingsModel;
- }
-
- protected void configureFanout() {
- // startup Fanout PubSub service
- if (settings.getInteger(Keys.fanout.port, 0) > 0) {
- String bindInterface = settings.getString(Keys.fanout.bindInterface, null);
- int port = settings.getInteger(Keys.fanout.port, FanoutService.DEFAULT_PORT);
- boolean useNio = settings.getBoolean(Keys.fanout.useNio, true);
- int limit = settings.getInteger(Keys.fanout.connectionLimit, 0);
-
- if (useNio) {
- if (StringUtils.isEmpty(bindInterface)) {
- fanoutService = new FanoutNioService(port);
- } else {
- fanoutService = new FanoutNioService(bindInterface, port);
- }
- } else {
- if (StringUtils.isEmpty(bindInterface)) {
- fanoutService = new FanoutSocketService(port);
- } else {
- fanoutService = new FanoutSocketService(bindInterface, port);
- }
- }
-
- fanoutService.setConcurrentConnectionLimit(limit);
- fanoutService.setAllowAllChannelAnnouncements(false);
- fanoutService.start();
- }
- }
-
- protected void configureGitDaemon() {
- int port = settings.getInteger(Keys.git.daemonPort, 0);
- String bindInterface = settings.getString(Keys.git.daemonBindInterface, "localhost");
- if (port > 0) {
- try {
- // HACK temporary pending manager separation and injection
- Gitblit gitblit = new Gitblit(
- getManager(IRuntimeManager.class),
- getManager(INotificationManager.class),
- getManager(IUserManager.class),
- getManager(ISessionManager.class),
- getManager(IRepositoryManager.class),
- getManager(IProjectManager.class),
- this,
- this);
- gitDaemon = new GitDaemon(gitblit);
- gitDaemon.start();
- } catch (IOException e) {
- gitDaemon = null;
- logger.error(MessageFormat.format("Failed to start Git daemon on {0}:{1,number,0}", bindInterface, port), e);
- }
- }
- }
-
- protected final Logger getLogger() {
- return logger;
- }
-
- protected final ScheduledExecutorService getScheduledExecutor() {
- return scheduledExecutor;
+ protected Object [] getModules() {
+ return new Object [] { new DaggerModule() };
}
/**
- * Configure Gitblit from the web.xml, if no configuration has already been
- * specified.
- *
- * @see ServletContextListener.contextInitialize(ServletContextEvent)
+ * Prepare runtime settings and start all manager instances.
*/
@Override
protected void beforeServletInjection(ServletContext context) {
@@ -958,12 +129,10 @@ public class GitBlit extends DaggerContextListener
// create the runtime settings object
IStoredSettings runtimeSettings = injector.get(IStoredSettings.class);
- this.settings = runtimeSettings; // XXX remove me eventually
final File baseFolder;
if (goSettings != null) {
// Gitblit GO
- logger.debug("configuring Gitblit GO");
baseFolder = configureGO(context, goSettings, goBaseFolder, runtimeSettings);
} else {
// servlet container
@@ -973,11 +142,9 @@ public class GitBlit extends DaggerContextListener
if (!StringUtils.isEmpty(System.getenv("OPENSHIFT_DATA_DIR"))) {
// RedHat OpenShift
- logger.debug("configuring Gitblit Express");
baseFolder = configureExpress(context, webxmlSettings, contextFolder, runtimeSettings);
} else {
// standard WAR
- logger.debug("configuring Gitblit WAR");
baseFolder = configureWAR(context, webxmlSettings, contextFolder, runtimeSettings);
}
@@ -985,27 +152,85 @@ public class GitBlit extends DaggerContextListener
ContainerUtils.CVE_2007_0450.test(runtimeSettings);
}
- // Runtime manager is a container for settings and other parameters
- IRuntimeManager runtime = startManager(injector, IRuntimeManager.class);
+ // Manually configure IRuntimeManager
+ logManager(IRuntimeManager.class);
+ IRuntimeManager runtime = injector.get(IRuntimeManager.class);
runtime.setBaseFolder(baseFolder);
runtime.getStatus().isGO = goSettings != null;
runtime.getStatus().servletContainer = context.getServerInfo();
+ runtime.start();
+ managers.add(runtime);
+ // start all other managers
startManager(injector, INotificationManager.class);
startManager(injector, IUserManager.class);
startManager(injector, ISessionManager.class);
startManager(injector, IRepositoryManager.class);
startManager(injector, IProjectManager.class);
+ startManager(injector, IGitblitManager.class);
+ startManager(injector, IFederationManager.class);
+ startManager(injector, IServicesManager.class);
+
+ logger.info("");
+ logger.info("All managers started.");
+ logger.info("");
+ }
+
+ protected <X extends IManager> X startManager(ObjectGraph injector, Class<X> clazz) {
+ logManager(clazz);
+ X x = injector.get(clazz);
+ x.start();
+ managers.add(x);
+ return x;
+ }
+
+ protected void logManager(Class<? extends IManager> clazz) {
+ logger.info("");
+ logger.info("----[{}]----", clazz.getName());
+ }
+
+ /**
+ * Instantiate and inject all filters and servlets into the container using
+ * the servlet 3 specification.
+ */
+ @Override
+ protected void injectServlets(ServletContext context) {
+ // access restricted servlets
+ serve(context, Constants.GIT_PATH, GitServlet.class, GitFilter.class);
+ serve(context, Constants.PAGES, PagesServlet.class, PagesFilter.class);
+ serve(context, Constants.RPC_PATH, RpcServlet.class, RpcFilter.class);
+ serve(context, Constants.ZIP_PATH, DownloadZipServlet.class, DownloadZipFilter.class);
+ serve(context, Constants.SYNDICATION_PATH, SyndicationServlet.class, SyndicationFilter.class);
+
+ // servlets
+ serve(context, Constants.FEDERATION_PATH, FederationServlet.class);
+ serve(context, Constants.SPARKLESHARE_INVITE_PATH, SparkleShareInviteServlet.class);
+ serve(context, Constants.BRANCH_GRAPH_PATH, BranchGraphServlet.class);
+ file(context, "/robots.txt", RobotsTxtServlet.class);
+ file(context, "/logo.png", LogoServlet.class);
- logger.info("Gitblit base folder = " + baseFolder.getAbsolutePath());
+ // optional force basic authentication
+ filter(context, "/*", EnforceAuthenticationFilter.class, null);
- loadSettingModels(runtime.getSettingsModel());
+ // Wicket
+ String toIgnore = StringUtils.flattenStrings(getRegisteredPaths(), ",");
+ Map<String, String> params = new HashMap<String, String>();
+ params.put(GitblitWicketFilter.FILTER_MAPPING_PARAM, "/*");
+ params.put(GitblitWicketFilter.IGNORE_PATHS_PARAM, toIgnore);
+ filter(context, "/*", GitblitWicketFilter.class, params);
+ }
- if (true/*startFederation*/) {
- configureFederation();
+ /**
+ * Gitblit is being shutdown either because the servlet container is
+ * shutting down or because the servlet container is re-deploying Gitblit.
+ */
+ @Override
+ protected void destroyContext(ServletContext context) {
+ logger.info("Gitblit context destroyed by servlet container.");
+ for (IManager manager : managers) {
+ logger.debug("stopping {}", manager.getClass().getSimpleName());
+ manager.stop();
}
- configureFanout();
- configureGitDaemon();
}
/**
@@ -1023,6 +248,8 @@ public class GitBlit extends DaggerContextListener
File goBaseFolder,
IStoredSettings runtimeSettings) {
+ logger.debug("configuring Gitblit GO");
+
// merge the stored settings into the runtime settings
//
// if runtimeSettings is also a FileSettings w/o a specified target file,
@@ -1049,6 +276,7 @@ public class GitBlit extends DaggerContextListener
IStoredSettings runtimeSettings) {
// Gitblit is running in a standard servlet container
+ logger.debug("configuring Gitblit WAR");
logger.info("WAR contextFolder is " + ((contextFolder != null) ? contextFolder.getAbsolutePath() : "<empty>"));
String path = webxmlSettings.getString(Constants.baseFolder, Constants.contextFolder$ + "/WEB-INF/data");
@@ -1112,6 +340,7 @@ public class GitBlit extends DaggerContextListener
IStoredSettings runtimeSettings) {
// Gitblit is running in OpenShift/JBoss
+ logger.debug("configuring Gitblit Express");
String openShift = System.getenv("OPENSHIFT_DATA_DIR");
File base = new File(openShift);
logger.info("EXPRESS contextFolder is " + contextFolder.getAbsolutePath());
@@ -1194,141 +423,4 @@ public class GitBlit extends DaggerContextListener
}
}
}
-
- /**
- * Gitblit is being shutdown either because the servlet container is
- * shutting down or because the servlet container is re-deploying Gitblit.
- */
- @Override
- protected void destroyContext(ServletContext context) {
- logger.info("Gitblit context destroyed by servlet container.");
- for (IManager manager : managers) {
- logger.debug("stopping {}", manager.getClass().getSimpleName());
- manager.stop();
- }
-
- scheduledExecutor.shutdownNow();
- if (fanoutService != null) {
- fanoutService.stop();
- }
- if (gitDaemon != null) {
- gitDaemon.stop();
- }
- }
-
- /**
- * Creates a personal fork of the specified repository. The clone is view
- * restricted by default and the owner of the source repository is given
- * access to the clone.
- *
- * @param repository
- * @param user
- * @return the repository model of the fork, if successful
- * @throws GitBlitException
- */
- @Override
- public RepositoryModel fork(RepositoryModel repository, UserModel user) throws GitBlitException {
- String cloneName = MessageFormat.format("{0}/{1}.git", user.getPersonalPath(), StringUtils.stripDotGit(StringUtils.getLastPathElement(repository.name)));
- String fromUrl = MessageFormat.format("file://{0}/{1}", getManager(IRepositoryManager.class).getRepositoriesFolder().getAbsolutePath(), repository.name);
-
- // clone the repository
- try {
- JGitUtils.cloneRepository(getManager(IRepositoryManager.class).getRepositoriesFolder(), cloneName, fromUrl, true, null);
- } catch (Exception e) {
- throw new GitBlitException(e);
- }
-
- // create a Gitblit repository model for the clone
- RepositoryModel cloneModel = repository.cloneAs(cloneName);
- // owner has REWIND/RW+ permissions
- cloneModel.addOwner(user.username);
- getManager(IRepositoryManager.class).updateRepositoryModel(cloneName, cloneModel, false);
-
- // add the owner of the source repository to the clone's access list
- if (!ArrayUtils.isEmpty(repository.owners)) {
- for (String owner : repository.owners) {
- UserModel originOwner = getManager(IUserManager.class).getUserModel(owner);
- if (originOwner != null) {
- originOwner.setRepositoryPermission(cloneName, AccessPermission.CLONE);
- updateUserModel(originOwner.username, originOwner, false);
- }
- }
- }
-
- // grant origin's user list clone permission to fork
- List<String> users = getManager(IRepositoryManager.class).getRepositoryUsers(repository);
- List<UserModel> cloneUsers = new ArrayList<UserModel>();
- for (String name : users) {
- if (!name.equalsIgnoreCase(user.username)) {
- UserModel cloneUser = getManager(IUserManager.class).getUserModel(name);
- if (cloneUser.canClone(repository)) {
- // origin user can clone origin, grant clone access to fork
- cloneUser.setRepositoryPermission(cloneName, AccessPermission.CLONE);
- }
- cloneUsers.add(cloneUser);
- }
- }
- getManager(IUserManager.class).updateUserModels(cloneUsers);
-
- // grant origin's team list clone permission to fork
- List<String> teams = getManager(IRepositoryManager.class).getRepositoryTeams(repository);
- List<TeamModel> cloneTeams = new ArrayList<TeamModel>();
- for (String name : teams) {
- TeamModel cloneTeam = getManager(IUserManager.class).getTeamModel(name);
- if (cloneTeam.canClone(repository)) {
- // origin team can clone origin, grant clone access to fork
- cloneTeam.setRepositoryPermission(cloneName, AccessPermission.CLONE);
- }
- cloneTeams.add(cloneTeam);
- }
- getManager(IUserManager.class).updateTeamModels(cloneTeams);
-
- // add this clone to the cached model
- getManager(IRepositoryManager.class).addToCachedRepositoryList(cloneModel);
- return cloneModel;
- }
-
- @Override
- protected Object [] getModules() {
- return new Object [] { new DaggerModule(this) };
- }
-
- protected <X extends IManager> X startManager(ObjectGraph injector, Class<X> clazz) {
- logger.debug("injecting and starting {}", clazz.getSimpleName());
- X x = injector.get(clazz);
- x.setup();
- managers.add(x);
- return x;
- }
-
- /**
- * Instantiate and inject all filters and servlets into the container using
- * the servlet 3 specification.
- */
- @Override
- protected void injectServlets(ServletContext context) {
- // access restricted servlets
- serve(context, Constants.GIT_PATH, GitServlet.class, GitFilter.class);
- serve(context, Constants.PAGES, PagesServlet.class, PagesFilter.class);
- serve(context, Constants.RPC_PATH, RpcServlet.class, RpcFilter.class);
- serve(context, Constants.ZIP_PATH, DownloadZipServlet.class, DownloadZipFilter.class);
- serve(context, Constants.SYNDICATION_PATH, SyndicationServlet.class, SyndicationFilter.class);
-
- // servlets
- serve(context, Constants.FEDERATION_PATH, FederationServlet.class);
- serve(context, Constants.SPARKLESHARE_INVITE_PATH, SparkleShareInviteServlet.class);
- serve(context, Constants.BRANCH_GRAPH_PATH, BranchGraphServlet.class);
- file(context, "/robots.txt", RobotsTxtServlet.class);
- file(context, "/logo.png", LogoServlet.class);
-
- // optional force basic authentication
- filter(context, "/*", EnforceAuthenticationFilter.class, null);
-
- // Wicket
- String toIgnore = StringUtils.flattenStrings(getRegisteredPaths(), ",");
- Map<String, String> params = new HashMap<String, String>();
- params.put(GitblitWicketFilter.FILTER_MAPPING_PARAM, "/*");
- params.put(GitblitWicketFilter.IGNORE_PATHS_PARAM, toIgnore);
- filter(context, "/*", GitblitWicketFilter.class, params);
- }
}