All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sonar.batch.cache.ProjectCacheSynchronizer Maven / Gradle / Ivy

The newest version!
/*
 * SonarQube
 * Copyright (C) 2009-2016 SonarSource SA
 * mailto:contact AT sonarsource DOT com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package org.sonar.batch.cache;

import com.google.common.base.Function;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
import org.sonar.batch.protocol.input.BatchInput.ServerIssue;
import org.sonar.batch.repository.ProjectRepositories;
import org.sonar.batch.repository.ProjectRepositoriesLoader;
import org.sonar.batch.repository.QualityProfileLoader;
import org.sonar.batch.repository.ServerIssuesLoader;
import org.sonar.batch.repository.user.UserRepositoryLoader;
import org.sonar.batch.rule.ActiveRulesLoader;
import org.sonar.batch.rule.RulesLoader;
import org.sonarqube.ws.QualityProfiles.SearchWsResponse.QualityProfile;

public class ProjectCacheSynchronizer {
  private static final Logger LOG = LoggerFactory.getLogger(ProjectCacheSynchronizer.class);

  private final ServerIssuesLoader issuesLoader;
  private final UserRepositoryLoader userRepository;
  private final ProjectCacheStatus cacheStatus;
  private final QualityProfileLoader qualityProfileLoader;
  private final ProjectRepositoriesLoader projectRepositoriesLoader;
  private final ActiveRulesLoader activeRulesLoader;
  private final RulesLoader rulesLoader;

  public ProjectCacheSynchronizer(RulesLoader rulesLoader, QualityProfileLoader qualityProfileLoader, ProjectRepositoriesLoader projectSettingsLoader,
    ActiveRulesLoader activeRulesLoader, ServerIssuesLoader issuesLoader,
    UserRepositoryLoader userRepository, ProjectCacheStatus cacheStatus) {
    this.rulesLoader = rulesLoader;
    this.qualityProfileLoader = qualityProfileLoader;
    this.projectRepositoriesLoader = projectSettingsLoader;
    this.activeRulesLoader = activeRulesLoader;
    this.issuesLoader = issuesLoader;
    this.userRepository = userRepository;
    this.cacheStatus = cacheStatus;
  }

  private static boolean isToday(Date d) {
    Calendar c1 = Calendar.getInstance();
    Calendar c2 = Calendar.getInstance();
    c2.setTime(d);

    return c1.get(Calendar.DAY_OF_YEAR) == c2.get(Calendar.DAY_OF_YEAR) &&
      c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR);
  }

  private static boolean shouldUpdate(Date lastUpdate) {
    return !isToday(lastUpdate);
  }

  public void load(String projectKey, boolean force) {
    Date lastSync = cacheStatus.getSyncStatus();
    boolean failOnError = true;

    if (lastSync != null) {
      if (force) {
        LOG.info("-- Found project [{}] cache [{}], synchronizing data (forced)..", projectKey, lastSync);
      } else if (shouldUpdate(lastSync)) {
        LOG.info("-- Found project [{}] cache [{}], synchronizing data..", projectKey, lastSync);
        failOnError = false;
      } else {
        LOG.info("Found project [{}] cache [{}]", projectKey, lastSync);
        return;
      }
    } else {
      LOG.info("-- Cache for project [{}] not found, synchronizing data..", projectKey);
    }

    try {
      loadData(projectKey);
    } catch (Exception e) {
      if (failOnError) {
        throw e;
      }

      LOG.warn("-- Cache update for project [{}] failed, continuing from cache..", projectKey, e);
      return;
    }

    saveStatus();
  }

  private void saveStatus() {
    cacheStatus.save();
    LOG.info("-- Successfully synchronized project cache");
  }

  private void loadData(String projectKey) {
    Profiler profiler = Profiler.create(Loggers.get(ProjectCacheSynchronizer.class));

    profiler.startInfo("Load rules");
    rulesLoader.load(null);
    profiler.stopInfo();

    profiler.startInfo("Load project settings");
    ProjectRepositories projectRepo = projectRepositoriesLoader.load(projectKey, true, null);

    if (!projectRepo.exists()) {
      LOG.debug("Project doesn't exist in the server");
    } else if (projectRepo.lastAnalysisDate() == null) {
      LOG.debug("No previous analysis found");
    }
    profiler.stopInfo();

    profiler.startInfo("Load project quality profiles");
    Collection qProfiles;
    if (projectRepo.exists()) {
      qProfiles = qualityProfileLoader.load(projectKey, null, null);
    } else {
      qProfiles = qualityProfileLoader.loadDefault(null, null);
    }
    profiler.stopInfo();

    profiler.startInfo("Load project active rules");
    Collection keys = getKeys(qProfiles);
    for (String k : keys) {
      activeRulesLoader.load(k, null);
    }
    profiler.stopInfo();

    if (projectRepo.lastAnalysisDate() != null) {
      profiler.startInfo("Load server issues");
      UserLoginAccumulator consumer = new UserLoginAccumulator();
      issuesLoader.load(projectKey, consumer);
      profiler.stopInfo();

      profiler.startInfo("Load user information");
      for (String login : consumer.loginSet) {
        userRepository.load(login, null);
      }
      profiler.stopInfo("Load user information");
    }
  }

  private static Collection getKeys(Collection qProfiles) {
    List list = new ArrayList<>(qProfiles.size());
    for (QualityProfile qp : qProfiles) {
      list.add(qp.getKey());
    }

    return list;
  }

  private static class UserLoginAccumulator implements Function {
    Set loginSet = new HashSet<>();

    @Override
    public Void apply(ServerIssue input) {
      if (!StringUtils.isEmpty(input.getAssigneeLogin())) {
        loginSet.add(input.getAssigneeLogin());
      }
      return null;
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy