From 42b27a86a33b63b0f72ff37c289ca7e41473ed7a Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Tue, 6 Oct 2015 17:36:39 +0200 Subject: SONAR-6837 Allow to configure WS read timeout from batch --- .../batch/analysis/AnalysisWSLoaderProvider.java | 13 +-- .../org/sonar/batch/bootstrap/GlobalContainer.java | 5 - .../batch/cache/ProjectCacheSynchronizer.java | 1 + .../sonar/batch/cache/ProjectSyncContainer.java | 22 ++-- .../batch/cache/StrategyWSLoaderProvider.java | 8 +- .../main/java/org/sonar/batch/cache/WSLoader.java | 126 +++++++++++---------- .../org/sonar/batch/rule/ActiveRulesProvider.java | 32 +++--- .../sonar/batch/rule/DefaultActiveRulesLoader.java | 3 + .../org/sonar/batch/scan/ProjectScanContainer.java | 50 ++++---- 9 files changed, 134 insertions(+), 126 deletions(-) (limited to 'sonar-batch/src/main') diff --git a/sonar-batch/src/main/java/org/sonar/batch/analysis/AnalysisWSLoaderProvider.java b/sonar-batch/src/main/java/org/sonar/batch/analysis/AnalysisWSLoaderProvider.java index dc91e97a2be..ca0f521d42e 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/analysis/AnalysisWSLoaderProvider.java +++ b/sonar-batch/src/main/java/org/sonar/batch/analysis/AnalysisWSLoaderProvider.java @@ -19,15 +19,12 @@ */ package org.sonar.batch.analysis; -import org.sonar.batch.cache.WSLoader; -import org.sonar.batch.cache.WSLoader.LoadStrategy; import org.picocontainer.injectors.ProviderAdapter; - -import java.util.Map; - +import org.sonar.api.batch.AnalysisMode; import org.sonar.batch.bootstrap.ServerClient; +import org.sonar.batch.cache.WSLoader; +import org.sonar.batch.cache.WSLoader.LoadStrategy; import org.sonar.home.cache.PersistentCache; -import org.sonar.api.batch.AnalysisMode; public class AnalysisWSLoaderProvider extends ProviderAdapter { private WSLoader wsLoader; @@ -36,12 +33,12 @@ public class AnalysisWSLoaderProvider extends ProviderAdapter { if (wsLoader == null) { // recreate cache directory if needed for this analysis cache.reconfigure(); - wsLoader = new WSLoader(getStrategy(props.properties(), mode), cache, client); + wsLoader = new WSLoader(getStrategy(mode), cache, client, props); } return wsLoader; } - private static LoadStrategy getStrategy(Map props, AnalysisMode mode) { + private static LoadStrategy getStrategy(AnalysisMode mode) { if (mode.isIssues()) { return LoadStrategy.CACHE_ONLY; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java index 3516932cd50..9df2d26f876 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java @@ -44,9 +44,6 @@ import org.sonar.batch.platform.DefaultServer; import org.sonar.batch.repository.DefaultGlobalRepositoriesLoader; import org.sonar.batch.repository.GlobalRepositoriesLoader; import org.sonar.batch.repository.GlobalRepositoriesProvider; -import org.sonar.batch.rule.DefaultRulesLoader; -import org.sonar.batch.rule.RulesLoader; -import org.sonar.batch.rule.RulesProvider; import org.sonar.batch.scan.ProjectScanContainer; import org.sonar.core.platform.ComponentContainer; import org.sonar.core.platform.PluginClassloaderFactory; @@ -109,7 +106,6 @@ public class GlobalContainer extends ComponentContainer { CachesManager.class, GlobalSettings.class, - new RulesProvider(), ServerClient.class, DefaultServer.class, new GlobalTempFolderProvider(), @@ -121,7 +117,6 @@ public class GlobalContainer extends ComponentContainer { new GlobalRepositoriesProvider(), UuidFactoryImpl.INSTANCE); addIfMissing(BatchPluginInstaller.class, PluginInstaller.class); - addIfMissing(DefaultRulesLoader.class, RulesLoader.class); addIfMissing(DefaultGlobalRepositoriesLoader.class, GlobalRepositoriesLoader.class); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectCacheSynchronizer.java b/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectCacheSynchronizer.java index 0b834e8b4d5..3487247ae2b 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectCacheSynchronizer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectCacheSynchronizer.java @@ -146,6 +146,7 @@ public class ProjectCacheSynchronizer { for (String k : keys) { activeRulesLoader.load(k, null); } + profiler.stopInfo(); if (projectRepo.lastAnalysisDate() != null) { profiler.startInfo("Load server issues"); diff --git a/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectSyncContainer.java b/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectSyncContainer.java index 2bfc9dd12fa..0bf59d119ee 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectSyncContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectSyncContainer.java @@ -19,26 +19,25 @@ */ package org.sonar.batch.cache; -import javax.annotation.Nullable; - -import org.sonar.batch.analysis.DefaultAnalysisMode; -import org.sonar.api.CoreProperties; - import java.util.HashMap; import java.util.Map; - +import javax.annotation.Nullable; +import org.sonar.api.CoreProperties; import org.sonar.batch.analysis.AnalysisProperties; +import org.sonar.batch.analysis.DefaultAnalysisMode; import org.sonar.batch.bootstrap.GlobalProperties; +import org.sonar.batch.cache.WSLoader.LoadStrategy; import org.sonar.batch.repository.DefaultProjectRepositoriesLoader; -import org.sonar.batch.rule.ActiveRulesLoader; -import org.sonar.batch.rule.DefaultActiveRulesLoader; -import org.sonar.batch.repository.QualityProfileLoader; import org.sonar.batch.repository.DefaultQualityProfileLoader; -import org.sonar.batch.cache.WSLoader.LoadStrategy; -import org.sonar.batch.repository.user.UserRepositoryLoader; import org.sonar.batch.repository.DefaultServerIssuesLoader; 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.DefaultActiveRulesLoader; +import org.sonar.batch.rule.DefaultRulesLoader; +import org.sonar.batch.rule.RulesLoader; import org.sonar.core.platform.ComponentContainer; public class ProjectSyncContainer extends ComponentContainer { @@ -88,6 +87,7 @@ public class ProjectSyncContainer extends ComponentContainer { addIfMissing(DefaultProjectRepositoriesLoader.class, ProjectRepositoriesLoader.class); addIfMissing(DefaultServerIssuesLoader.class, ServerIssuesLoader.class); addIfMissing(DefaultQualityProfileLoader.class, QualityProfileLoader.class); + addIfMissing(DefaultRulesLoader.class, RulesLoader.class); addIfMissing(DefaultActiveRulesLoader.class, ActiveRulesLoader.class); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/cache/StrategyWSLoaderProvider.java b/sonar-batch/src/main/java/org/sonar/batch/cache/StrategyWSLoaderProvider.java index ecd7ef8f405..e64015db867 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/cache/StrategyWSLoaderProvider.java +++ b/sonar-batch/src/main/java/org/sonar/batch/cache/StrategyWSLoaderProvider.java @@ -19,10 +19,10 @@ */ package org.sonar.batch.cache; -import org.sonar.batch.cache.WSLoader.LoadStrategy; - import org.picocontainer.injectors.ProviderAdapter; +import org.sonar.batch.bootstrap.GlobalProperties; import org.sonar.batch.bootstrap.ServerClient; +import org.sonar.batch.cache.WSLoader.LoadStrategy; import org.sonar.home.cache.PersistentCache; public class StrategyWSLoaderProvider extends ProviderAdapter { @@ -33,9 +33,9 @@ public class StrategyWSLoaderProvider extends ProviderAdapter { this.strategy = strategy; } - public WSLoader provide(PersistentCache cache, ServerClient client) { + public WSLoader provide(PersistentCache cache, ServerClient client, GlobalProperties globalProps) { if (wsLoader == null) { - wsLoader = new WSLoader(strategy, cache, client); + wsLoader = new WSLoader(strategy, cache, client, globalProps); } return wsLoader; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/cache/WSLoader.java b/sonar-batch/src/main/java/org/sonar/batch/cache/WSLoader.java index a430a3ce93e..5845469dcf9 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/cache/WSLoader.java +++ b/sonar-batch/src/main/java/org/sonar/batch/cache/WSLoader.java @@ -19,29 +19,29 @@ */ package org.sonar.batch.cache; -import org.sonar.api.utils.HttpDownloader.HttpException; - import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; - import javax.annotation.Nonnull; import javax.annotation.Nullable; - import org.apache.commons.io.IOUtils; +import org.sonar.api.utils.HttpDownloader.HttpException; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.batch.bootstrap.ServerClient; +import org.sonar.batch.bootstrap.UserProperties; import org.sonar.home.cache.PersistentCache; + import static org.sonar.batch.cache.WSLoader.ServerStatus.ACCESSIBLE; import static org.sonar.batch.cache.WSLoader.ServerStatus.NOT_ACCESSIBLE; import static org.sonar.batch.cache.WSLoader.ServerStatus.UNKNOWN; public class WSLoader { + static final String SONAR_WS_TIMEOUT_PROPS = "sonar.ws.timeout"; private static final Logger LOG = Loggers.get(WSLoader.class); private static final String FAIL_MSG = "Server is not accessible and data is not cached"; private static final int CONNECT_TIMEOUT = 5_000; - private static final int READ_TIMEOUT = 600_000; + private static final int DEFAULT_READ_TIMEOUT = 60_000; private static final String REQUEST_METHOD = "GET"; public enum ServerStatus { @@ -55,15 +55,76 @@ public class WSLoader { private final LoadStrategy defautLoadStrategy; private final ServerClient client; private final PersistentCache cache; + private final UserProperties userProperties; private ServerStatus serverStatus; - public WSLoader(LoadStrategy strategy, PersistentCache cache, ServerClient client) { + private DataLoader stringServerLoader = new DataLoader() { + @Override + public String load(String id) throws IOException { + InputStream is = client.load(id, REQUEST_METHOD, true, CONNECT_TIMEOUT, getReadTimeout()); + String str = IOUtils.toString(is, StandardCharsets.UTF_8); + try { + cache.put(id, str.getBytes(StandardCharsets.UTF_8)); + } catch (IOException e) { + throw new IllegalStateException("Error saving to WS cache", e); + } + return str; + } + + }; + + private DataLoader stringCacheLoader = new DataLoader() { + @Override + public String load(String id) throws IOException { + return cache.getString(id); + } + }; + + private DataLoader streamServerLoader = new DataLoader() { + @Override + public InputStream load(String id) throws IOException { + InputStream is = client.load(id, REQUEST_METHOD, true, CONNECT_TIMEOUT, getReadTimeout()); + try { + cache.put(id, is); + } catch (IOException e) { + throw new IllegalStateException("Error saving to WS cache", e); + } + is.close(); + return cache.getStream(id); + } + }; + + private DataLoader streamCacheLoader = new DataLoader() { + @Override + public InputStream load(String id) throws IOException { + return cache.getStream(id); + } + }; + + private class NotAvailableException extends Exception { + private static final long serialVersionUID = 1L; + + public NotAvailableException(String message) { + super(message); + } + + public NotAvailableException(Throwable cause) { + super(cause); + } + } + + public WSLoader(LoadStrategy strategy, PersistentCache cache, ServerClient client, UserProperties settings) { this.defautLoadStrategy = strategy; + this.userProperties = settings; this.serverStatus = UNKNOWN; this.cache = cache; this.client = client; } + private int getReadTimeout() { + return userProperties.properties().containsKey(SONAR_WS_TIMEOUT_PROPS) ? Integer.parseInt(userProperties.property(SONAR_WS_TIMEOUT_PROPS)) * 1000 : DEFAULT_READ_TIMEOUT; + } + @Nonnull public WSLoaderResult loadStream(String id) { return load(id, defautLoadStrategy, streamServerLoader, streamCacheLoader); @@ -185,57 +246,4 @@ public class WSLoader { } } - private DataLoader stringServerLoader = new DataLoader() { - @Override - public String load(String id) throws IOException { - InputStream is = client.load(id, REQUEST_METHOD, true, CONNECT_TIMEOUT, READ_TIMEOUT); - String str = IOUtils.toString(is, StandardCharsets.UTF_8); - try { - cache.put(id, str.getBytes(StandardCharsets.UTF_8)); - } catch (IOException e) { - throw new IllegalStateException("Error saving to WS cache", e); - } - return str; - } - }; - - private DataLoader stringCacheLoader = new DataLoader() { - @Override - public String load(String id) throws IOException { - return cache.getString(id); - } - }; - - private DataLoader streamServerLoader = new DataLoader() { - @Override - public InputStream load(String id) throws IOException { - InputStream is = client.load(id, REQUEST_METHOD, true, CONNECT_TIMEOUT, READ_TIMEOUT); - try { - cache.put(id, is); - } catch (IOException e) { - throw new IllegalStateException("Error saving to WS cache", e); - } - is.close(); - return cache.getStream(id); - } - }; - - private DataLoader streamCacheLoader = new DataLoader() { - @Override - public InputStream load(String id) throws IOException { - return cache.getStream(id); - } - }; - - private class NotAvailableException extends Exception { - private static final long serialVersionUID = 1L; - - public NotAvailableException(String message) { - super(message); - } - - public NotAvailableException(Throwable cause) { - super(cause); - } - } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java b/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java index da9f5211994..3c96cf3ea63 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java +++ b/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java @@ -19,22 +19,21 @@ */ package org.sonar.batch.rule; -import org.sonar.api.utils.log.Profiler; - -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.picocontainer.injectors.ProviderAdapter; -import org.sonar.api.batch.rule.ActiveRules; -import org.sonar.api.batch.rule.internal.ActiveRulesBuilder; -import org.sonar.api.batch.rule.internal.NewActiveRule; -import org.sonar.api.rule.RuleKey; - import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.lang.mutable.MutableBoolean; +import org.picocontainer.injectors.ProviderAdapter; +import org.sonar.api.batch.rule.ActiveRules; +import org.sonar.api.batch.rule.internal.ActiveRulesBuilder; +import org.sonar.api.batch.rule.internal.NewActiveRule; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.api.utils.log.Profiler; /** * Loads the rules that are activated on the Quality profiles @@ -48,13 +47,14 @@ public class ActiveRulesProvider extends ProviderAdapter { public ActiveRules provide(ActiveRulesLoader loader, ModuleQProfiles qProfiles) { if (singleton == null) { Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG); - singleton = load(loader, qProfiles); - profiler.stopInfo(); + MutableBoolean fromCache = new MutableBoolean(); + singleton = load(loader, qProfiles, fromCache); + profiler.stopInfo(fromCache.booleanValue()); } return singleton; } - private static ActiveRules load(ActiveRulesLoader loader, ModuleQProfiles qProfiles) { + private static ActiveRules load(ActiveRulesLoader loader, ModuleQProfiles qProfiles, MutableBoolean fromCache) { Collection qProfileKeys = getKeys(qProfiles); Map loadedRulesByKey = new HashMap<>(); @@ -62,7 +62,7 @@ public class ActiveRulesProvider extends ProviderAdapter { try { for (String qProfileKey : qProfileKeys) { Collection qProfileRules; - qProfileRules = load(loader, qProfileKey); + qProfileRules = load(loader, qProfileKey, fromCache); for (LoadedActiveRule r : qProfileRules) { if (!loadedRulesByKey.containsKey(r.getRuleKey())) { @@ -100,8 +100,8 @@ public class ActiveRulesProvider extends ProviderAdapter { return builder.build(); } - private static List load(ActiveRulesLoader loader, String qProfileKey) throws IOException { - return loader.load(qProfileKey, null); + private static List load(ActiveRulesLoader loader, String qProfileKey, MutableBoolean fromCache) throws IOException { + return loader.load(qProfileKey, fromCache); } private static Collection getKeys(ModuleQProfiles qProfiles) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/DefaultActiveRulesLoader.java b/sonar-batch/src/main/java/org/sonar/batch/rule/DefaultActiveRulesLoader.java index 6c63e451f45..373364dd944 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/rule/DefaultActiveRulesLoader.java +++ b/sonar-batch/src/main/java/org/sonar/batch/rule/DefaultActiveRulesLoader.java @@ -64,6 +64,9 @@ public class DefaultActiveRulesLoader implements ActiveRulesLoader { break; } page++; + if (fromCache != null) { + fromCache.setValue(result.isFromCache()); + } } return ruleList; diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java index b882d231243..7b605d2b9b0 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java @@ -19,29 +19,6 @@ */ package org.sonar.batch.scan; -import org.sonar.batch.repository.ProjectRepositoriesProvider; - -import org.sonar.batch.repository.ProjectRepositories; -import org.sonar.batch.cache.ProjectPersistentCacheProvider; -import org.sonar.batch.issue.tracking.LocalIssueTracking; -import org.sonar.batch.issue.tracking.IssueTransition; -import org.sonar.batch.repository.QualityProfileProvider; -import org.sonar.batch.repository.DefaultQualityProfileLoader; -import org.sonar.batch.repository.QualityProfileLoader; -import org.sonar.batch.rule.DefaultActiveRulesLoader; -import org.sonar.batch.rule.ActiveRulesLoader; -import org.sonar.batch.analysis.DefaultAnalysisMode; -import org.sonar.batch.analysis.AnalysisWSLoaderProvider; -import org.sonar.batch.analysis.AnalysisTempFolderProvider; -import org.sonar.batch.analysis.AnalysisProperties; -import org.sonar.batch.repository.user.UserRepositoryLoader; -import org.sonar.batch.issue.tracking.DefaultServerLineHashesLoader; -import org.sonar.batch.issue.tracking.ServerLineHashesLoader; -import org.sonar.batch.repository.DefaultProjectRepositoriesLoader; -import org.sonar.batch.repository.DefaultServerIssuesLoader; -import org.sonar.batch.repository.ProjectRepositoriesLoader; -import org.sonar.batch.repository.ServerIssuesLoader; -import org.sonar.batch.issue.DefaultIssueCallback; import com.google.common.annotations.VisibleForTesting; import org.sonar.api.CoreProperties; import org.sonar.api.batch.InstantiationStrategy; @@ -55,18 +32,28 @@ import org.sonar.api.utils.log.Loggers; import org.sonar.batch.DefaultFileLinesContextFactory; import org.sonar.batch.DefaultProjectTree; import org.sonar.batch.ProjectConfigurator; +import org.sonar.batch.analysis.AnalysisProperties; +import org.sonar.batch.analysis.AnalysisTempFolderProvider; +import org.sonar.batch.analysis.AnalysisWSLoaderProvider; +import org.sonar.batch.analysis.DefaultAnalysisMode; import org.sonar.batch.bootstrap.ExtensionInstaller; import org.sonar.batch.bootstrap.ExtensionMatcher; import org.sonar.batch.bootstrap.ExtensionUtils; import org.sonar.batch.bootstrap.MetricProvider; +import org.sonar.batch.cache.ProjectPersistentCacheProvider; import org.sonar.batch.duplication.DuplicationCache; import org.sonar.batch.events.EventBus; import org.sonar.batch.index.BatchComponentCache; import org.sonar.batch.index.Caches; import org.sonar.batch.index.DefaultIndex; +import org.sonar.batch.issue.DefaultIssueCallback; import org.sonar.batch.issue.DefaultProjectIssues; import org.sonar.batch.issue.IssueCache; +import org.sonar.batch.issue.tracking.DefaultServerLineHashesLoader; +import org.sonar.batch.issue.tracking.IssueTransition; +import org.sonar.batch.issue.tracking.LocalIssueTracking; import org.sonar.batch.issue.tracking.ServerIssueRepository; +import org.sonar.batch.issue.tracking.ServerLineHashesLoader; import org.sonar.batch.mediumtest.ScanTaskObservers; import org.sonar.batch.phases.PhasesTimeProfiler; import org.sonar.batch.profiling.PhasesSumUpTimeProfiler; @@ -80,8 +67,23 @@ import org.sonar.batch.report.MetadataPublisher; import org.sonar.batch.report.ReportPublisher; import org.sonar.batch.report.SourcePublisher; import org.sonar.batch.report.TestExecutionAndCoveragePublisher; +import org.sonar.batch.repository.DefaultProjectRepositoriesLoader; +import org.sonar.batch.repository.DefaultQualityProfileLoader; +import org.sonar.batch.repository.DefaultServerIssuesLoader; +import org.sonar.batch.repository.ProjectRepositories; +import org.sonar.batch.repository.ProjectRepositoriesLoader; +import org.sonar.batch.repository.ProjectRepositoriesProvider; +import org.sonar.batch.repository.QualityProfileLoader; +import org.sonar.batch.repository.QualityProfileProvider; +import org.sonar.batch.repository.ServerIssuesLoader; import org.sonar.batch.repository.language.DefaultLanguagesRepository; +import org.sonar.batch.repository.user.UserRepositoryLoader; +import org.sonar.batch.rule.ActiveRulesLoader; import org.sonar.batch.rule.ActiveRulesProvider; +import org.sonar.batch.rule.DefaultActiveRulesLoader; +import org.sonar.batch.rule.DefaultRulesLoader; +import org.sonar.batch.rule.RulesLoader; +import org.sonar.batch.rule.RulesProvider; import org.sonar.batch.scan.filesystem.InputPathCache; import org.sonar.batch.scan.measure.DefaultMetricFinder; import org.sonar.batch.scan.measure.DeprecatedMetricFinder; @@ -148,6 +150,7 @@ public class ProjectScanContainer extends ComponentContainer { Caches.class, BatchComponentCache.class, DefaultIssueCallback.class, + new RulesProvider(), new ProjectRepositoriesProvider(), new ProjectPersistentCacheProvider(), @@ -205,6 +208,7 @@ public class ProjectScanContainer extends ComponentContainer { ScanTaskObservers.class, UserRepositoryLoader.class); + addIfMissing(DefaultRulesLoader.class, RulesLoader.class); addIfMissing(DefaultActiveRulesLoader.class, ActiveRulesLoader.class); addIfMissing(DefaultQualityProfileLoader.class, QualityProfileLoader.class); addIfMissing(DefaultProjectRepositoriesLoader.class, ProjectRepositoriesLoader.class); -- cgit v1.2.3