diff options
author | James Moger <james.moger@gitblit.com> | 2013-11-20 22:12:54 -0500 |
---|---|---|
committer | James Moger <james.moger@gitblit.com> | 2013-11-29 11:05:51 -0500 |
commit | a1f27e2fac7b38b87645bd53b7e023484c796f1c (patch) | |
tree | 3bd6bcdfc5ae274e5bbb0c28d7d23941d3dc75fa | |
parent | 95cdba46c79d952f2c2baba937e70796674ed57e (diff) | |
download | gitblit-a1f27e2fac7b38b87645bd53b7e023484c796f1c.tar.gz gitblit-a1f27e2fac7b38b87645bd53b7e023484c796f1c.zip |
Extract ProjectManager from the GitBlit singleton
Change-Id: I93493a473e3d6ea9b2523c1913d6dc323642344d
-rw-r--r-- | src/main/java/com/gitblit/DaggerModule.java | 12 | ||||
-rw-r--r-- | src/main/java/com/gitblit/GitBlit.java | 256 | ||||
-rw-r--r-- | src/main/java/com/gitblit/manager/IProjectManager.java | 2 | ||||
-rw-r--r-- | src/main/java/com/gitblit/manager/ProjectManager.java | 327 |
4 files changed, 341 insertions, 256 deletions
diff --git a/src/main/java/com/gitblit/DaggerModule.java b/src/main/java/com/gitblit/DaggerModule.java index 240fe7fc..8cd9c8b5 100644 --- a/src/main/java/com/gitblit/DaggerModule.java +++ b/src/main/java/com/gitblit/DaggerModule.java @@ -29,6 +29,7 @@ import com.gitblit.manager.IRuntimeManager; import com.gitblit.manager.ISessionManager; import com.gitblit.manager.IUserManager; import com.gitblit.manager.NotificationManager; +import com.gitblit.manager.ProjectManager; import com.gitblit.manager.RepositoryManager; import com.gitblit.manager.RuntimeManager; import com.gitblit.manager.SessionManager; @@ -125,8 +126,15 @@ public class DaggerModule { userManager); } - @Provides @Singleton IProjectManager provideProjectManager() { - return gitblit; + @Provides @Singleton IProjectManager provideProjectManager( + IRuntimeManager runtimeManager, + IUserManager userManager, + IRepositoryManager repositoryManager) { + + return new ProjectManager( + runtimeManager, + userManager, + repositoryManager); } @Provides @Singleton IGitblitManager provideGitblitManager() { diff --git a/src/main/java/com/gitblit/GitBlit.java b/src/main/java/com/gitblit/GitBlit.java index 4e8822b3..493f8fce 100644 --- a/src/main/java/com/gitblit/GitBlit.java +++ b/src/main/java/com/gitblit/GitBlit.java @@ -32,10 +32,8 @@ import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -50,8 +48,6 @@ import javax.servlet.http.HttpServletRequest; import org.apache.wicket.resource.ContextRelativeResource; import org.apache.wicket.util.resource.ResourceStreamNotFoundException; -import org.eclipse.jgit.storage.file.FileBasedConfig; -import org.eclipse.jgit.util.FS; import org.slf4j.Logger; import com.gitblit.Constants.AccessPermission; @@ -77,7 +73,6 @@ import com.gitblit.models.FederationModel; import com.gitblit.models.FederationProposal; import com.gitblit.models.FederationSet; import com.gitblit.models.GitClientApplication; -import com.gitblit.models.ProjectModel; import com.gitblit.models.RepositoryModel; import com.gitblit.models.RepositoryUrl; import com.gitblit.models.ServerSettings; @@ -86,12 +81,10 @@ import com.gitblit.models.TeamModel; import com.gitblit.models.UserModel; import com.gitblit.utils.ArrayUtils; import com.gitblit.utils.ContainerUtils; -import com.gitblit.utils.DeepCopier; import com.gitblit.utils.FederationUtils; import com.gitblit.utils.HttpUtils; import com.gitblit.utils.JGitUtils; import com.gitblit.utils.JsonUtils; -import com.gitblit.utils.ModelUtils; import com.gitblit.utils.ObjectCache; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitblitWicketFilter; @@ -117,8 +110,7 @@ import dagger.ObjectGraph; */ @WebListener public class GitBlit extends DaggerContextListener - implements IProjectManager, - IFederationManager, + implements IFederationManager, IGitblitManager { private static GitBlit gitblit; @@ -138,16 +130,8 @@ public class GitBlit extends DaggerContextListener private final Map<String, FederationModel> federationPullResults = new ConcurrentHashMap<String, FederationModel>(); - private final Map<String, ProjectModel> projectCache = new ConcurrentHashMap<String, ProjectModel>(); - - private final ObjectCache<String> projectMarkdownCache = new ObjectCache<String>(); - - private final ObjectCache<String> projectRepositoriesMarkdownCache = new ObjectCache<String>(); - private IStoredSettings settings; - private FileBasedConfig projectConfigs; - private FanoutService fanoutService; private GitDaemon gitDaemon; @@ -442,237 +426,6 @@ public class GitBlit extends DaggerContextListener } } - private void reloadProjectMarkdown(ProjectModel project) { - // project markdown - File pmkd = new File(getManager(IRepositoryManager.class).getRepositoriesFolder(), (project.isRoot ? "" : project.name) + "/project.mkd"); - if (pmkd.exists()) { - Date lm = new Date(pmkd.lastModified()); - if (!projectMarkdownCache.hasCurrent(project.name, lm)) { - String mkd = com.gitblit.utils.FileUtils.readContent(pmkd, "\n"); - projectMarkdownCache.updateObject(project.name, lm, mkd); - } - project.projectMarkdown = projectMarkdownCache.getObject(project.name); - } - - // project repositories markdown - File rmkd = new File(getManager(IRepositoryManager.class).getRepositoriesFolder(), (project.isRoot ? "" : project.name) + "/repositories.mkd"); - if (rmkd.exists()) { - Date lm = new Date(rmkd.lastModified()); - if (!projectRepositoriesMarkdownCache.hasCurrent(project.name, lm)) { - String mkd = com.gitblit.utils.FileUtils.readContent(rmkd, "\n"); - projectRepositoriesMarkdownCache.updateObject(project.name, lm, mkd); - } - project.repositoriesMarkdown = projectRepositoriesMarkdownCache.getObject(project.name); - } - } - - - /** - * Returns the map of project config. This map is cached and reloaded if - * the underlying projects.conf file changes. - * - * @return project config map - */ - private Map<String, ProjectModel> getProjectConfigs() { - if (projectCache.isEmpty() || projectConfigs.isOutdated()) { - - try { - projectConfigs.load(); - } catch (Exception e) { - } - - // project configs - String rootName = settings.getString(Keys.web.repositoryRootGroupName, "main"); - ProjectModel rootProject = new ProjectModel(rootName, true); - - Map<String, ProjectModel> configs = new HashMap<String, ProjectModel>(); - // cache the root project under its alias and an empty path - configs.put("", rootProject); - configs.put(rootProject.name.toLowerCase(), rootProject); - - for (String name : projectConfigs.getSubsections("project")) { - ProjectModel project; - if (name.equalsIgnoreCase(rootName)) { - project = rootProject; - } else { - project = new ProjectModel(name); - } - project.title = projectConfigs.getString("project", name, "title"); - project.description = projectConfigs.getString("project", name, "description"); - - reloadProjectMarkdown(project); - - configs.put(name.toLowerCase(), project); - } - projectCache.clear(); - projectCache.putAll(configs); - } - return projectCache; - } - - /** - * Returns a list of project models for the user. - * - * @param user - * @param includeUsers - * @return list of projects that are accessible to the user - */ - @Override - public List<ProjectModel> getProjectModels(UserModel user, boolean includeUsers) { - Map<String, ProjectModel> configs = getProjectConfigs(); - - // per-user project lists, this accounts for security and visibility - Map<String, ProjectModel> map = new TreeMap<String, ProjectModel>(); - // root project - map.put("", configs.get("")); - - for (RepositoryModel model : getManager(IRepositoryManager.class).getRepositoryModels(user)) { - String rootPath = StringUtils.getRootPath(model.name).toLowerCase(); - if (!map.containsKey(rootPath)) { - ProjectModel project; - if (configs.containsKey(rootPath)) { - // clone the project model because it's repository list will - // be tailored for the requesting user - project = DeepCopier.copy(configs.get(rootPath)); - } else { - project = new ProjectModel(rootPath); - } - map.put(rootPath, project); - } - map.get(rootPath).addRepository(model); - } - - // sort projects, root project first - List<ProjectModel> projects; - if (includeUsers) { - // all projects - projects = new ArrayList<ProjectModel>(map.values()); - Collections.sort(projects); - projects.remove(map.get("")); - projects.add(0, map.get("")); - } else { - // all non-user projects - projects = new ArrayList<ProjectModel>(); - ProjectModel root = map.remove(""); - for (ProjectModel model : map.values()) { - if (!model.isUserProject()) { - projects.add(model); - } - } - Collections.sort(projects); - projects.add(0, root); - } - return projects; - } - - /** - * Returns the project model for the specified user. - * - * @param name - * @param user - * @return a project model, or null if it does not exist - */ - @Override - public ProjectModel getProjectModel(String name, UserModel user) { - for (ProjectModel project : getProjectModels(user, true)) { - if (project.name.equalsIgnoreCase(name)) { - return project; - } - } - return null; - } - - /** - * Returns a project model for the Gitblit/system user. - * - * @param name a project name - * @return a project model or null if the project does not exist - */ - @Override - public ProjectModel getProjectModel(String name) { - Map<String, ProjectModel> configs = getProjectConfigs(); - ProjectModel project = configs.get(name.toLowerCase()); - if (project == null) { - project = new ProjectModel(name); - if (ModelUtils.isPersonalRepository(name)) { - UserModel user = getManager(IUserManager.class).getUserModel(ModelUtils.getUserNameFromRepoPath(name)); - if (user != null) { - project.title = user.getDisplayName(); - project.description = "personal repositories"; - } - } - } else { - // clone the object - project = DeepCopier.copy(project); - } - if (StringUtils.isEmpty(name)) { - // get root repositories - for (String repository : getManager(IRepositoryManager.class).getRepositoryList()) { - if (repository.indexOf('/') == -1) { - project.addRepository(repository); - } - } - } else { - // get repositories in subfolder - String folder = name.toLowerCase() + "/"; - for (String repository : getManager(IRepositoryManager.class).getRepositoryList()) { - if (repository.toLowerCase().startsWith(folder)) { - project.addRepository(repository); - } - } - } - if (project.repositories.size() == 0) { - // no repositories == no project - return null; - } - - reloadProjectMarkdown(project); - return project; - } - - /** - * Returns the list of project models that are referenced by the supplied - * repository model list. This is an alternative method exists to ensure - * Gitblit does not call getRepositoryModels(UserModel) twice in a request. - * - * @param repositoryModels - * @param includeUsers - * @return a list of project models - */ - @Override - public List<ProjectModel> getProjectModels(List<RepositoryModel> repositoryModels, boolean includeUsers) { - Map<String, ProjectModel> projects = new LinkedHashMap<String, ProjectModel>(); - for (RepositoryModel repository : repositoryModels) { - if (!includeUsers && repository.isPersonalRepository()) { - // exclude personal repositories - continue; - } - if (!projects.containsKey(repository.projectPath)) { - ProjectModel project = getProjectModel(repository.projectPath); - if (project == null) { - logger.warn(MessageFormat.format("excluding project \"{0}\" from project list because it is empty!", - repository.projectPath)); - continue; - } - projects.put(repository.projectPath, project); - // clear the repo list in the project because that is the system - // list, not the user-accessible list and start building the - // user-accessible list - project.repositories.clear(); - project.repositories.add(repository.name); - project.lastChange = repository.lastChange; - } else { - // update the user-accessible list - // this is used for repository count - ProjectModel project = projects.get(repository.projectPath); - project.repositories.add(repository.name); - if (project.lastChange.before(repository.lastChange)) { - project.lastChange = repository.lastChange; - } - } - } - return new ArrayList<ProjectModel>(projects.values()); - } /** * Returns Gitblit's scheduled executor service for scheduling tasks. @@ -1173,7 +926,7 @@ public class GitBlit extends DaggerContextListener getManager(IUserManager.class), getManager(ISessionManager.class), getManager(IRepositoryManager.class), - this, + getManager(IProjectManager.class), this, this); gitDaemon = new GitDaemon(gitblit); @@ -1242,15 +995,12 @@ public class GitBlit extends DaggerContextListener startManager(injector, IUserManager.class); startManager(injector, ISessionManager.class); startManager(injector, IRepositoryManager.class); + startManager(injector, IProjectManager.class); logger.info("Gitblit base folder = " + baseFolder.getAbsolutePath()); loadSettingModels(runtime.getSettingsModel()); - // load and cache the project metadata - projectConfigs = new FileBasedConfig(runtime.getFileOrFolder(Keys.web.projectsFile, "${baseFolder}/projects.conf"), FS.detect()); - getProjectConfigs(); - if (true/*startFederation*/) { configureFederation(); } diff --git a/src/main/java/com/gitblit/manager/IProjectManager.java b/src/main/java/com/gitblit/manager/IProjectManager.java index b2577f56..c5b490e5 100644 --- a/src/main/java/com/gitblit/manager/IProjectManager.java +++ b/src/main/java/com/gitblit/manager/IProjectManager.java @@ -21,7 +21,7 @@ import com.gitblit.models.ProjectModel; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; -public interface IProjectManager { +public interface IProjectManager extends IManager { /** * Returns a list of project models for the user. diff --git a/src/main/java/com/gitblit/manager/ProjectManager.java b/src/main/java/com/gitblit/manager/ProjectManager.java new file mode 100644 index 00000000..83a63102 --- /dev/null +++ b/src/main/java/com/gitblit/manager/ProjectManager.java @@ -0,0 +1,327 @@ +/* + * Copyright 2013 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.manager; + +import java.io.File; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; + +import org.eclipse.jgit.storage.file.FileBasedConfig; +import org.eclipse.jgit.util.FS; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.gitblit.IStoredSettings; +import com.gitblit.Keys; +import com.gitblit.models.ProjectModel; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.UserModel; +import com.gitblit.utils.DeepCopier; +import com.gitblit.utils.ModelUtils; +import com.gitblit.utils.ObjectCache; +import com.gitblit.utils.StringUtils; + +/** + * Project manager handles project-related functions. + * + * @author James Moger + * + */ +public class ProjectManager implements IProjectManager { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final Map<String, ProjectModel> projectCache = new ConcurrentHashMap<String, ProjectModel>(); + + private final ObjectCache<String> projectMarkdownCache = new ObjectCache<String>(); + + private final ObjectCache<String> projectRepositoriesMarkdownCache = new ObjectCache<String>(); + + private final IStoredSettings settings; + + private final IRuntimeManager runtimeManager; + + private final IUserManager userManager; + + private final IRepositoryManager repositoryManager; + + private FileBasedConfig projectConfigs; + + public ProjectManager( + IRuntimeManager runtimeManager, + IUserManager userManager, + IRepositoryManager repositoryManager) { + + this.settings = runtimeManager.getSettings(); + this.runtimeManager = runtimeManager; + this.userManager = userManager; + this.repositoryManager = repositoryManager; + } + + @Override + public IManager setup() { + // load and cache the project metadata + projectConfigs = new FileBasedConfig(runtimeManager.getFileOrFolder(Keys.web.projectsFile, "${baseFolder}/projects.conf"), FS.detect()); + getProjectConfigs(); + + return this; + } + + @Override + public IManager stop() { + return this; + } + + private void reloadProjectMarkdown(ProjectModel project) { + // project markdown + File pmkd = new File(repositoryManager.getRepositoriesFolder(), (project.isRoot ? "" : project.name) + "/project.mkd"); + if (pmkd.exists()) { + Date lm = new Date(pmkd.lastModified()); + if (!projectMarkdownCache.hasCurrent(project.name, lm)) { + String mkd = com.gitblit.utils.FileUtils.readContent(pmkd, "\n"); + projectMarkdownCache.updateObject(project.name, lm, mkd); + } + project.projectMarkdown = projectMarkdownCache.getObject(project.name); + } + + // project repositories markdown + File rmkd = new File(repositoryManager.getRepositoriesFolder(), (project.isRoot ? "" : project.name) + "/repositories.mkd"); + if (rmkd.exists()) { + Date lm = new Date(rmkd.lastModified()); + if (!projectRepositoriesMarkdownCache.hasCurrent(project.name, lm)) { + String mkd = com.gitblit.utils.FileUtils.readContent(rmkd, "\n"); + projectRepositoriesMarkdownCache.updateObject(project.name, lm, mkd); + } + project.repositoriesMarkdown = projectRepositoriesMarkdownCache.getObject(project.name); + } + } + + + /** + * Returns the map of project config. This map is cached and reloaded if + * the underlying projects.conf file changes. + * + * @return project config map + */ + private Map<String, ProjectModel> getProjectConfigs() { + if (projectCache.isEmpty() || projectConfigs.isOutdated()) { + + try { + projectConfigs.load(); + } catch (Exception e) { + } + + // project configs + String rootName = settings.getString(Keys.web.repositoryRootGroupName, "main"); + ProjectModel rootProject = new ProjectModel(rootName, true); + + Map<String, ProjectModel> configs = new HashMap<String, ProjectModel>(); + // cache the root project under its alias and an empty path + configs.put("", rootProject); + configs.put(rootProject.name.toLowerCase(), rootProject); + + for (String name : projectConfigs.getSubsections("project")) { + ProjectModel project; + if (name.equalsIgnoreCase(rootName)) { + project = rootProject; + } else { + project = new ProjectModel(name); + } + project.title = projectConfigs.getString("project", name, "title"); + project.description = projectConfigs.getString("project", name, "description"); + + reloadProjectMarkdown(project); + + configs.put(name.toLowerCase(), project); + } + projectCache.clear(); + projectCache.putAll(configs); + } + return projectCache; + } + + /** + * Returns a list of project models for the user. + * + * @param user + * @param includeUsers + * @return list of projects that are accessible to the user + */ + @Override + public List<ProjectModel> getProjectModels(UserModel user, boolean includeUsers) { + Map<String, ProjectModel> configs = getProjectConfigs(); + + // per-user project lists, this accounts for security and visibility + Map<String, ProjectModel> map = new TreeMap<String, ProjectModel>(); + // root project + map.put("", configs.get("")); + + for (RepositoryModel model : repositoryManager.getRepositoryModels(user)) { + String rootPath = StringUtils.getRootPath(model.name).toLowerCase(); + if (!map.containsKey(rootPath)) { + ProjectModel project; + if (configs.containsKey(rootPath)) { + // clone the project model because it's repository list will + // be tailored for the requesting user + project = DeepCopier.copy(configs.get(rootPath)); + } else { + project = new ProjectModel(rootPath); + } + map.put(rootPath, project); + } + map.get(rootPath).addRepository(model); + } + + // sort projects, root project first + List<ProjectModel> projects; + if (includeUsers) { + // all projects + projects = new ArrayList<ProjectModel>(map.values()); + Collections.sort(projects); + projects.remove(map.get("")); + projects.add(0, map.get("")); + } else { + // all non-user projects + projects = new ArrayList<ProjectModel>(); + ProjectModel root = map.remove(""); + for (ProjectModel model : map.values()) { + if (!model.isUserProject()) { + projects.add(model); + } + } + Collections.sort(projects); + projects.add(0, root); + } + return projects; + } + + /** + * Returns the project model for the specified user. + * + * @param name + * @param user + * @return a project model, or null if it does not exist + */ + @Override + public ProjectModel getProjectModel(String name, UserModel user) { + for (ProjectModel project : getProjectModels(user, true)) { + if (project.name.equalsIgnoreCase(name)) { + return project; + } + } + return null; + } + + /** + * Returns a project model for the Gitblit/system user. + * + * @param name a project name + * @return a project model or null if the project does not exist + */ + @Override + public ProjectModel getProjectModel(String name) { + Map<String, ProjectModel> configs = getProjectConfigs(); + ProjectModel project = configs.get(name.toLowerCase()); + if (project == null) { + project = new ProjectModel(name); + if (ModelUtils.isPersonalRepository(name)) { + UserModel user = userManager.getUserModel(ModelUtils.getUserNameFromRepoPath(name)); + if (user != null) { + project.title = user.getDisplayName(); + project.description = "personal repositories"; + } + } + } else { + // clone the object + project = DeepCopier.copy(project); + } + if (StringUtils.isEmpty(name)) { + // get root repositories + for (String repository : repositoryManager.getRepositoryList()) { + if (repository.indexOf('/') == -1) { + project.addRepository(repository); + } + } + } else { + // get repositories in subfolder + String folder = name.toLowerCase() + "/"; + for (String repository : repositoryManager.getRepositoryList()) { + if (repository.toLowerCase().startsWith(folder)) { + project.addRepository(repository); + } + } + } + if (project.repositories.size() == 0) { + // no repositories == no project + return null; + } + + reloadProjectMarkdown(project); + return project; + } + + /** + * Returns the list of project models that are referenced by the supplied + * repository model list. This is an alternative method exists to ensure + * Gitblit does not call getRepositoryModels(UserModel) twice in a request. + * + * @param repositoryModels + * @param includeUsers + * @return a list of project models + */ + @Override + public List<ProjectModel> getProjectModels(List<RepositoryModel> repositoryModels, boolean includeUsers) { + Map<String, ProjectModel> projects = new LinkedHashMap<String, ProjectModel>(); + for (RepositoryModel repository : repositoryModels) { + if (!includeUsers && repository.isPersonalRepository()) { + // exclude personal repositories + continue; + } + if (!projects.containsKey(repository.projectPath)) { + ProjectModel project = getProjectModel(repository.projectPath); + if (project == null) { + logger.warn(MessageFormat.format("excluding project \"{0}\" from project list because it is empty!", + repository.projectPath)); + continue; + } + projects.put(repository.projectPath, project); + // clear the repo list in the project because that is the system + // list, not the user-accessible list and start building the + // user-accessible list + project.repositories.clear(); + project.repositories.add(repository.name); + project.lastChange = repository.lastChange; + } else { + // update the user-accessible list + // this is used for repository count + ProjectModel project = projects.get(repository.projectPath); + project.repositories.add(repository.name); + if (project.lastChange.before(repository.lastChange)) { + project.lastChange = repository.lastChange; + } + } + } + return new ArrayList<ProjectModel>(projects.values()); + } +} |