From 892570d96cdfaf4779c1e92c89d76dabf78be361 Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Fri, 01 Jul 2011 17:47:28 -0400 Subject: [PATCH] Documentation. Adding JavaDoc comments. Adjustments to method names. --- src/com/gitblit/GitBlit.java | 324 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 294 insertions(+), 30 deletions(-) diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java index 9b66117..467d662 100644 --- a/src/com/gitblit/GitBlit.java +++ b/src/com/gitblit/GitBlit.java @@ -34,6 +34,8 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.transport.resolver.FileResolver; +import org.eclipse.jgit.transport.resolver.RepositoryResolver; +import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException; import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; import org.eclipse.jgit.util.FileUtils; import org.slf4j.Logger; @@ -45,13 +47,29 @@ import com.gitblit.utils.JGitUtils; import com.gitblit.utils.StringUtils; +/** + * 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 from the + * definition in the web.xml file (Gitblit WAR). + * + * This class is the central logic processor for Gitblit. All settings, user + * object, and repository object operations pass through this class. + * + * Repository Resolution. There are two pathways for finding repositories. One + * pathway, for web ui display and repository authentication & authorization, is + * within this class. The other pathway is through the standard GitServlet. + * + * @author James Moger + * + */ public class GitBlit implements ServletContextListener { private static GitBlit gitblit; private final Logger logger = LoggerFactory.getLogger(GitBlit.class); - private FileResolver<Void> repositoryResolver; + private RepositoryResolver<Void> repositoryResolver; private File repositoriesFolder; @@ -59,59 +77,136 @@ private IUserService userService; - private IStoredSettings storedSettings; + private IStoredSettings settings; public GitBlit() { if (gitblit == null) { - // Singleton reference when running in standard servlet container + // set the static singleton reference gitblit = this; } } + /** + * Returns the Gitblit singleton. + * + * @return gitblit singleton + */ public static GitBlit self() { if (gitblit == null) { - gitblit = new GitBlit(); + new GitBlit(); } return gitblit; } + /** + * Returns the boolean value for the specified key. If the key does not + * exist or the value for the key can not be interpreted as a boolean, the + * defaultValue is returned. + * + * @see IStoredSettings.getBoolean(String, boolean) + * @param key + * @param defaultValue + * @return key value or defaultValue + */ public static boolean getBoolean(String key, boolean defaultValue) { - return self().storedSettings.getBoolean(key, defaultValue); + return self().settings.getBoolean(key, defaultValue); } + /** + * Returns the integer value for the specified key. If the key does not + * exist or the value for the key can not be interpreted as an integer, the + * defaultValue is returned. + * + * @see IStoredSettings.getInteger(String key, int defaultValue) + * @param key + * @param defaultValue + * @return key value or defaultValue + */ public static int getInteger(String key, int defaultValue) { - return self().storedSettings.getInteger(key, defaultValue); + return self().settings.getInteger(key, defaultValue); } + /** + * Returns the string value for the specified key. If the key does not exist + * or the value for the key can not be interpreted as a string, the + * defaultValue is returned. + * + * @see IStoredSettings.getString(String key, String defaultValue) + * @param key + * @param defaultValue + * @return key value or defaultValue + */ public static String getString(String key, String defaultValue) { - return self().storedSettings.getString(key, defaultValue); + return self().settings.getString(key, defaultValue); } + /** + * Returns a list of space-separated strings from the specified key. + * + * @see IStoredSettings.getStrings(String key) + * @param name + * @return list of strings + */ public static List<String> getStrings(String key) { - return self().storedSettings.getStrings(key); + return self().settings.getStrings(key); } + + /** + * Returns the list of keys whose name starts with the specified prefix. If + * the prefix is null or empty, all key names are returned. + * + * @see IStoredSettings.getAllKeys(String key) + * @param startingWith + * @return list of keys + */ public static List<String> getAllKeys(String startingWith) { - return self().storedSettings.getAllKeys(startingWith); + return self().settings.getAllKeys(startingWith); } + /** + * Is Gitblit running in debug mode? + * + * @return true if Gitblit is running in debug mode + */ public static boolean isDebugMode() { - return self().storedSettings.getBoolean(Keys.web.debugMode, false); + return self().settings.getBoolean(Keys.web.debugMode, false); } + /** + * Returns the list of non-Gitblit clone urls. This allows Gitblit to + * advertise alternative urls for Git client repository access. + * + * @param repositoryName + * @return list of non-gitblit clone urls + */ public List<String> getOtherCloneUrls(String repositoryName) { List<String> cloneUrls = new ArrayList<String>(); - for (String url : storedSettings.getStrings(Keys.web.otherUrls)) { + for (String url : settings.getStrings(Keys.web.otherUrls)) { cloneUrls.add(MessageFormat.format(url, repositoryName)); } return cloneUrls; } + /** + * Set the user service. The user service authenticates all users and is + * responsible for managing user permissions. + * + * @param userService + */ public void setUserService(IUserService userService) { logger.info("Setting up user service " + userService.toString()); this.userService = userService; } + /** + * Authenticate a user based on a username and password. + * + * @see IUserService.authenticate(String, char[]) + * @param username + * @param password + * @return a user object or null + */ public UserModel authenticate(String username, char[] password) { if (userService == null) { return null; @@ -119,6 +214,12 @@ return userService.authenticate(username, password); } + /** + * Authenticate a user based on their cookie. + * + * @param cookies + * @return a user object or null + */ public UserModel authenticate(Cookie[] cookies) { if (userService == null) { return null; @@ -136,6 +237,12 @@ return null; } + /** + * Sets a cookie for the specified user. + * + * @param response + * @param user + */ public void setCookie(WebResponse response, UserModel user) { if (userService == null) { return; @@ -156,41 +263,100 @@ } } + /** + * Returns the list of all users available to the login service. + * + * @see IUserService.getAllUsernames() + * @return list of all usernames + */ public List<String> getAllUsernames() { List<String> names = new ArrayList<String>(userService.getAllUsernames()); Collections.sort(names); return names; } + /** + * Delete the user object with the specified username + * + * @see IUserService.deleteUser(String) + * @param username + * @return true if successful + */ public boolean deleteUser(String username) { return userService.deleteUser(username); } + /** + * Retrieve the user object for the specified username. + * + * @see IUserService.getUserModel(String) + * @param username + * @return a user object or null + */ public UserModel getUserModel(String username) { UserModel user = userService.getUserModel(username); return user; } + /** + * Returns the list of all users who are allowed to bypass the access + * restriction placed on the specified repository. + * + * @see IUserService.getUsernamesForRepositoryRole(String) + * @param repository + * @return list of all usernames that can bypass the access restriction + */ public List<String> getRepositoryUsers(RepositoryModel repository) { - return userService.getUsernamesForRepository(repository.name); + return userService.getUsernamesForRepositoryRole(repository.name); } + /** + * Sets the list of all uses who are allowed to bypass the access + * restriction placed on the specified repository. + * + * @see IUserService.setUsernamesForRepositoryRole(String, List<String>) + * @param repository + * @param usernames + * @return true if successful + */ public boolean setRepositoryUsers(RepositoryModel repository, List<String> repositoryUsers) { - return userService.setUsernamesForRepository(repository.name, repositoryUsers); + return userService.setUsernamesForRepositoryRole(repository.name, repositoryUsers); } - public void editUserModel(String username, UserModel user, boolean isCreate) + /** + * 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 + */ + public void updateUserModel(String username, UserModel user, boolean isCreate) throws GitBlitException { if (!userService.updateUserModel(username, user)) { throw new GitBlitException(isCreate ? "Failed to add user!" : "Failed to update user!"); } } + /** + * Returns the list of all repositories available to Gitblit. This method + * does not consider user access permissions. + * + * @return list of all repositories + */ public List<String> getRepositoryList() { return JGitUtils.getRepositoryList(repositoriesFolder, exportAll, - storedSettings.getBoolean(Keys.git.searchRepositoriesSubfolders, true)); + settings.getBoolean(Keys.git.searchRepositoriesSubfolders, true)); } + /** + * Returns the JGit repository for the specified name. + * + * @param repositoryName + * @return repository or null + */ public Repository getRepository(String repositoryName) { Repository r = null; try { @@ -199,13 +365,24 @@ r = null; logger.error("GitBlit.getRepository(String) failed to find " + new File(repositoriesFolder, repositoryName).getAbsolutePath()); + } catch (ServiceNotAuthorizedException e) { + r = null; + logger.error("GitBlit.getRepository(String) failed to find " + + new File(repositoriesFolder, repositoryName).getAbsolutePath(), e); } catch (ServiceNotEnabledException e) { r = null; - e.printStackTrace(); + logger.error("GitBlit.getRepository(String) failed to find " + + new File(repositoriesFolder, repositoryName).getAbsolutePath(), e); } return r; } + /** + * Returns the list of repository models that are accessible to the user. + * + * @param user + * @return list of repository models accessible to user + */ public List<RepositoryModel> getRepositoryModels(UserModel user) { List<String> list = getRepositoryList(); List<RepositoryModel> repositories = new ArrayList<RepositoryModel>(); @@ -218,6 +395,14 @@ return repositories; } + /** + * Returns a repository model if the repository exists and the user may + * access the repository. + * + * @param user + * @param repositoryName + * @return repository model or null + */ public RepositoryModel getRepositoryModel(UserModel user, String repositoryName) { RepositoryModel model = getRepositoryModel(repositoryName); if (model == null) { @@ -233,6 +418,13 @@ } } + /** + * Returns the repository model for the specified repository. This method + * does not consider user access permissions. + * + * @param repositoryName + * @return repository model or null + */ public RepositoryModel getRepositoryModel(String repositoryName) { Repository r = getRepository(repositoryName); if (r == null) { @@ -258,6 +450,15 @@ return model; } + /** + * Returns the gitblit string vlaue for the specified key. If key is not + * set, returns defaultValue. + * + * @param config + * @param field + * @param defaultValue + * @return field value or defaultValue + */ private String getConfig(StoredConfig config, String field, String defaultValue) { String value = config.getString("gitblit", null, field); if (StringUtils.isEmpty(value)) { @@ -266,11 +467,34 @@ return value; } + /** + * Returns the gitblit boolean vlaue for the specified key. If key is not + * set, returns defaultValue. + * + * @param config + * @param field + * @param defaultValue + * @return field value or defaultValue + */ private boolean getConfig(StoredConfig config, String field, boolean defaultValue) { return config.getBoolean("gitblit", field, defaultValue); } - public void editRepositoryModel(String repositoryName, RepositoryModel repository, + /** + * Creates/updates the repository model keyed by reopsitoryName. Saves all + * repository settings in .git/config. This method allows for renaming + * repositories and will update user access permissions accordingly. + * + * All repositories created by this method are bare and automatically have + * .git appended to their names, which is the standard convention for bare + * repositories. + * + * @param repositoryName + * @param repository + * @param isCreate + * @throws GitBlitException + */ + public void updateRepositoryModel(String repositoryName, RepositoryModel repository, boolean isCreate) throws GitBlitException { Repository r = null; if (isCreate) { @@ -316,6 +540,8 @@ r = repositoryResolver.open(null, repository.name); } catch (RepositoryNotFoundException e) { logger.error("Repository not found", e); + } catch (ServiceNotAuthorizedException e) { + logger.error("Service not authorized", e); } catch (ServiceNotEnabledException e) { logger.error("Service not enabled", e); } @@ -342,15 +568,29 @@ } } + /** + * Deletes the repository from the file system and removes the repository + * permission from all repository users. + * + * @param model + * @return true if successful + */ public boolean deleteRepositoryModel(RepositoryModel model) { return deleteRepository(model.name); } + /** + * Deletes the repository from the file system and removes the repository + * permission from all repository users. + * + * @param repositoryName + * @return true if successful + */ public boolean deleteRepository(String repositoryName) { try { File folder = new File(repositoriesFolder, repositoryName); if (folder.exists() && folder.isDirectory()) { - FileUtils.delete(folder, FileUtils.RECURSIVE); + FileUtils.delete(folder, FileUtils.RECURSIVE | FileUtils.RETRY); if (userService.deleteRepositoryRole(repositoryName)) { return true; } @@ -361,25 +601,33 @@ return false; } + /** + * Returns an html version of the commit message with any global or + * repository-specific regular expression substitution applied. + * + * @param repositoryName + * @param text + * @return html version of the commit message + */ public String processCommitMessage(String repositoryName, String text) { String html = StringUtils.breakLinesForHtml(text); Map<String, String> map = new HashMap<String, String>(); // global regex keys - if (storedSettings.getBoolean(Keys.regex.global, false)) { - for (String key : storedSettings.getAllKeys(Keys.regex.global)) { + if (settings.getBoolean(Keys.regex.global, false)) { + for (String key : settings.getAllKeys(Keys.regex.global)) { if (!key.equals(Keys.regex.global)) { String subKey = key.substring(key.lastIndexOf('.') + 1); - map.put(subKey, storedSettings.getString(key, "")); + map.put(subKey, settings.getString(key, "")); } } } // repository-specific regex keys - List<String> keys = storedSettings.getAllKeys(Keys.regex._ROOT + "." + List<String> keys = settings.getAllKeys(Keys.regex._ROOT + "." + repositoryName.toLowerCase()); for (String key : keys) { String subKey = key.substring(key.lastIndexOf('.') + 1); - map.put(subKey, storedSettings.getString(key, "")); + map.put(subKey, settings.getString(key, "")); } for (Entry<String, String> entry : map.entrySet()) { @@ -396,23 +644,30 @@ return html; } + /** + * Configure the Gitblit singleton with the specified settings source. This + * source may be file settings (Gitblit GO) or may be web.xml settings + * (Gitblit WAR). + * + * @param settings + */ public void configureContext(IStoredSettings settings) { logger.info("Reading configuration from " + settings.toString()); - this.storedSettings = settings; + this.settings = settings; repositoriesFolder = new File(settings.getString(Keys.git.repositoriesFolder, "git")); logger.info("Git repositories folder " + repositoriesFolder.getAbsolutePath()); repositoryResolver = new FileResolver<Void>(repositoriesFolder, exportAll); String realm = settings.getString(Keys.realm.userService, "users.properties"); IUserService loginService = null; try { - // Check to see if this "file" is a login service class + // check to see if this "file" is a login service class Class<?> realmClass = Class.forName(realm); if (IUserService.class.isAssignableFrom(realmClass)) { loginService = (IUserService) realmClass.newInstance(); } } catch (Throwable t) { - // Not a login service class OR other issue - // Use default file login service + // not a login service class or class could not be instantiated. + // try to use default file login service File realmFile = new File(realm); if (!realmFile.exists()) { try { @@ -427,16 +682,25 @@ setUserService(loginService); } + /** + * Configure Gitblit from the web.xml, if no configuration has already been + * specified. + * + * @see ServletContextListener.contextInitialize(ServletContextEvent) + */ @Override public void contextInitialized(ServletContextEvent contextEvent) { - if (storedSettings == null) { - // for running gitblit as a traditional webapp in a servlet - // container + if (settings == null) { + // Gitblit WAR is running in a servlet container WebXmlSettings webxmlSettings = new WebXmlSettings(contextEvent.getServletContext()); configureContext(webxmlSettings); } } + /** + * Gitblit is being shutdown either because the servlet container is + * shutting down or because the servlet container is re-deploying Gitblit. + */ @Override public void contextDestroyed(ServletContextEvent contextEvent) { logger.info("Gitblit context destroyed by servlet container."); -- Gitblit v1.9.1