Skip to content

Commit

Permalink
Add ability to exclude ProjectGenerationConfiguration
Browse files Browse the repository at this point in the history
  • Loading branch information
zambrovski authored and mhalbritter committed Nov 19, 2024
1 parent 0db7ed4 commit 2b83654
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.spring.initializr.generator.project;

/**
* Allows to filter {@link ProjectGenerationConfiguration}.
*
* @author Simon Zambrovski
*/
public interface ProjectGenerationConfigurationTypeFilter {

/**
* Determines if the provided class matches the filter.
* @param type type to match.
* @return true, if the type matches.
*/
boolean match(Class<?> type);

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.util.ClassUtils;

/**
* Main entry point for project generation that processes a {@link ProjectDescription} by
Expand Down Expand Up @@ -116,17 +117,51 @@ public <T> T generate(ProjectDescription description, ProjectAssetGenerator<T> p

/**
* Return the {@link ProjectGenerationConfiguration} class names that should be
* considered. By default this method will load candidates using
* {@link SpringFactoriesLoader} with {@link ProjectGenerationConfiguration}.
* considered. By default, this method will load candidates using
* {@link SpringFactoriesLoader} with {@link ProjectGenerationConfiguration} and
* exclude those which are matched by the
* {@link ProjectGenerationConfigurationTypeFilter}
* @param description the description of the project to generate
* @return a list of candidate configurations
*/
@SuppressWarnings("deprecation")

protected List<String> getCandidateProjectGenerationConfigurations(ProjectDescription description) {
List<String> candidates = getProjectGenerationConfigurationFactoryNames();
ProjectGenerationConfigurationTypeFilter filter = getProjectGenerationConfigurationExclusionFilter();
return candidates.stream().filter((candidate) -> {
Class<?> type = this.resolveClass(candidate);
return type != null && !filter.match(type);
}).toList();
}

private Class<?> resolveClass(String candidate) {
try {
return ClassUtils.forName(candidate, getClass().getClassLoader());
}
catch (ClassNotFoundException ex) {
return null;
}
}

@SuppressWarnings("deprecation")
List<String> getProjectGenerationConfigurationFactoryNames() {
return SpringFactoriesLoader.loadFactoryNames(ProjectGenerationConfiguration.class,
getClass().getClassLoader());
}

ProjectGenerationConfigurationTypeFilter getProjectGenerationConfigurationExclusionFilter() {
List<ProjectGenerationConfigurationTypeFilter> filters = SpringFactoriesLoader
.loadFactories(ProjectGenerationConfigurationTypeFilter.class, getClass().getClassLoader());
// Build a composite filter, combining results with a logical OR
return (configurationClass) -> {
boolean excluded = false;
for (ProjectGenerationConfigurationTypeFilter filter : filters) {
excluded = excluded || filter.match(configurationClass);
}
return excluded;
};
}

private void registerProjectDescription(ProjectGenerationContext context, ProjectDescription description) {
context.registerBean(ProjectDescription.class, resolve(description, context));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

import io.spring.initializr.generator.buildsystem.maven.MavenBuildSystem;
import io.spring.initializr.generator.project.contributor.TestProjectGenerationConfiguration;
import io.spring.initializr.generator.project.contributor.TestProjectGenerationConfiguration2;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.mockito.InOrder;
Expand Down Expand Up @@ -181,8 +183,9 @@ void generateCanBeExtendedToFilterProjectContributors(@TempDir Path projectDir)
given(description.getBuildSystem()).willReturn(new MavenBuildSystem());
ProjectGenerator generator = new ProjectGenerator(mockContextInitializr()) {
@Override
protected List<String> getCandidateProjectGenerationConfigurations(ProjectDescription description) {
assertThat(description).isSameAs(description);
protected List<String> getCandidateProjectGenerationConfigurations(
ProjectDescription generatorDescription) {
assertThat(description).isSameAs(generatorDescription);
return Collections.singletonList(TestProjectGenerationConfiguration.class.getName());
}
};
Expand All @@ -195,6 +198,37 @@ protected List<String> getCandidateProjectGenerationConfigurations(ProjectDescri
verify(description).getBuildSystem();
}

@Test
void loadAndConstructProjectGenerationTypeExclusionFilter() {
ProjectGenerator generator = new ProjectGenerator(mockContextInitializr());
ProjectGenerationConfigurationTypeFilter filter = generator.getProjectGenerationConfigurationExclusionFilter();
assertThat(filter).isNotNull();
assertThat(filter.match(TestProjectGenerationConfiguration.class)).isTrue();
assertThat(filter.match(TestProjectGenerationConfiguration2.class)).isTrue();
assertThat(filter.match(Integer.class)).isFalse();
}

@Test
void filterProjectContributorsCorrectly(@TempDir Path projectDir) {
ProjectDescription description = mock(ProjectDescription.class);
given(description.getArtifactId()).willReturn("test-custom-contributor");
given(description.getBuildSystem()).willReturn(new MavenBuildSystem());
ProjectGenerator generator = new ProjectGenerator(mockContextInitializr()) {
@Override
List<String> getProjectGenerationConfigurationFactoryNames() {
return Lists.list(TestProjectGenerationConfiguration.class.getName(),
TestProjectGenerationConfiguration2.class.getName());
}

@Override
ProjectGenerationConfigurationTypeFilter getProjectGenerationConfigurationExclusionFilter() {
return TestProjectGenerationConfiguration2.class::equals;
}
};
List<String> candidates = generator.getCandidateProjectGenerationConfigurations(description);
assertThat(candidates).containsOnly(TestProjectGenerationConfiguration.class.getCanonicalName());
}

@SuppressWarnings("unchecked")
private Consumer<ProjectGenerationContext> mockContextInitializr() {
return mock(Consumer.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.spring.initializr.generator.project.contributor;

import io.spring.initializr.generator.project.ProjectGenerationConfiguration;

/**
* Test contributor.
*/
@ProjectGenerationConfiguration
public class TestProjectGenerationConfiguration2 {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.spring.initializr.generator.project.contributor;

import io.spring.initializr.generator.project.ProjectGenerationConfigurationTypeFilter;

public class TestProjectGenerationConfiguration2ExcludingTypeFilter
implements ProjectGenerationConfigurationTypeFilter {

@Override
public boolean match(Class<?> type) {
return TestProjectGenerationConfiguration2.class.equals(type);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.spring.initializr.generator.project.contributor;

import io.spring.initializr.generator.project.ProjectGenerationConfigurationTypeFilter;

public class TestProjectGenerationConfigurationExcludingTypeFilter implements ProjectGenerationConfigurationTypeFilter {

@Override
public boolean match(Class<?> type) {
return TestProjectGenerationConfiguration.class.equals(type);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
io.spring.initializr.generator.project.ProjectGenerationConfigurationTypeFilter=\
io.spring.initializr.generator.project.contributor.TestProjectGenerationConfigurationExcludingTypeFilter,\
io.spring.initializr.generator.project.contributor.TestProjectGenerationConfiguration2ExcludingTypeFilter

0 comments on commit 2b83654

Please sign in to comment.