Skip to content

Commit

Permalink
SONAR-6315 use new RegisterQualityProfile code only if property is set
Browse files Browse the repository at this point in the history
  • Loading branch information
sns-seb committed May 12, 2017
1 parent aa60bca commit fde768c
Show file tree
Hide file tree
Showing 10 changed files with 493 additions and 179 deletions.
Expand Up @@ -25,8 +25,12 @@
import org.sonar.server.platform.ServerLifecycleNotifier;
import org.sonar.server.platform.web.RegisterServletFilters;
import org.sonar.server.qualitygate.RegisterQualityGates;
import org.sonar.server.qualityprofile.CachingDefinedQProfileCreationImpl;
import org.sonar.server.qualityprofile.CachingRuleActivator;
import org.sonar.server.qualityprofile.CachingRuleActivatorContextFactory;
import org.sonar.server.qualityprofile.DefinedQProfileInsertImpl;
import org.sonar.server.qualityprofile.DefinedQProfileLoader;
import org.sonar.server.qualityprofile.MassRegisterQualityProfiles;
import org.sonar.server.qualityprofile.RegisterQualityProfiles;
import org.sonar.server.rule.RegisterRules;
import org.sonar.server.startup.DeleteOldAnalysisReportsFromFs;
Expand Down Expand Up @@ -57,6 +61,10 @@ protected void configureLevel() {
add(DefinedQProfileLoader.class);
addIfStartupLeader(
DefinedQProfileInsertImpl.class,
MassRegisterQualityProfiles.class,
CachingRuleActivatorContextFactory.class,
CachingRuleActivator.class,
CachingDefinedQProfileCreationImpl.class,
RegisterQualityProfiles.class,
RegisterPermissionTemplates.class,
RenameDeprecatedPropertyKeys.class,
Expand Down
@@ -0,0 +1,26 @@
/*
* SonarQube
* Copyright (C) 2009-2017 SonarSource SA
* mailto:info 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.server.qualityprofile;

/**
* Marker interface of any implementation of {@link DefinedQProfileCreation} which supports caching.
*/
public interface CachingDefinedQProfileCreation extends DefinedQProfileCreation {
}
@@ -0,0 +1,28 @@
/*
* SonarQube
* Copyright (C) 2009-2017 SonarSource SA
* mailto:info 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.server.qualityprofile;

import org.sonar.db.DbClient;

public class CachingDefinedQProfileCreationImpl extends DefinedQProfileCreationImpl implements CachingDefinedQProfileCreation {
public CachingDefinedQProfileCreationImpl(DbClient dbClient, QProfileFactory profileFactory, CachingRuleActivator ruleActivator) {
super(dbClient, profileFactory, ruleActivator);
}
}
@@ -0,0 +1,55 @@
/*
* SonarQube
* Copyright (C) 2009-2017 SonarSource SA
* mailto:info 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.server.qualityprofile;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.List;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
import org.sonar.server.rule.index.RuleIndex;
import org.sonar.server.user.UserSession;
import org.sonar.server.util.TypeValidations;

public class CachingRuleActivator extends RuleActivator {
private final Cache<String, List<QualityProfileDto>> childrenByParentKey = CacheBuilder.newBuilder()
.maximumSize(10_000)
.build();

public CachingRuleActivator(System2 system2, DbClient db, RuleIndex ruleIndex, CachingRuleActivatorContextFactory contextFactory, TypeValidations typeValidations,
ActiveRuleIndexer activeRuleIndexer, UserSession userSession) {
super(system2, db, ruleIndex, contextFactory, typeValidations, activeRuleIndexer, userSession);
}

@Override
protected List<QualityProfileDto> getChildren(DbSession session, String qualityProfileKey) {
List<QualityProfileDto> res = childrenByParentKey.getIfPresent(qualityProfileKey);
if (res != null) {
return res;
}
res = super.getChildren(session, qualityProfileKey);
childrenByParentKey.put(qualityProfileKey, res);
return res;
}

}
@@ -0,0 +1,83 @@
/*
* SonarQube
* Copyright (C) 2009-2017 SonarSource SA
* mailto:info 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.server.qualityprofile;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import org.picocontainer.Startable;
import org.sonar.api.rule.RuleKey;
import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.qualityprofile.ActiveRuleDto;
import org.sonar.db.qualityprofile.ActiveRuleKey;
import org.sonar.db.rule.RuleDefinitionDto;

public class CachingRuleActivatorContextFactory extends RuleActivatorContextFactory implements Startable {
private final DbClient dbClient;
private final Map<RuleKey, RuleDefinitionDto> rulesByRuleKey = new HashMap<>();
private final Cache<String, Map<RuleKey, ActiveRuleDto>> childrenByParentKey = CacheBuilder.newBuilder()
.maximumSize(10)
.build();

public CachingRuleActivatorContextFactory(DbClient db) {
super(db);
this.dbClient = db;
}

@Override
public void start() {
try (DbSession dbSession = dbClient.openSession(false)) {
dbClient.ruleDao().selectAllDefinitions(dbSession).forEach(rule -> rulesByRuleKey.put(rule.getKey(), rule));
}
}

@Override
public void stop() {
// nothing to do
}

@Override
Optional<RuleDefinitionDto> getRule(DbSession dbSession, RuleKey ruleKey) {
return Optional.ofNullable(rulesByRuleKey.get(ruleKey));
}

@Override
Optional<ActiveRuleDto> getActiveRule(DbSession session, ActiveRuleKey key) {
try {
String profileKey = key.qProfile();
Map<RuleKey, ActiveRuleDto> profileActiveRulesByRuleKey = childrenByParentKey.get(
profileKey,
() -> loadActiveRulesOfQualityProfile(session, profileKey));
return Optional.ofNullable(profileActiveRulesByRuleKey.get(key.ruleKey()));
} catch (ExecutionException e) {
throw new IllegalStateException(e.getCause());
}
}

private Map<RuleKey, ActiveRuleDto> loadActiveRulesOfQualityProfile(DbSession session, String profileKey) {
return dbClient.activeRuleDao().selectByProfileKey(session, profileKey).stream()
.collect(MoreCollectors.uniqueIndex(dto -> dto.getKey().ruleKey()));
}
}
Expand Up @@ -20,10 +20,18 @@
package org.sonar.server.qualityprofile;

import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.api.rule.RuleKey;
Expand All @@ -47,13 +55,14 @@
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Lists.newArrayList;
import static java.util.Objects.requireNonNull;

public class DefinedQProfileInsertImpl implements DefinedQProfileInsert {
private final DbClient dbClient;
private final System2 system2;
private final UuidFactory uuidFactory;
private final TypeValidations typeValidations;
private RegisterQualityProfiles.RuleRepository ruleRepository;
private RuleRepository ruleRepository;

public DefinedQProfileInsertImpl(DbClient dbClient, System2 system2, UuidFactory uuidFactory, TypeValidations typeValidations) {
this.dbClient = dbClient;
Expand All @@ -68,10 +77,6 @@ public void create(DbSession session, DefinedQProfile definedQProfile, Organizat

checkArgument(definedQProfile.getParentQProfileName() == null,
"Inheritance of Quality Profiles is not supported yet");
// Optional.ofNullable(definedQProfile.getParentQProfileName())
// .map(parentQProfileName -> dbClient.qualityProfileDao().selectByNameAndLanguage(organization, parentQProfileName.getName(),
// parentQProfileName.getLanguage(), session))
// .map(parentQualityProfileDto -> dbClient.activeRuleDao().selectByRuleIds());

Date now = new Date(system2.now());
QualityProfileDto profileDto = insertQualityProfile(session, definedQProfile, organization, now);
Expand All @@ -90,7 +95,7 @@ public void create(DbSession session, DefinedQProfile definedQProfile, Organizat

private void initRuleRepository(DbSession session) {
if (ruleRepository == null) {
ruleRepository = new RegisterQualityProfiles.RuleRepository(dbClient, session);
ruleRepository = new RuleRepository(dbClient, session);
}
}

Expand All @@ -111,15 +116,7 @@ private ActiveRuleChange insertActiveRule(DbSession session, QualityProfileDto p
.orElseThrow(() -> new IllegalStateException("RuleDefinition not found for key " + ruleKey));

ActiveRuleDto dto = ActiveRuleDto.createFor(profileDto, ruleDefinitionDto);
dto.setSeverity(
firstNonNull(
activeRule.getSeverity().name(),
// context.parentSeverity(),
ruleDefinitionDto.getSeverityString()));
// ActiveRule.Inheritance inheritance = activeRule.getInheritance();
// if (inheritance != null) {
// activeRule.setInheritance(inheritance.name());
// }
dto.setSeverity(firstNonNull(activeRule.getSeverity().name(), ruleDefinitionDto.getSeverityString()));
dto.setUpdatedAt(now);
dto.setCreatedAt(now);
dbClient.activeRuleDao().insert(session, dto);
Expand Down Expand Up @@ -173,4 +170,37 @@ private void insertTemplate(DbSession session, DefinedQProfile qualityProfile, O
LoadedTemplateDto template = new LoadedTemplateDto(organization.getUuid(), qualityProfile.getLoadedTemplateType());
dbClient.loadedTemplateDao().insert(template, session);
}

public static class RuleRepository {
private final Map<RuleKey, RuleDefinitionDto> ruleDefinitions;
private final Map<RuleKey, Set<RuleParamDto>> ruleParams;

private RuleRepository(DbClient dbClient, DbSession session) {
this.ruleDefinitions = dbClient.ruleDao().selectAllDefinitions(session)
.stream()
.collect(Collectors.toMap(RuleDefinitionDto::getKey, Function.identity()));
Map<Integer, RuleKey> ruleIdsByKey = ruleDefinitions.values()
.stream()
.collect(MoreCollectors.uniqueIndex(RuleDefinitionDto::getId, RuleDefinitionDto::getKey));
this.ruleParams = new HashMap<>(ruleIdsByKey.size());
dbClient.ruleDao().selectRuleParamsByRuleKeys(session, ruleDefinitions.keySet())
.forEach(ruleParam -> ruleParams.compute(
ruleIdsByKey.get(ruleParam.getRuleId()),
(key, value) -> {
if (value == null) {
return ImmutableSet.of(ruleParam);
}
return ImmutableSet.copyOf(Sets.union(value, Collections.singleton(ruleParam)));
}));
}

Optional<RuleDefinitionDto> getDefinition(RuleKey ruleKey) {
return Optional.ofNullable(ruleDefinitions.get(requireNonNull(ruleKey, "RuleKey can't be null")));
}

Set<RuleParamDto> getRuleParams(RuleKey ruleKey) {
Set<RuleParamDto> res = ruleParams.get(requireNonNull(ruleKey, "RuleKey can't be null"));
return res == null ? Collections.emptySet() : res;
}
}
}

0 comments on commit fde768c

Please sign in to comment.