Skip to content

Commit 7b58222

Browse files
committed
Check for dependency on AppEngineDriver (closes #207, wip #237)
1 parent 462c921 commit 7b58222

File tree

8 files changed

+257
-1
lines changed

8 files changed

+257
-1
lines changed

components/sbm-core/src/main/java/org/springframework/sbm/java/api/ProjectJavaSources.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,6 @@ public interface ProjectJavaSources {
5050
List<MethodCall> findMethodCalls(String pattern);
5151

5252
List<JavaSourceAndType> findTypesImplementing(String jpaRepositoryInterface);
53+
54+
List<? extends JavaSource> findClassesUsingType(String databaseDriverGAE);
5355
}

components/sbm-core/src/main/java/org/springframework/sbm/java/impl/ProjectJavaSourcesImpl.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@
1616
package org.springframework.sbm.java.impl;
1717

1818
import lombok.extern.slf4j.Slf4j;
19+
import org.apache.commons.lang3.exception.ExceptionContext;
20+
import org.openrewrite.ExecutionContext;
1921
import org.openrewrite.Recipe;
2022
import org.openrewrite.java.ChangeType;
2123
import org.openrewrite.java.MethodMatcher;
2224
import org.openrewrite.java.search.FindMethods;
25+
import org.openrewrite.java.search.UsesType;
2326
import org.openrewrite.java.tree.J;
2427
import org.openrewrite.java.tree.JavaType;
2528
import org.openrewrite.java.tree.TypeUtils;
@@ -28,10 +31,12 @@
2831
import org.springframework.sbm.java.refactoring.JavaGlobalRefactoring;
2932
import org.springframework.sbm.project.resource.ProjectResourceSet;
3033
import org.springframework.sbm.project.resource.RewriteSourceFileHolder;
34+
import org.springframework.sbm.support.openrewrite.GenericOpenRewriteRecipe;
3135

3236
import java.util.ArrayList;
3337
import java.util.List;
3438
import java.util.Optional;
39+
import java.util.stream.Collectors;
3540
import java.util.stream.Stream;
3641

3742
@Slf4j
@@ -119,6 +124,18 @@ public List<JavaSourceAndType> findTypesImplementing(String type) {
119124
return matches;
120125
}
121126

127+
@Override
128+
public List<? extends JavaSource> findClassesUsingType(String fqName) {
129+
UsesType<ExecutionContext> usesType = new UsesType<>(fqName);
130+
GenericOpenRewriteRecipe<UsesType<ExecutionContext>> recipe = new GenericOpenRewriteRecipe<>(() -> usesType);
131+
return find(recipe).stream()
132+
.filter(RewriteSourceFileHolder.class::isInstance)
133+
.map(RewriteSourceFileHolder.class::cast)
134+
.filter(r -> r.getType().isAssignableFrom(J.CompilationUnit.class))
135+
.map(r -> (OpenRewriteJavaSource)r)
136+
.collect(Collectors.toList());
137+
}
138+
122139
private boolean hasTypeImplementing(J.ClassDeclaration c, String type) {
123140
try {
124141
return c.getImplements() != null &&
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.sbm.boot.upgrade_27_30;
18+
19+
import org.springframework.sbm.engine.context.ProjectContext;
20+
21+
public interface Sbu30_PreconditionCheck {
22+
Sbu30_PreconditionCheckResult run(ProjectContext context);
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.sbm.boot.upgrade_27_30;
18+
19+
import lombok.Getter;
20+
import lombok.RequiredArgsConstructor;
21+
import org.springframework.sbm.engine.precondition.PreconditionCheck;
22+
23+
@Getter
24+
@RequiredArgsConstructor
25+
public class Sbu30_PreconditionCheckResult {
26+
private final PreconditionCheck.ResultState state;
27+
private final String message;
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.sbm.boot.upgrade_27_30;
18+
19+
import com.fasterxml.jackson.annotation.JsonIgnore;
20+
import org.springframework.beans.factory.annotation.Autowired;
21+
import org.springframework.sbm.engine.context.ProjectContext;
22+
import org.springframework.sbm.engine.precondition.PreconditionCheck;
23+
import org.springframework.sbm.engine.recipe.AbstractAction;
24+
25+
import java.util.ArrayList;
26+
import java.util.List;
27+
import java.util.stream.Collectors;
28+
29+
public class Sbu30_PreconditionChecks extends AbstractAction {
30+
31+
@Autowired
32+
@JsonIgnore
33+
private List<Sbu30_PreconditionCheck> checks = new ArrayList<>();
34+
35+
@Override
36+
public void apply(ProjectContext context) {
37+
List<Sbu30_PreconditionCheckResult> results = checks.stream()
38+
.map(sbu30_preconditionCheck -> sbu30_preconditionCheck.run(context))
39+
.collect(Collectors.toList());
40+
41+
results.forEach(this::render);
42+
43+
if(results.stream().anyMatch(c -> c.getState().equals(PreconditionCheck.ResultState.FAILED))) {
44+
// TODO: ask user to proceed, fail/end otherwise
45+
}
46+
47+
}
48+
49+
private void render(Sbu30_PreconditionCheckResult result) {
50+
System.out.println(result.getMessage());
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.sbm.boot.upgrade_27_30.checks;
18+
19+
import org.openrewrite.java.tree.JavaType;
20+
import org.springframework.sbm.boot.upgrade_27_30.Sbu30_PreconditionCheck;
21+
import org.springframework.sbm.boot.upgrade_27_30.Sbu30_PreconditionCheckResult;
22+
import org.springframework.sbm.build.api.ApplicationModule;
23+
import org.springframework.sbm.engine.context.ProjectContext;
24+
import org.springframework.sbm.engine.precondition.PreconditionCheck;
25+
import org.springframework.sbm.java.api.JavaSource;
26+
import org.springframework.sbm.java.impl.OpenRewriteJavaSource;
27+
import org.springframework.stereotype.Component;
28+
29+
import java.util.List;
30+
import java.util.Set;
31+
import java.util.stream.Collectors;
32+
import java.util.stream.Stream;
33+
34+
@Component
35+
public class DatabaseDriverGaeCheck implements Sbu30_PreconditionCheck {
36+
37+
@Override
38+
public Sbu30_PreconditionCheckResult run(ProjectContext context) {
39+
40+
Set<ApplicationModule> collect = context.getApplicationModules()
41+
.stream()
42+
.filter(this::hasClassAppEngineDriverOnClasspath)
43+
.collect(Collectors.toSet());
44+
45+
if(collect.isEmpty()) {
46+
return new Sbu30_PreconditionCheckResult(PreconditionCheck.ResultState.PASSED, "No dependency to Google AppEngine's AppEngineDriver found.");
47+
} else {
48+
String message = "Dependencies containing 'com.google.appengine.api.rdbms.AppEngineDriver' were found in these modules: '" + collect.stream().map(m -> m.getBuildFile().getCoordinates()).collect(Collectors.joining("', '")) + "'";
49+
return new Sbu30_PreconditionCheckResult(PreconditionCheck.ResultState.FAILED, message);
50+
}
51+
}
52+
53+
private boolean hasClassAppEngineDriverOnClasspath(ApplicationModule m) {
54+
return Stream.concat(m.getTestJavaSourceSet().stream(), m.getMainJavaSourceSet().stream())
55+
.anyMatch(js -> {
56+
if (dependsOn(js, "com.google.appengine.api.rdbms.AppEngineDriver")) {
57+
return true;
58+
} else {
59+
return false;
60+
}
61+
});
62+
}
63+
64+
private boolean dependsOn(JavaSource js, String s) {
65+
if (OpenRewriteJavaSource.class.isInstance(js)) {
66+
OpenRewriteJavaSource javaSource = OpenRewriteJavaSource.class.cast(js);
67+
return javaSource.getSourceFile().getMarkers().findFirst(org.openrewrite.java.marker.JavaSourceSet.class).get()
68+
.getClasspath()
69+
.stream()
70+
.map(JavaType.FullyQualified::getFullyQualifiedName)
71+
.anyMatch(fq -> s.equals(fq));
72+
}
73+
return false;
74+
}
75+
}

components/sbm-recipes-boot-upgrade/src/main/resources/recipes/boot-2.7-3.0-dependency-version-update.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@
22
description: Bump spring-boot-starter-parent from 2.7.x to 3.0.0-M3
33
condition:
44
type: org.springframework.sbm.boot.common.conditions.HasSpringBootStarterParent
5+
# TODO: pattern should also allow 3.0.* as it can't be re-run otherwise agfter bumping the version to 3.0.0
56
versionPattern: "2\\.7\\..*"
67

78
actions:
9+
- type: org.springframework.sbm.boot.upgrade_27_30.Sbu30_PreconditionChecks
10+
description: "Check if the application adheres to preconditions."
11+
condition:
12+
type: org.springframework.sbm.common.migration.conditions.TrueCondition
813

914
# TODO: upgrades for 2.7
1015
- type: org.springframework.sbm.build.migration.actions.AddRepositoryAction
@@ -22,12 +27,13 @@
2227
type: org.springframework.sbm.boot.upgrade.common.conditions.HasSpringBootParentOfVersion
2328
versionStartingWith: "2.7."
2429
description: Add Spring Milestone Repository and bump parent pom to 3.0.0-M3
30+
# TODO: remove TEST in name
2531
openRewriteRecipe: |-
2632
type: specs.openrewrite.org/v1beta/recipe
2733
name: org.openrewrite.java.spring.boot3.data.TEST
2834
displayName: Upgrade to Spring Data 3.0
2935
description: 'Upgrade to Spring Data to 3.0 from any prior version.'
30-
recipeList:
36+
recipeList:
3137
- org.openrewrite.maven.UpgradeParentVersion:
3238
groupId: org.springframework.boot
3339
artifactId: spring-boot-starter-parent
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.sbm.boot.upgrade_27_30.checks;
18+
19+
import org.junit.jupiter.api.Test;
20+
import org.springframework.sbm.boot.upgrade_27_30.Sbu30_PreconditionCheckResult;
21+
import org.springframework.sbm.engine.context.ProjectContext;
22+
import org.springframework.sbm.engine.precondition.PreconditionCheck;
23+
import org.springframework.sbm.project.resource.TestProjectContext;
24+
25+
import static org.assertj.core.api.Assertions.assertThat;
26+
27+
class DatabaseDriverGaeCheckTest {
28+
29+
@Test
30+
void checkShouldFailWhenAppEngineDriverIsFoundOnClasspath() {
31+
32+
String javaClass =
33+
"import org.springframework.boot.jdbc.DatabaseDriver;\n" +
34+
"\n" +
35+
"public class Foo {\n" +
36+
" public Foo() {\n" +
37+
" DatabaseDriver driver = DatabaseDriver.GAE;\n" +
38+
" com.google.appengine.api.rdbms.AppEngineDriver d;" +
39+
" }\n" +
40+
"}";
41+
42+
ProjectContext context = TestProjectContext.buildProjectContext()
43+
.withBuildFileHavingDependencies("org.springframework.boot:spring-boot:2.7.1", "com.google.appengine:appengine-api-1.0-sdk:1.9.17")
44+
.addJavaSource("src/main/java", javaClass)
45+
.build();
46+
47+
Sbu30_PreconditionCheckResult result = new DatabaseDriverGaeCheck().run(context);
48+
49+
assertThat(result.getState()).isEqualTo(PreconditionCheck.ResultState.FAILED);
50+
assertThat(result.getMessage()).isEqualTo("Dependencies containing 'com.google.appengine.api.rdbms.AppEngineDriver' were found in these modules: 'com.example:dummy-root:0.1.0-SNAPSHOT'");
51+
52+
}
53+
}

0 commit comments

Comments
 (0)