James Moger
2013-11-20 a1f27e2fac7b38b87645bd53b7e023484c796f1c
src/main/java/com/gitblit/GitBlit.java
@@ -32,10 +32,8 @@
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 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.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.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 @@
 */
@WebListener
public class GitBlit extends DaggerContextListener
                implements IProjectManager,
                        IFederationManager,
                implements IFederationManager,
                        IGitblitManager {
   private static GitBlit gitblit;
@@ -138,15 +130,7 @@
   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;
@@ -442,237 +426,6 @@
      }
   }
   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 @@
                  getManager(IUserManager.class),
                  getManager(ISessionManager.class),
                  getManager(IRepositoryManager.class),
                  this,
                  getManager(IProjectManager.class),
                  this,
                  this);
            gitDaemon = new GitDaemon(gitblit);
@@ -1242,14 +995,11 @@
      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();