Package com.gitblit.manager

Source Code of com.gitblit.manager.ProjectManager

/*
* 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 ProjectManager start() {
    // load and cache the project metadata
    projectConfigs = new FileBasedConfig(runtimeManager.getFileOrFolder(Keys.web.projectsFile, "${baseFolder}/projects.conf"), FS.detect());
    getProjectConfigs();

    return this;
  }

  @Override
  public ProjectManager 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());
  }
}
TOP

Related Classes of com.gitblit.manager.ProjectManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.