Skip to content

Commit 927b01d

Browse files
Remove finalizer from classes in util.zip (#233)
* recipe for removing finalizer from ZipFile, Deflater and Inflater * adding license header to recipe * Format textblocks and resolve ZipFile compilation issues * Format RemoveFinalizerFromZip * Add tests to show or prevent implementation issues * added preconditions and refactored the logic * fixing finalize removal recipe to handle edge cases * Apply formatter * Only override visitMethodInvocation Support case of empty select by looking at surrounding class declaration Use method matcher instead of String comparison to find finalize calls Use TypeUtils instead of String comparison to find extending classes * Also removeCallsToSelfFinalize * Limit to Java 12+ --------- Co-authored-by: Tim te Beek <[email protected]>
1 parent 4241d47 commit 927b01d

File tree

2 files changed

+373
-0
lines changed

2 files changed

+373
-0
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 2023 the original author or authors.
3+
* <p>
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+
* <p>
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
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.openrewrite.java.migrate.util;
18+
19+
import lombok.EqualsAndHashCode;
20+
import lombok.Value;
21+
import org.openrewrite.ExecutionContext;
22+
import org.openrewrite.Preconditions;
23+
import org.openrewrite.Recipe;
24+
import org.openrewrite.TreeVisitor;
25+
import org.openrewrite.java.JavaVisitor;
26+
import org.openrewrite.java.MethodMatcher;
27+
import org.openrewrite.java.search.UsesJavaVersion;
28+
import org.openrewrite.java.search.UsesType;
29+
import org.openrewrite.java.tree.Expression;
30+
import org.openrewrite.java.tree.J;
31+
import org.openrewrite.java.tree.JavaType;
32+
import org.openrewrite.java.tree.TypeUtils;
33+
34+
import java.util.List;
35+
36+
@Value
37+
@EqualsAndHashCode(callSuper = true)
38+
public class RemoveFinalizerFromZip extends Recipe {
39+
40+
private static final String JAVA_UTIL_ZIP_DEFLATER = "java.util.zip.Deflater";
41+
private static final String JAVA_UTIL_ZIP_INFLATER = "java.util.zip.Inflater";
42+
private static final String JAVA_UTIL_ZIP_ZIP_FILE = "java.util.zip.ZipFile";
43+
44+
private static final MethodMatcher METHOD_MATCHER = new MethodMatcher("java.lang.Object finalize()");
45+
46+
@Override
47+
public String getDisplayName() {
48+
return "Remove invocations of deprecated invocations from Deflater, Inflater, ZipFile ";
49+
}
50+
51+
@Override
52+
public String getDescription() {
53+
return "Remove invocations of finalize() deprecated invocations from Deflater, Inflater, ZipFile.";
54+
}
55+
56+
@Override
57+
public TreeVisitor<?, ExecutionContext> getVisitor() {
58+
return Preconditions.check(Preconditions.and(
59+
new UsesJavaVersion<>(12),
60+
Preconditions.or(
61+
new UsesType<>(JAVA_UTIL_ZIP_DEFLATER, false),
62+
new UsesType<>(JAVA_UTIL_ZIP_INFLATER, false),
63+
new UsesType<>(JAVA_UTIL_ZIP_ZIP_FILE, false))),
64+
new JavaVisitor<ExecutionContext>() {
65+
@Override
66+
public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext executionContext) {
67+
J.MethodInvocation mi = (J.MethodInvocation) super.visitMethodInvocation(method, executionContext);
68+
69+
if (METHOD_MATCHER.matches(mi)) {
70+
Expression select = mi.getSelect();
71+
if (select == null) {
72+
J.ClassDeclaration cd = getCursor().firstEnclosingOrThrow(J.ClassDeclaration.class);
73+
if (shouldRemoveFinalize(cd.getType())) {
74+
return null;
75+
}
76+
} else {
77+
if (shouldRemoveFinalize(select.getType())) {
78+
// Retain any side effects preceding the finalize() call
79+
List<J> sideEffects = select.getSideEffects();
80+
if (sideEffects.isEmpty()) {
81+
return null;
82+
}
83+
if (sideEffects.size() == 1) {
84+
return sideEffects.get(0).withPrefix(mi.getPrefix());
85+
}
86+
}
87+
}
88+
}
89+
90+
return mi;
91+
}
92+
93+
private boolean shouldRemoveFinalize(JavaType type) {
94+
return TypeUtils.isAssignableTo(JAVA_UTIL_ZIP_DEFLATER, type)
95+
|| TypeUtils.isAssignableTo(JAVA_UTIL_ZIP_INFLATER, type)
96+
|| TypeUtils.isAssignableTo(JAVA_UTIL_ZIP_ZIP_FILE, type);
97+
}
98+
});
99+
}
100+
101+
}
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
/*
2+
* Copyright 2023 the original author or authors.
3+
* <p>
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+
* <p>
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
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.openrewrite.java.migrate.util;
18+
19+
import org.junit.jupiter.api.Test;
20+
import org.openrewrite.DocumentExample;
21+
import org.openrewrite.test.RecipeSpec;
22+
import org.openrewrite.test.RewriteTest;
23+
24+
import static org.openrewrite.java.Assertions.*;
25+
26+
class RemoveFinalizerFromZipTest implements RewriteTest {
27+
28+
@Override
29+
public void defaults(RecipeSpec spec) {
30+
spec.recipe(new RemoveFinalizerFromZip()).allSources(s -> s.markers(javaVersion(12)));
31+
}
32+
33+
@Test
34+
@DocumentExample
35+
void removeFinalizerForInflater() {
36+
//language=java
37+
rewriteRun(java("""
38+
import java.util.zip.Inflater;
39+
40+
class FooInflater extends Inflater {
41+
public void test() {
42+
FooInflater obj = new FooInflater();
43+
obj.finalize();
44+
}
45+
}
46+
""", """
47+
import java.util.zip.Inflater;
48+
49+
class FooInflater extends Inflater {
50+
public void test() {
51+
FooInflater obj = new FooInflater();
52+
}
53+
}
54+
"""));
55+
}
56+
57+
@Test
58+
void removeCallsToSelfFinalize() {
59+
//language=java
60+
rewriteRun(java("""
61+
import java.util.zip.Inflater;
62+
63+
class FooBar extends Inflater {
64+
public void test() {
65+
finalize();
66+
}
67+
}
68+
""", """
69+
import java.util.zip.Inflater;
70+
71+
class FooBar extends Inflater {
72+
public void test() {
73+
}
74+
}
75+
"""));
76+
}
77+
78+
@Test
79+
void removeCallsToThisFinalize() {
80+
//language=java
81+
rewriteRun(java("""
82+
import java.util.zip.Inflater;
83+
84+
class FooBar extends Inflater {
85+
public void test() {
86+
this.finalize();
87+
}
88+
}
89+
""", """
90+
import java.util.zip.Inflater;
91+
92+
class FooBar extends Inflater {
93+
public void test() {
94+
}
95+
}
96+
"""));
97+
}
98+
99+
@Test
100+
void removeWhileKeepingSideEffects() {
101+
//language=java
102+
rewriteRun(java("""
103+
import java.util.zip.Inflater;
104+
105+
class FooBar extends Inflater {
106+
public void test() {
107+
new FooBar().finalize();
108+
}
109+
}
110+
""", """
111+
import java.util.zip.Inflater;
112+
113+
class FooBar extends Inflater {
114+
public void test() {
115+
new FooBar();
116+
}
117+
}
118+
"""));
119+
}
120+
121+
@Test
122+
void noChangeWithFinalizeOnObject() {
123+
//language=java
124+
rewriteRun(java("""
125+
import java.util.zip.Inflater;
126+
127+
class FooBar extends Inflater {
128+
public void test() {
129+
new Object().finalize();
130+
}
131+
}
132+
"""));
133+
}
134+
135+
@Test
136+
void noChangeWithoutFinalizerForInflater() {
137+
//language=java
138+
rewriteRun(java("""
139+
import java.util.zip.Inflater;
140+
141+
class FooBar extends Inflater {
142+
public void test() {
143+
FooBar obj = new FooBar();
144+
}
145+
}
146+
"""));
147+
}
148+
149+
@Test
150+
void removeFinalizerForDeflater() {
151+
//language=java
152+
rewriteRun(java("""
153+
import java.util.zip.Deflater;
154+
155+
class FooBar extends Deflater {
156+
public void test() {
157+
FooBar obj = new FooBar();
158+
obj.finalize();
159+
}
160+
}
161+
""", """
162+
import java.util.zip.Deflater;
163+
164+
class FooBar extends Deflater {
165+
public void test() {
166+
FooBar obj = new FooBar();
167+
}
168+
}
169+
"""));
170+
}
171+
172+
@Test
173+
void noChangeWithoutFinalizerForDeflater() {
174+
//language=java
175+
rewriteRun(java("""
176+
import java.util.zip.Deflater;
177+
178+
class FooBar extends Deflater {
179+
public void test() {
180+
FooBar obj = new FooBar();
181+
}
182+
}
183+
"""));
184+
}
185+
186+
@Test
187+
void removeFinalizerForZipFile() {
188+
//language=java
189+
rewriteRun(java("""
190+
import java.util.zip.ZipFile;
191+
192+
class FooBar extends ZipFile {
193+
FooBar(){
194+
super("");
195+
}
196+
public void test() {
197+
FooBar obj = new FooBar();
198+
obj.finalize();
199+
}
200+
}
201+
""", """
202+
import java.util.zip.ZipFile;
203+
204+
class FooBar extends ZipFile {
205+
FooBar(){
206+
super("");
207+
}
208+
public void test() {
209+
FooBar obj = new FooBar();
210+
}
211+
}
212+
"""));
213+
}
214+
215+
@Test
216+
void noChangeWithoutFinalizerForZipFile() {
217+
//language=java
218+
rewriteRun(java("""
219+
import java.util.zip.ZipFile;
220+
221+
class FooBar extends ZipFile {
222+
FooBar(){
223+
super("");
224+
}
225+
public void test() {
226+
FooBar obj = new FooBar();
227+
}
228+
}
229+
"""));
230+
}
231+
232+
@Test
233+
void noChangeWithoutExtends() {
234+
//language=java
235+
rewriteRun(java("""
236+
class FooBar {
237+
public void test() {
238+
new Object().finalize();
239+
}
240+
}
241+
"""));
242+
}
243+
244+
@Test
245+
void noChangeWithoutExtendsOrSelect() {
246+
//language=java
247+
rewriteRun(java("""
248+
class FooBar {
249+
public void test() {
250+
finalize();
251+
}
252+
}
253+
"""));
254+
}
255+
256+
@Test
257+
void noChangeOnJava11() {
258+
//language=java
259+
rewriteRun(version(java("""
260+
import java.util.zip.ZipFile;
261+
262+
class FooBar extends ZipFile {
263+
FooBar(){
264+
super("");
265+
}
266+
public void test() {
267+
finalize();
268+
}
269+
}
270+
"""), 11));
271+
}
272+
}

0 commit comments

Comments
 (0)