Skip to content

Commit

Permalink
SONAR-8924 let api/qualityprofiles/search use project’s organization
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Schwarz authored and bartfastiel committed May 4, 2017
1 parent 5e1fdd1 commit 5a73d80
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 120 deletions.
Expand Up @@ -34,6 +34,7 @@
import org.sonar.db.DbSession; import org.sonar.db.DbSession;
import org.sonar.db.KeyLongValue; import org.sonar.db.KeyLongValue;
import org.sonar.db.RowNotFoundException; import org.sonar.db.RowNotFoundException;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.organization.OrganizationDto; import org.sonar.db.organization.OrganizationDto;


import static org.sonar.db.DatabaseUtils.executeLargeInputs; import static org.sonar.db.DatabaseUtils.executeLargeInputs;
Expand Down Expand Up @@ -111,8 +112,8 @@ public QualityProfileDto selectByProjectAndLanguage(DbSession session, String pr
return mapper(session).selectByProjectAndLanguage(projectKey, language); return mapper(session).selectByProjectAndLanguage(projectKey, language);
} }


public List<QualityProfileDto> selectByProjectAndLanguages(DbSession session, OrganizationDto organization, String projectKey, Collection<String> languageKeys) { public List<QualityProfileDto> selectByProjectAndLanguages(DbSession session, OrganizationDto organization, ComponentDto project, Collection<String> languageKeys) {
return executeLargeInputs(languageKeys, input -> mapper(session).selectByProjectAndLanguages(organization.getUuid(), projectKey, input)); return executeLargeInputs(languageKeys, input -> mapper(session).selectByProjectAndLanguages(organization.getUuid(), project.getKey(), input));
} }


public List<QualityProfileDto> selectByLanguage(DbSession dbSession, OrganizationDto organization, String language) { public List<QualityProfileDto> selectByLanguage(DbSession dbSession, OrganizationDto organization, String language) {
Expand Down
Expand Up @@ -330,16 +330,18 @@ public void select_by_project_key_and_language() {
} }


@Test @Test
public void select_by_project_key_and_languages() { public void select_by_project_and_languages() {
dbTester.prepareDbUnit(getClass(), "projects.xml"); dbTester.prepareDbUnit(getClass(), "projects.xml");


OrganizationDto organization = dbTester.organizations().insert(OrganizationTesting.newOrganizationDto().setUuid("org1")); OrganizationDto organization = dbTester.organizations().insert(OrganizationTesting.newOrganizationDto().setUuid("org1"));
List<QualityProfileDto> dto = underTest.selectByProjectAndLanguages(dbTester.getSession(), organization, "org.codehaus.sonar:sonar", singletonList("java")); ComponentDto project = dbTester.getDbClient().componentDao().selectOrFailByKey(dbTester.getSession(), "org.codehaus.sonar:sonar");
ComponentDto unknownProject = dbTester.components().insertPrivateProject(organization, p -> p.setKey("unknown"));
List<QualityProfileDto> dto = underTest.selectByProjectAndLanguages(dbTester.getSession(), organization, project, singletonList("java"));
assertThat(dto).extracting("id").containsOnly(1); assertThat(dto).extracting("id").containsOnly(1);


assertThat(underTest.selectByProjectAndLanguages(dbTester.getSession(), organization, "org.codehaus.sonar:sonar", singletonList("unkown"))).isEmpty(); assertThat(underTest.selectByProjectAndLanguages(dbTester.getSession(), organization, project, singletonList("unkown"))).isEmpty();
assertThat(underTest.selectByProjectAndLanguages(dbTester.getSession(), organization, "org.codehaus.sonar:sonar", of("java", "unkown"))).extracting("id").containsOnly(1); assertThat(underTest.selectByProjectAndLanguages(dbTester.getSession(), organization, project, of("java", "unkown"))).extracting("id").containsOnly(1);
assertThat(underTest.selectByProjectAndLanguages(dbTester.getSession(), organization, "unknown", singletonList("java"))).isEmpty(); assertThat(underTest.selectByProjectAndLanguages(dbTester.getSession(), organization, unknownProject, singletonList("java"))).isEmpty();
} }


@Test @Test
Expand Down
Expand Up @@ -23,6 +23,7 @@
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.sonar.api.resources.Languages; import org.sonar.api.resources.Languages;
import org.sonar.api.rule.RuleStatus; import org.sonar.api.rule.RuleStatus;
import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Request;
Expand All @@ -31,6 +32,7 @@
import org.sonar.api.server.ws.WebService.NewAction; import org.sonar.api.server.ws.WebService.NewAction;
import org.sonar.db.DbClient; import org.sonar.db.DbClient;
import org.sonar.db.DbSession; import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.organization.OrganizationDto; import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.qualityprofile.QualityProfileDto; import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.server.util.LanguageParamUtils; import org.sonar.server.util.LanguageParamUtils;
Expand All @@ -41,6 +43,7 @@
import static java.lang.String.format; import static java.lang.String.format;
import static java.util.function.Function.identity; import static java.util.function.Function.identity;
import static org.sonar.api.utils.DateUtils.formatDateTime; import static org.sonar.api.utils.DateUtils.formatDateTime;
import static org.sonar.server.ws.WsUtils.checkFoundWithOptional;
import static org.sonar.server.ws.WsUtils.checkRequest; import static org.sonar.server.ws.WsUtils.checkRequest;
import static org.sonar.server.ws.WsUtils.writeProtobuf; import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_SEARCH; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_SEARCH;
Expand Down Expand Up @@ -125,16 +128,43 @@ SearchWsResponse doHandle(SearchWsRequest request) {


private SearchData load(SearchWsRequest request) { private SearchData load(SearchWsRequest request) {
try (DbSession dbSession = dbClient.openSession(false)) { try (DbSession dbSession = dbClient.openSession(false)) {
OrganizationDto organization = wsSupport.getOrganizationByKey(dbSession, request.getOrganizationKey());
@Nullable ComponentDto project;
OrganizationDto organization;
if (request.getProjectKey() == null) {
project = null;
organization = wsSupport.getOrganizationByKey(dbSession, request.getOrganizationKey());
} else {
project = getProject(request.getProjectKey(), dbSession);
organization = dbClient.organizationDao().selectByUuid(dbSession, project.getOrganizationUuid())
.orElseThrow(() -> new IllegalStateException(
String.format("Organization with uuid '%s' is referenced by project '%s' but could not be found", project.getOrganizationUuid(), project.getKey())));
if (request.getOrganizationKey() != null && !request.getOrganizationKey().equals(organization.getKey())) {
throw new IllegalArgumentException(String.format("The provided organization key '%s' does not match the organization key '%s' of the component '%s'",
request.getOrganizationKey(),
organization.getKey(),
project.getKey()
));
}
}

return new SearchData() return new SearchData()
.setOrganization(organization) .setOrganization(organization)
.setProfiles(dataLoader.findProfiles(dbSession, request, organization)) .setProfiles(dataLoader.findProfiles(dbSession, request, organization, project))
.setActiveRuleCountByProfileKey(dbClient.activeRuleDao().countActiveRulesByProfileKey(dbSession, organization)) .setActiveRuleCountByProfileKey(dbClient.activeRuleDao().countActiveRulesByProfileKey(dbSession, organization))
.setActiveDeprecatedRuleCountByProfileKey(dbClient.activeRuleDao().countActiveRulesForRuleStatusByProfileKey(dbSession, organization, RuleStatus.DEPRECATED)) .setActiveDeprecatedRuleCountByProfileKey(dbClient.activeRuleDao().countActiveRulesForRuleStatusByProfileKey(dbSession, organization, RuleStatus.DEPRECATED))
.setProjectCountByProfileKey(dbClient.qualityProfileDao().countProjectsByProfileKey(dbSession, organization)); .setProjectCountByProfileKey(dbClient.qualityProfileDao().countProjectsByProfileKey(dbSession, organization));
} }
} }


private ComponentDto getProject(String moduleKey, DbSession dbSession) {
ComponentDto module = checkFoundWithOptional(dbClient.componentDao().selectByKey(dbSession, moduleKey), "Component key '%s' not found", moduleKey);
if (module.isRootProject()) {
return module;
}
return dbClient.componentDao().selectOrFailByUuid(dbSession, module.projectUuid());
}

private static void validateRequest(SearchWsRequest request) { private static void validateRequest(SearchWsRequest request) {
boolean hasLanguage = request.getLanguage() != null; boolean hasLanguage = request.getLanguage() != null;
boolean isDefault = request.getDefaults(); boolean isDefault = request.getDefaults();
Expand Down
Expand Up @@ -37,7 +37,6 @@
import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentDto;
import org.sonar.db.organization.OrganizationDto; import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.qualityprofile.QualityProfileDto; import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.qualityprofile.QProfileLookup; import org.sonar.server.qualityprofile.QProfileLookup;
import org.sonarqube.ws.client.qualityprofile.SearchWsRequest; import org.sonarqube.ws.client.qualityprofile.SearchWsRequest;


Expand All @@ -52,23 +51,20 @@ public class SearchDataLoader {
private final Languages languages; private final Languages languages;
private final QProfileLookup profileLookup; private final QProfileLookup profileLookup;
private final DbClient dbClient; private final DbClient dbClient;
private final ComponentFinder componentFinder;


public SearchDataLoader(Languages languages, QProfileLookup profileLookup, DbClient dbClient, public SearchDataLoader(Languages languages, QProfileLookup profileLookup, DbClient dbClient) {
ComponentFinder componentFinder) {
this.languages = languages; this.languages = languages;
this.profileLookup = profileLookup; this.profileLookup = profileLookup;
this.dbClient = dbClient; this.dbClient = dbClient;
this.componentFinder = componentFinder;
} }


@VisibleForTesting @VisibleForTesting
List<QualityProfileDto> findProfiles(DbSession dbSession, SearchWsRequest request, OrganizationDto organization) { List<QualityProfileDto> findProfiles(DbSession dbSession, SearchWsRequest request, OrganizationDto organization, @Nullable ComponentDto project) {
Collection<QualityProfileDto> profiles; Collection<QualityProfileDto> profiles;
if (askDefaultProfiles(request)) { if (askDefaultProfiles(request)) {
profiles = findDefaultProfiles(dbSession, request, organization); profiles = findDefaultProfiles(dbSession, request, organization);
} else if (hasComponentKey(request)) { } else if (project != null) {
profiles = findProjectProfiles(dbSession, request, organization); profiles = findProjectProfiles(dbSession, request, organization, project);
} else { } else {
profiles = findAllProfiles(dbSession, request, organization); profiles = findAllProfiles(dbSession, request, organization);
} }
Expand All @@ -92,8 +88,7 @@ private Collection<QualityProfileDto> findDefaultProfiles(DbSession dbSession, S
return qualityProfiles.values(); return qualityProfiles.values();
} }


private Collection<QualityProfileDto> findProjectProfiles(DbSession dbSession, SearchWsRequest request, OrganizationDto organization) { private Collection<QualityProfileDto> findProjectProfiles(DbSession dbSession, SearchWsRequest request, OrganizationDto organization, ComponentDto project) {
String componentKey = request.getProjectKey();
String profileName = request.getProfileName(); String profileName = request.getProfileName();


Set<String> languageKeys = getLanguageKeys(); Set<String> languageKeys = getLanguageKeys();
Expand All @@ -102,12 +97,12 @@ private Collection<QualityProfileDto> findProjectProfiles(DbSession dbSession, S
// look up profiles by profileName (if any) for each language // look up profiles by profileName (if any) for each language
Set<String> unresolvedLanguages = lookupByProfileName(dbSession, organization, qualityProfiles, languageKeys, profileName); Set<String> unresolvedLanguages = lookupByProfileName(dbSession, organization, qualityProfiles, languageKeys, profileName);
// look up profile by componentKey for each language for which we don't have one yet // look up profile by componentKey for each language for which we don't have one yet
Set<String> stillUnresolvedLanguages = lookupByModuleKey(dbSession, organization, qualityProfiles, unresolvedLanguages, componentKey); Set<String> stillUnresolvedLanguages = lookupByModule(dbSession, organization, qualityProfiles, unresolvedLanguages, project);
// look up profile by default for each language for which we don't have one yet // look up profile by default for each language for which we don't have one yet
Set<String> noDefaultProfileLanguages = lookupDefaults(dbSession, organization, qualityProfiles, stillUnresolvedLanguages); Set<String> noDefaultProfileLanguages = lookupDefaults(dbSession, organization, qualityProfiles, stillUnresolvedLanguages);


if (!noDefaultProfileLanguages.isEmpty()) { if (!noDefaultProfileLanguages.isEmpty()) {
throw new IllegalStateException(format("No quality profile can been found on language(s) '%s' for project '%s'", noDefaultProfileLanguages, componentKey)); throw new IllegalStateException(format("No quality profile can been found on language(s) '%s' for project '%s'", noDefaultProfileLanguages, project.getKey()));
} }


return qualityProfiles.values(); return qualityProfiles.values();
Expand All @@ -134,26 +129,17 @@ private Set<String> lookupByProfileName(DbSession dbSession, OrganizationDto org
return difference(languageKeys, qualityProfiles.keySet()); return difference(languageKeys, qualityProfiles.keySet());
} }


private Set<String> lookupByModuleKey(DbSession dbSession, OrganizationDto organization, Map<String, QualityProfileDto> qualityProfiles, Set<String> languageKeys, private Set<String> lookupByModule(DbSession dbSession, OrganizationDto organization, Map<String, QualityProfileDto> qualityProfiles, Set<String> languageKeys,
@Nullable String moduleKey) { ComponentDto project) {
if (languageKeys.isEmpty() || moduleKey == null) { if (languageKeys.isEmpty()) {
return languageKeys; return languageKeys;
} }


ComponentDto project = getProject(moduleKey, dbSession); dbClient.qualityProfileDao().selectByProjectAndLanguages(dbSession, organization, project, languageKeys)
dbClient.qualityProfileDao().selectByProjectAndLanguages(dbSession, organization, project.getKey(), languageKeys)
.forEach(qualityProfile -> qualityProfiles.put(qualityProfile.getLanguage(), qualityProfile)); .forEach(qualityProfile -> qualityProfiles.put(qualityProfile.getLanguage(), qualityProfile));
return difference(languageKeys, qualityProfiles.keySet()); return difference(languageKeys, qualityProfiles.keySet());
} }


private ComponentDto getProject(String moduleKey, DbSession session) {
ComponentDto module = componentFinder.getByKey(session, moduleKey);
if (module.isRootProject()) {
return module;
}
return dbClient.componentDao().selectOrFailByUuid(session, module.projectUuid());
}

private Set<String> lookupDefaults(DbSession dbSession, OrganizationDto organization, Map<String, QualityProfileDto> qualityProfiles, Set<String> languageKeys) { private Set<String> lookupDefaults(DbSession dbSession, OrganizationDto organization, Map<String, QualityProfileDto> qualityProfiles, Set<String> languageKeys) {
if (languageKeys.isEmpty()) { if (languageKeys.isEmpty()) {
return languageKeys; return languageKeys;
Expand Down Expand Up @@ -182,8 +168,4 @@ private List<QualityProfileDto> findDefaultProfiles(final DbSession dbSession, O
private static boolean askDefaultProfiles(SearchWsRequest request) { private static boolean askDefaultProfiles(SearchWsRequest request) {
return request.getDefaults(); return request.getDefaults();
} }

private static boolean hasComponentKey(SearchWsRequest request) {
return request.getProjectKey() != null;
}
} }

0 comments on commit 5a73d80

Please sign in to comment.