diff --git a/.gitignore b/.gitignore index c32ce724..bb52179c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ bin/ .project .classpath .settings/ +.DS_Store +.moderne/ diff --git a/src/main/java/org/openrewrite/java/apache/httpclient5/UseTimeValue.java b/src/main/java/org/openrewrite/java/apache/httpclient5/UseTimeValue.java new file mode 100644 index 00000000..1458f06d --- /dev/null +++ b/src/main/java/org/openrewrite/java/apache/httpclient5/UseTimeValue.java @@ -0,0 +1,80 @@ +/* + * Copyright 2023 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 org.openrewrite.java.apache.httpclient5; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.Preconditions; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.JavaParser; +import org.openrewrite.java.JavaTemplate; +import org.openrewrite.java.MethodMatcher; +import org.openrewrite.java.search.UsesType; +import org.openrewrite.java.tree.J; + +import java.util.Arrays; +import java.util.List; + +public class UseTimeValue extends Recipe { + @Override + public String getDisplayName() { + return "Use `TimeValue` class to define time values (duration)"; + } + + @Override + public String getDescription() { + return "Use `TimeValue` class to define time values (duration)."; + } + + @Override + public TreeVisitor getVisitor() { + return Preconditions.check(new UsesType<>("org.apache.hc..*", true), new JavaIsoVisitor() { + + List methodMatchers = Arrays.asList( + new MethodMatcher("org.apache.hc.core5.http.io.SocketConfig.Builder setSoLinger(int)") + ); + + JavaTemplate template = JavaTemplate.builder("TimeValue.ofMilliseconds(#{})") + .contextSensitive() + .javaParser(JavaParser.fromJavaVersion().classpath( + "httpclient5", "httpcore5" + )) + .imports("org.apache.hc.core5.util.TimeValue") + .build(); + + @Override + public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { + J.MethodInvocation m = super.visitMethodInvocation(method, ctx); + + if (methodMatches(m)) { + m = template.apply(updateCursor(m), m.getCoordinates().replaceArguments(), m.getArguments().get(0)); + maybeAddImport("org.apache.hc.core5.util.TimeValue"); + } + return m; + } + + private boolean methodMatches(J.MethodInvocation method) { + for (MethodMatcher matcher : methodMatchers) { + if (matcher.matches(method)) { + return true; + } + } + return false; + } + }); + } +} diff --git a/src/main/java/org/openrewrite/java/apache/httpclient5/UseTimeout.java b/src/main/java/org/openrewrite/java/apache/httpclient5/UseTimeout.java new file mode 100644 index 00000000..de17e1c5 --- /dev/null +++ b/src/main/java/org/openrewrite/java/apache/httpclient5/UseTimeout.java @@ -0,0 +1,84 @@ +/* + * Copyright 2023 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 org.openrewrite.java.apache.httpclient5; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.Preconditions; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.JavaParser; +import org.openrewrite.java.JavaTemplate; +import org.openrewrite.java.MethodMatcher; +import org.openrewrite.java.search.UsesType; +import org.openrewrite.java.tree.J; + +import java.util.Arrays; +import java.util.List; + + +public class UseTimeout extends Recipe { + @Override + public String getDisplayName() { + return "Use `Timeout` class to define timeouts"; + } + + @Override + public String getDescription() { + return "Use Timeout class to define timeouts."; + } + + @Override + public TreeVisitor getVisitor() { + return Preconditions.check(new UsesType<>("org.apache.hc..*", true), new JavaIsoVisitor() { + + final List methodMatchers = Arrays.asList( + new MethodMatcher("org.apache.hc.client5.http.config.RequestConfig.Builder setConnectionRequestTimeout(int)"), + new MethodMatcher("org.apache.hc.client5.http.config.RequestConfig.Builder setConnectTimeout(int)"), + new MethodMatcher("org.apache.hc.client5.http.config.RequestConfig.Builder setResponseTimeout(int)"), + new MethodMatcher("org.apache.hc.core5.http.io.SocketConfig.Builder setSoTimeout(int)") + ); + + final JavaTemplate template = JavaTemplate.builder("Timeout.ofMilliseconds(#{})") + .contextSensitive() + .javaParser(JavaParser.fromJavaVersion().classpath( + "httpclient5", "httpcore5" + )) + .imports("org.apache.hc.core5.util.Timeout") + .build(); + + @Override + public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { + J.MethodInvocation m = super.visitMethodInvocation(method, ctx); + + if (methodMatches(m)) { + m = template.apply(updateCursor(m), m.getCoordinates().replaceArguments(), m.getArguments().get(0)); + maybeAddImport("org.apache.hc.core5.util.Timeout"); + } + return m; + } + + private boolean methodMatches(J.MethodInvocation method) { + for (MethodMatcher matcher : methodMatchers) { + if (matcher.matches(method)) { + return true; + } + } + return false; + } + }); + } +} diff --git a/src/main/java/org/openrewrite/java/apache/httpclient5/package-info.java b/src/main/java/org/openrewrite/java/apache/httpclient5/package-info.java new file mode 100644 index 00000000..7c64be3d --- /dev/null +++ b/src/main/java/org/openrewrite/java/apache/httpclient5/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2023 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. + */ +@NonNullApi @NonNullFields +package org.openrewrite.java.apache.httpclient5; + +import org.openrewrite.internal.lang.NonNullApi; +import org.openrewrite.internal.lang.NonNullFields; diff --git a/src/main/resources/META-INF/rewrite/apache-httpclient-5.yml b/src/main/resources/META-INF/rewrite/apache-httpclient-5.yml index 177cee8b..cd005b95 100644 --- a/src/main/resources/META-INF/rewrite/apache-httpclient-5.yml +++ b/src/main/resources/META-INF/rewrite/apache-httpclient-5.yml @@ -36,6 +36,10 @@ recipeList: newVersion: 5.1.x overrideManagedVersion: true - org.openrewrite.java.apache.httpclient5.UpgradeApacheHttpClient_5_ClassMapping + - org.openrewrite.java.apache.httpclient5.UpgradeApacheHttpClient_5_DeprecatedMethods + - org.openrewrite.java.apache.httpclient5.UseTimeout + - org.openrewrite.java.apache.httpclient5.UseTimeValue + --- type: specs.openrewrite.org/v1beta/recipe name: org.openrewrite.java.apache.httpclient5.UpgradeApacheHttpClient_5_ClassMapping @@ -251,8 +255,11 @@ recipeList: oldPackageName: org.apache.http.config newPackageName: org.apache.hc.core5.http.config - org.openrewrite.java.ChangeType: - oldFullyQualifiedTypeName: org.apache.http.config.SocketConfig + oldFullyQualifiedTypeName: org.apache.hc.core5.http.config.SocketConfig newFullyQualifiedTypeName: org.apache.hc.core5.http.io.SocketConfig + - org.openrewrite.java.ChangeType: + oldFullyQualifiedTypeName: org.apache.hc.core5.http.config.SocketConfig.Builder + newFullyQualifiedTypeName: org.apache.hc.core5.http.io.SocketConfig.Builder - org.openrewrite.java.ChangePackage: oldPackageName: org.apache.http.impl @@ -396,3 +403,12 @@ recipeList: - org.openrewrite.java.ChangeType: oldFullyQualifiedTypeName: org.apache.hc.core5.http.HttpConnectionFactory newFullyQualifiedTypeName: org.apache.hc.core5.http.io.HttpConnectionFactory +--- +type: specs.openrewrite.org/v1beta/recipe +name: org.openrewrite.java.apache.httpclient5.UpgradeApacheHttpClient_5_DeprecatedMethods +displayName: Migrate to ApacheHttpClient 5.x deprecated methods from 4.x +description: Migrates deprecated methods to their equivalent ones in 5.x +recipeList: + - org.openrewrite.java.ChangeMethodName: + methodPattern: org.apache.hc.client5.http.config.RequestConfig.Builder setSocketTimeout(int) + newMethodName: setResponseTimeout diff --git a/src/main/resources/META-INF/rewrite/classpath/httpclient5-5.1.4.jar b/src/main/resources/META-INF/rewrite/classpath/httpclient5-5.1.4.jar new file mode 100644 index 00000000..4700b86f Binary files /dev/null and b/src/main/resources/META-INF/rewrite/classpath/httpclient5-5.1.4.jar differ diff --git a/src/main/resources/META-INF/rewrite/classpath/httpcore5-5.1.5.jar b/src/main/resources/META-INF/rewrite/classpath/httpcore5-5.1.5.jar new file mode 100644 index 00000000..6035de6d Binary files /dev/null and b/src/main/resources/META-INF/rewrite/classpath/httpcore5-5.1.5.jar differ diff --git a/src/test/java/org/openrewrite/java/apache/httpclient5/UpgradeApacheHttpClient5Test.java b/src/test/java/org/openrewrite/java/apache/httpclient5/UpgradeApacheHttpClient5Test.java index d41c4e60..9cdc3520 100644 --- a/src/test/java/org/openrewrite/java/apache/httpclient5/UpgradeApacheHttpClient5Test.java +++ b/src/test/java/org/openrewrite/java/apache/httpclient5/UpgradeApacheHttpClient5Test.java @@ -113,4 +113,70 @@ void method(HttpEntity entity, String urlStr) throws Exception { """) ); } + + @Test + void useTimeoutClass() { + rewriteRun( + //language=java + java(""" + import org.apache.http.client.config.RequestConfig; + import org.apache.http.config.SocketConfig; + + class A { + void method() { + RequestConfig.custom() + .setConnectionRequestTimeout(300) + .setConnectTimeout(500) + .setSocketTimeout(1500); + + SocketConfig.custom() + .setSoTimeout(1000); + } + } + """, """ + import org.apache.hc.client5.http.config.RequestConfig; + import org.apache.hc.core5.http.io.SocketConfig; + import org.apache.hc.core5.util.Timeout; + + class A { + void method() { + RequestConfig.custom() + .setConnectionRequestTimeout(Timeout.ofMilliseconds(300)) + .setConnectTimeout(Timeout.ofMilliseconds(500)) + .setResponseTimeout(Timeout.ofMilliseconds(1500)); + + SocketConfig.custom() + .setSoTimeout(Timeout.ofMilliseconds(1000)); + } + } + """) + ); + } + + @Test + void useTimeValueClass() { + rewriteRun( + //language=java + java(""" + import org.apache.http.config.SocketConfig; + + class A { + void method() { + SocketConfig.custom() + .setSoLinger(500); + } + } + """, """ + import org.apache.hc.core5.http.io.SocketConfig; + import org.apache.hc.core5.util.TimeValue; + + class A { + void method() { + SocketConfig.custom() + .setSoLinger(TimeValue.ofMilliseconds(500)); + } + } + """) + ); + } }