@@ -30,8 +30,8 @@ import org.sonar.ce.task.step.ComputationStep; | |||
*/ | |||
public class TriggerViewRefreshStep implements ComputationStep { | |||
@Nullable | |||
private final TriggerViewRefreshDelegate triggerViewRefreshDelegate; | |||
private final TriggerViewRefreshDelegate[] triggerViewRefreshDelegates; | |||
private final AnalysisMetadataHolder analysisMetadata; | |||
/** | |||
@@ -39,15 +39,15 @@ public class TriggerViewRefreshStep implements ComputationStep { | |||
*/ | |||
public TriggerViewRefreshStep(AnalysisMetadataHolder analysisMetadata) { | |||
this.analysisMetadata = analysisMetadata; | |||
this.triggerViewRefreshDelegate = null; | |||
this.triggerViewRefreshDelegates = new TriggerViewRefreshDelegate[0]; | |||
} | |||
/** | |||
* Constructor used by Pico when an implementation of {@link TriggerViewRefreshDelegate} is available | |||
*/ | |||
public TriggerViewRefreshStep(AnalysisMetadataHolder analysisMetadata, @Nullable TriggerViewRefreshDelegate triggerViewRefreshDelegate) { | |||
public TriggerViewRefreshStep(AnalysisMetadataHolder analysisMetadata, TriggerViewRefreshDelegate[] triggerViewRefreshDelegates) { | |||
this.analysisMetadata = analysisMetadata; | |||
this.triggerViewRefreshDelegate = triggerViewRefreshDelegate; | |||
this.triggerViewRefreshDelegates = triggerViewRefreshDelegates; | |||
} | |||
@Override | |||
@@ -57,9 +57,9 @@ public class TriggerViewRefreshStep implements ComputationStep { | |||
@Override | |||
public void execute(ComputationStep.Context context) { | |||
if (triggerViewRefreshDelegate != null) { | |||
for (TriggerViewRefreshDelegate triggerViewRefreshDelegate : this.triggerViewRefreshDelegates) { | |||
OptionalInt count = triggerViewRefreshDelegate.triggerFrom(analysisMetadata.getProject()); | |||
count.ifPresent(i -> context.getStatistics().add("refreshes", i)); | |||
count.ifPresent(i -> context.getStatistics().add("refreshes" + triggerViewRefreshDelegate.getQualifier(), i)); | |||
} | |||
} | |||
} |
@@ -33,4 +33,6 @@ public interface TriggerViewRefreshDelegate { | |||
*/ | |||
OptionalInt triggerFrom(Project project); | |||
String getQualifier(); | |||
} |
@@ -44,7 +44,7 @@ public class TriggerViewRefreshStepTest { | |||
@Test | |||
public void execute_has_no_effect_if_constructor_with_null_delegate() { | |||
TriggerViewRefreshStep underTest = new TriggerViewRefreshStep(analysisMetadataHolder, null); | |||
TriggerViewRefreshStep underTest = new TriggerViewRefreshStep(analysisMetadataHolder); | |||
underTest.execute(new TestComputationStepContext()); | |||
@@ -56,7 +56,7 @@ public class TriggerViewRefreshStepTest { | |||
TriggerViewRefreshDelegate delegate = mock(TriggerViewRefreshDelegate.class); | |||
Project project = mock(Project.class); | |||
when(analysisMetadataHolder.getProject()).thenReturn(project); | |||
TriggerViewRefreshStep underTest = new TriggerViewRefreshStep(analysisMetadataHolder, delegate); | |||
TriggerViewRefreshStep underTest = new TriggerViewRefreshStep(analysisMetadataHolder, new TriggerViewRefreshDelegate[]{delegate}); | |||
underTest.execute(new TestComputationStepContext()); | |||
@@ -19,12 +19,22 @@ | |||
*/ | |||
package org.sonar.ce.task.projectanalysis.component; | |||
import com.google.common.collect.ImmutableMap; | |||
import java.util.Map; | |||
import java.util.Optional; | |||
import javax.annotation.CheckForNull; | |||
import org.junit.rules.ExternalResource; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
import static java.util.Objects.requireNonNull; | |||
import static org.sonar.ce.task.projectanalysis.component.ComponentVisitor.Order.POST_ORDER; | |||
public class TreeRootHolderRule extends ExternalResource implements TreeRootHolder { | |||
protected TreeRootHolderImpl delegate = new TreeRootHolderImpl(); | |||
@CheckForNull | |||
private Map<String, Component> componentsByKey; | |||
@Override | |||
protected void after() { | |||
this.delegate = null; | |||
@@ -40,6 +50,34 @@ public class TreeRootHolderRule extends ExternalResource implements TreeRootHold | |||
return this; | |||
} | |||
public Component getComponentByKey(String key) { | |||
checkKeyArgument(key); | |||
ensureComponentByKeyIsPopulated(); | |||
Component component = componentsByKey.get(key); | |||
checkArgument(component != null, "Component with key '%s' can't be found", key); | |||
return component; | |||
} | |||
private static void checkKeyArgument(String key) { | |||
requireNonNull(key, "key can not be null"); | |||
} | |||
private void ensureComponentByKeyIsPopulated() { | |||
if (componentsByKey != null) { | |||
return; | |||
} | |||
final ImmutableMap.Builder<String, Component> builder = ImmutableMap.builder(); | |||
new DepthTraversalTypeAwareCrawler( | |||
new TypeAwareVisitorAdapter(CrawlerDepthLimit.LEAVES, POST_ORDER) { | |||
@Override | |||
public void visitAny(Component component) { | |||
builder.put(component.getDbKey(), component); | |||
} | |||
}).visit(getRoot()); | |||
this.componentsByKey = builder.build(); | |||
} | |||
@Override | |||
public boolean isEmpty() { | |||
return delegate.isEmpty(); |
@@ -195,9 +195,17 @@ public class ComponentTesting { | |||
return newApplication(organizationDto.getUuid()); | |||
} | |||
public static ComponentDto newApplication(OrganizationDto organizationDto, String uuid) { | |||
return newApplication(organizationDto.getUuid(), uuid); | |||
} | |||
public static ComponentDto newApplication(String organizationUuid) { | |||
return newView(organizationUuid, Uuids.createFast()) | |||
.setQualifier(Qualifiers.APP); | |||
return newApplication(organizationUuid, Uuids.createFast()); | |||
} | |||
public static ComponentDto newApplication(String organizationUuid, String uuid) { | |||
return newView(organizationUuid, uuid).setQualifier(Qualifiers.APP); | |||
} | |||
public static ComponentDto newProjectCopy(ComponentDto project, ComponentDto view) { |
@@ -334,6 +334,7 @@ public class SearchProjectsAction implements ComponentsWsAction { | |||
switch (edition.get()) { | |||
case ENTERPRISE: | |||
case DATACENTER: | |||
case DEVELOPER: | |||
return Sets.newHashSet(Qualifiers.PROJECT, Qualifiers.APP); | |||
default: | |||
return Sets.newHashSet(Qualifiers.PROJECT); |
@@ -41,20 +41,31 @@ public class DefaultTemplatesResolverImpl implements DefaultTemplatesResolver { | |||
String defaultProjectTemplate = dbClient.internalPropertiesDao().selectByKey(dbSession, InternalProperties.DEFAULT_PROJECT_TEMPLATE).orElseThrow(() -> { | |||
throw new IllegalStateException("Default template for project is missing"); | |||
}); | |||
if (!isPortfolioEnabled(resourceTypes)) { | |||
return new ResolvedDefaultTemplates(defaultProjectTemplate, null, null); | |||
} else { | |||
String defaultPortfolioTemplate = dbClient.internalPropertiesDao().selectByKey(dbSession, InternalProperties.DEFAULT_PORTFOLIO_TEMPLATE).orElse(defaultProjectTemplate); | |||
String defaultApplicationTemplate = dbClient.internalPropertiesDao().selectByKey(dbSession, InternalProperties.DEFAULT_APPLICATION_TEMPLATE).orElse(defaultProjectTemplate); | |||
return new ResolvedDefaultTemplates(defaultProjectTemplate, defaultApplicationTemplate, defaultPortfolioTemplate); | |||
String defaultPortfolioTemplate = null; | |||
String defaultApplicationTemplate = null; | |||
if (isPortfolioEnabled(resourceTypes)) { | |||
defaultPortfolioTemplate = dbClient.internalPropertiesDao().selectByKey(dbSession, InternalProperties.DEFAULT_PORTFOLIO_TEMPLATE).orElse(defaultProjectTemplate); | |||
} | |||
if (isApplicationEnabled(resourceTypes)) { | |||
defaultApplicationTemplate = dbClient.internalPropertiesDao().selectByKey(dbSession, InternalProperties.DEFAULT_APPLICATION_TEMPLATE).orElse(defaultProjectTemplate); | |||
} | |||
return new ResolvedDefaultTemplates(defaultProjectTemplate, defaultApplicationTemplate, defaultPortfolioTemplate); | |||
} | |||
private static boolean isPortfolioEnabled(ResourceTypes resourceTypes) { | |||
return resourceTypes.getRoots() | |||
.stream() | |||
.map(ResourceType::getQualifier) | |||
.anyMatch(qualifier -> Qualifiers.VIEW.equals(qualifier) || Qualifiers.APP.equals(qualifier)); | |||
.anyMatch(qualifier -> Qualifiers.VIEW.equals(qualifier)); | |||
} | |||
private static boolean isApplicationEnabled(ResourceTypes resourceTypes) { | |||
return resourceTypes.getRoots() | |||
.stream() | |||
.map(ResourceType::getQualifier) | |||
.anyMatch(qualifier -> Qualifiers.APP.equals(qualifier)); | |||
} | |||
} |
@@ -142,7 +142,7 @@ public class SearchProjectsActionTest { | |||
public static Object[][] component_qualifiers_for_valid_editions() { | |||
return new Object[][] { | |||
{new String[] {Qualifiers.PROJECT}, Edition.COMMUNITY}, | |||
{new String[] {Qualifiers.PROJECT}, Edition.DEVELOPER}, | |||
{new String[] {Qualifiers.APP, Qualifiers.PROJECT}, Edition.DEVELOPER}, | |||
{new String[] {Qualifiers.APP, Qualifiers.PROJECT}, Edition.ENTERPRISE}, | |||
{new String[] {Qualifiers.APP, Qualifiers.PROJECT}, Edition.DATACENTER}, | |||
}; |
@@ -38,9 +38,11 @@ public class DefaultTemplatesResolverImplTest { | |||
public DbTester db = DbTester.create(System2.INSTANCE); | |||
private ResourceTypesRule resourceTypesWithPortfoliosInstalled = new ResourceTypesRule().setRootQualifiers(PROJECT, APP, VIEW); | |||
private ResourceTypesRule resourceTypesWithApplicationInstalled = new ResourceTypesRule().setRootQualifiers(PROJECT, APP); | |||
private ResourceTypesRule resourceTypes = new ResourceTypesRule().setRootQualifiers(PROJECT); | |||
private DefaultTemplatesResolverImpl underTestWithPortfoliosInstalled = new DefaultTemplatesResolverImpl(db.getDbClient(), resourceTypesWithPortfoliosInstalled); | |||
private DefaultTemplatesResolverImpl underTestWithApplicationInstalled = new DefaultTemplatesResolverImpl(db.getDbClient(), resourceTypesWithApplicationInstalled); | |||
private DefaultTemplatesResolverImpl underTest = new DefaultTemplatesResolverImpl(db.getDbClient(), resourceTypes); | |||
@Test | |||
@@ -79,6 +81,24 @@ public class DefaultTemplatesResolverImplTest { | |||
assertThat(underTestWithPortfoliosInstalled.resolve(db.getSession()).getPortfolio()).contains("port"); | |||
} | |||
@Test | |||
public void get_default_templates_always_return_project_template_when_only_project_template_and_application_is_installed_() { | |||
db.permissionTemplates().setDefaultTemplates("prj", null, null); | |||
assertThat(underTestWithApplicationInstalled.resolve(db.getSession()).getProject()).contains("prj"); | |||
assertThat(underTestWithApplicationInstalled.resolve(db.getSession()).getApplication()).contains("prj"); | |||
assertThat(underTestWithApplicationInstalled.resolve(db.getSession()).getPortfolio()).isEmpty(); | |||
} | |||
@Test | |||
public void get_default_templates_for_all_components_when_application_is_installed() { | |||
db.permissionTemplates().setDefaultTemplates("prj", "app", null); | |||
assertThat(underTestWithApplicationInstalled.resolve(db.getSession()).getProject()).contains("prj"); | |||
assertThat(underTestWithApplicationInstalled.resolve(db.getSession()).getApplication()).contains("app"); | |||
assertThat(underTestWithApplicationInstalled.resolve(db.getSession()).getPortfolio()).isEmpty(); | |||
} | |||
@Test | |||
public void fail_when_default_template_for_project_is_missing() { | |||
DbSession session = db.getSession(); |