diff --git a/.gitignore b/.gitignore index 261a2e0..8d9638e 100644 --- a/.gitignore +++ b/.gitignore @@ -46,4 +46,6 @@ gradle-app.setting .classpath .idea/ -out/ \ No newline at end of file +out/ +bin/ +.vscode/ diff --git a/build.gradle.kts b/build.gradle.kts index 18e9ddd..202e55e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,7 +3,7 @@ plugins { } group = "org.openrewrite.recipe" -description = "Open Liberty Migration" +description = "Recipes to migrate to the IBM WebSphere Liberty. Automatically." val rewriteVersion = rewriteRecipe.rewriteVersion.get() dependencies { @@ -12,6 +12,7 @@ dependencies { implementation("org.openrewrite:rewrite-java") implementation("org.openrewrite.recipe:rewrite-java-dependencies") implementation("org.openrewrite.recipe:rewrite-migrate-java") + implementation("org.openrewrite.recipe:rewrite-static-analysis") testImplementation("org.openrewrite:rewrite-java-17") testImplementation("org.openrewrite:rewrite-test") diff --git a/src/main/java/org/openrewrite/java/liberty/ChangeMethodInvocation.java b/src/main/java/org/openrewrite/java/liberty/ChangeMethodInvocation.java new file mode 100644 index 0000000..4a8dea1 --- /dev/null +++ b/src/main/java/org/openrewrite/java/liberty/ChangeMethodInvocation.java @@ -0,0 +1,189 @@ +/* + * 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.liberty; + +import lombok.EqualsAndHashCode; +import lombok.Value; + +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.openrewrite.*; +import org.openrewrite.internal.lang.NonNull; +import org.openrewrite.internal.lang.Nullable; +import org.openrewrite.java.JavaTemplate; +import org.openrewrite.java.JavaVisitor; +import org.openrewrite.java.MethodMatcher; +import org.openrewrite.java.tree.*; +import org.openrewrite.java.tree.JavaType.FullyQualified; +import org.openrewrite.marker.Markers; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/* + Development in this class is not complete +*/ +@Value +@EqualsAndHashCode(callSuper = true) +public class ChangeMethodInvocation extends Recipe { + + @Option(displayName = "Method pattern", + description = "A method pattern that is used to find matching method invocations.", + example = "org.mockito.Matchers anyVararg()") + @NonNull + String methodPattern; + + @Option(displayName = "New method name", + description = "The method name that will replace the existing name.", + example = "org.mockito.Matchers any()") + @NonNull + String newMethodPattern; + + @Option(displayName = "Perform static methd call", + description = "When set to `true` the method invocation will be performed statically.", + example = "true", + required = false) + @Nullable + Boolean performStaticCall; + + @JsonCreator + public ChangeMethodInvocation(@NonNull @JsonProperty("methodPattern") String methodPattern, + @NonNull @JsonProperty("newMethodPattern") String newMethodPattern, @Nullable @JsonProperty("performStaticCall") Boolean performStaticCall) { + this.methodPattern = methodPattern; + this.newMethodPattern = newMethodPattern; + this.performStaticCall = performStaticCall; + } + + + @Override + public String getDisplayName() { + return "Change method invocation"; + } + + @Override + public String getDescription() { + return "Rename a method invocation."; + } + + @Override + public boolean causesAnotherCycle() { + return true; + } + + @Override + public TreeVisitor getVisitor() { + return new ChangeMethodInvocationVisitor(new MethodMatcher(methodPattern, false), newMethodPattern); + } + + private class ChangeMethodInvocationVisitor extends JavaVisitor { + private final MethodMatcher methodMatcher; + private MethodMatcher methodReplacmentMatcher; + private String oldMethodType; + + private String newMethodType; + private String newMethodOwnerName; + private String newMethodName; + private String newMethodsArgsStr; + + Pattern methodPatternMatcher = Pattern.compile("([^\\s]+)\\s+([a-zA-Z0-9]+)\\((.*)\\)"); + + private ChangeMethodInvocationVisitor(MethodMatcher methodMatcher, String newMethodPattern) { + this.methodMatcher = methodMatcher; + this.oldMethodType = methodMatcher.getTargetTypePattern().pattern().replace("[.$]", "."); + + if (newMethodPattern != null) { + Matcher m = methodPatternMatcher.matcher(newMethodPattern); + if (m.find()) { + this.newMethodType = m.group(1); + if (this.newMethodType != null) { + String[] parts = this.newMethodType.split("\\."); + this.newMethodOwnerName = parts[parts.length - 1]; + } + + this.newMethodName = m.group(2); + this.newMethodsArgsStr = m.group(3); + if (this.newMethodsArgsStr != null) { + StringBuilder newArgs = new StringBuilder(); + int argSize = newMethodsArgsStr.split(",").length; + for (int i = 1; i <= argSize; i++) { + newArgs.append("*"); + if (i < argSize) { + newArgs.append(","); + } + } + this.methodReplacmentMatcher = new MethodMatcher(newMethodPattern.replace(this.newMethodsArgsStr, newArgs), false); + } else { + this.newMethodsArgsStr = ""; + this.methodReplacmentMatcher = new MethodMatcher(newMethodPattern, false); + } + } + } + } + + @Override + public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { + J.MethodInvocation m = method; + + if (methodReplacmentMatcher != null && methodMatcher.matches(method) && !methodReplacmentMatcher.matches(method)) { + if (performStaticCall) { + String temp = newMethodType + "." + newMethodName + "(" + newMethodsArgsStr + ");"; + JavaTemplate addArgTemplate = JavaTemplate.builder(temp).build(); + J.MethodInvocation qualifiedInvocation = addArgTemplate.apply(getCursor(), m.getCoordinates().replace()); + + temp = newMethodOwnerName + "." + newMethodName + "(" + newMethodsArgsStr + ");"; + addArgTemplate = JavaTemplate.builder(temp).build(); + J.MethodInvocation simpleInvocation = addArgTemplate.apply(getCursor(), m.getCoordinates().replace()); + + m = simpleInvocation.withMethodType(qualifiedInvocation.getMethodType()); + m = m.withSelect(m.getSelect().withType(qualifiedInvocation.getSelect().getType())); + + maybeAddImport(m.getMethodType().getDeclaringType().getFullyQualifiedName(), false); + maybeRemoveImport(oldMethodType); + } else { + // This block of code is not complete + JavaType.Method type = m.getMethodType(); + if (type != null) { + type = type.withName(newMethodName); + FullyQualified declaringType = type.getDeclaringType(); + String previousMethodType = declaringType.getFullyQualifiedName(); + declaringType = declaringType.withFullyQualifiedName(newMethodType); + type = type.withDeclaringType(declaringType); + + //add new import and remove old if no longer used + maybeAddImport(newMethodType); + maybeRemoveImport(previousMethodType); + } + m = m.withName(m.getName().withSimpleName(newMethodName)) + .withMethodType(type); + + if (this.newMethodsArgsStr == null) { + // clear arguments + List methodArgs = Collections.singletonList(new J.Empty(Tree.randomId(), Space.EMPTY, Markers.EMPTY)); + m = m.withArguments(methodArgs); + } else { + // override arguments + JavaTemplate addArgTemplate = JavaTemplate.builder(newMethodsArgsStr).build(); + m = addArgTemplate.apply(getCursor(), m.getCoordinates().replaceArguments()); + } + } + } + return m; + } + } +} diff --git a/src/main/java/org/openrewrite/java/liberty/ChangeStringLiteral.java b/src/main/java/org/openrewrite/java/liberty/ChangeStringLiteral.java new file mode 100644 index 0000000..ab58585 --- /dev/null +++ b/src/main/java/org/openrewrite/java/liberty/ChangeStringLiteral.java @@ -0,0 +1,91 @@ +/* + * 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.liberty; + +import lombok.EqualsAndHashCode; +import lombok.Value; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.Option; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.internal.lang.NonNull; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.tree.*; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +@Value +@EqualsAndHashCode(callSuper = true) +public class ChangeStringLiteral extends Recipe { + + @Option(displayName = "Value pattern", + description = "A pattern that is used to find matching string literal.", + example = "java:(.*)") + @NonNull + String valuePattern; + + @Option(displayName = "New value template", + description = "The template that will replace the existing value.", + example = "org:$1") + @NonNull + String newValueTemplate; + + @JsonCreator + public ChangeStringLiteral(@NonNull @JsonProperty("valuePattern") String valuePattern, @NonNull @JsonProperty("newValueTemplate") String newValueTemplate) { + this.valuePattern = valuePattern; + this.newValueTemplate = newValueTemplate; + } + + + @Override + public String getDisplayName() { + return "Change string literal"; + } + + @Override + public String getDescription() { + return "Changes the value of a string literal."; + } + + @Override + public TreeVisitor getVisitor() { + return new ChangeStringLiteralVisitor<>(Pattern.compile(valuePattern), newValueTemplate); + } + + @Value + @EqualsAndHashCode(callSuper = true) + public class ChangeStringLiteralVisitor

extends JavaIsoVisitor

{ + Pattern valuePattern; + String newValueTemplate; + + @Override + public J.Literal visitLiteral(J.Literal literal, P p) { + String literalValue = literal.getValue().toString(); + Matcher m = valuePattern.matcher(literalValue); + if (m.find()) { + literalValue = m.replaceFirst(newValueTemplate); + literal = literal.withValue(literalValue).withValueSource(literalValue); + } + return literal; + } + } + +} \ No newline at end of file diff --git a/src/main/java/org/openrewrite/java/liberty/RemoveWas2LibertyNonPortableJndiLookup.java b/src/main/java/org/openrewrite/java/liberty/RemoveWas2LibertyNonPortableJndiLookup.java new file mode 100644 index 0000000..7d9270b --- /dev/null +++ b/src/main/java/org/openrewrite/java/liberty/RemoveWas2LibertyNonPortableJndiLookup.java @@ -0,0 +1,86 @@ +/* + * 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.liberty; + +import java.util.function.Supplier; + +import org.openrewrite.internal.lang.Nullable; +import org.openrewrite.ExecutionContext; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.java.JavaVisitor; +import org.openrewrite.java.MethodMatcher; +import org.openrewrite.java.tree.Expression; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.MethodCall; + +public class RemoveWas2LibertyNonPortableJndiLookup extends Recipe { + + @Override + public String getDisplayName() { + return "Removes invalid JNDI properties"; + } + + @Override + public String getDescription() { + return "Remove the use of invalid JNDI properties from Hashtable."; + } + + @Override + public TreeVisitor getVisitor() { + return new MethodInvocationVisitor(); + } + + private class MethodInvocationVisitor extends JavaVisitor { + MethodMatcher methodMatcher = new MethodMatcher("java.util.Hashtable put(java.lang.Object, java.lang.Object)", false); + + @SuppressWarnings("NullableProblems") + @Nullable + @Override + public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ec) { + return visitMethodCall(method); + } + + @Nullable + private M visitMethodCall(M methodCall) { + if (!methodMatcher.matches(methodCall)) { + return methodCall; + } + J.Block parentBlock = getCursor().firstEnclosing(J.Block.class); + //noinspection SuspiciousMethodCalls + if (parentBlock != null && !parentBlock.getStatements().contains(methodCall)) { + return methodCall; + } + // Remove the method invocation when the argumentMatcherPredicate is true for all arguments + Expression firstArg = methodCall.getArguments().get(0); + if (firstArg instanceof J.Literal) { + J.Literal literalExp = (J.Literal) firstArg; + Object value = literalExp.getValue(); + if (!value.equals("java.naming.factory.initial") && !value.equals("java.naming.provider.url")) { + return methodCall; + } + } else { + return methodCall; + } + + if (methodCall.getMethodType() != null) { + maybeRemoveImport(methodCall.getMethodType().getDeclaringType()); + } + return null; + } + } + +} diff --git a/src/main/java/org/openrewrite/xml/liberty/PersistenceXmlLocationRule.java b/src/main/java/org/openrewrite/xml/liberty/PersistenceXmlLocationRule.java new file mode 100644 index 0000000..c12e6a7 --- /dev/null +++ b/src/main/java/org/openrewrite/xml/liberty/PersistenceXmlLocationRule.java @@ -0,0 +1,129 @@ +/* + * 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.xml.liberty; + +import org.openrewrite.internal.lang.Nullable; +import org.openrewrite.java.marker.JavaProject; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.Recipe; +import org.openrewrite.SourceFile; +import org.openrewrite.Tree; +import org.openrewrite.TreeVisitor; + +import java.io.File; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +public class PersistenceXmlLocationRule extends Recipe { + + @Override + public String getDisplayName() { + return "Move persistence.xml file."; + } + + @Override + public String getDescription() { + return "This recipes moves persistence.xml files into the root META-INF directory in source folder."; + } + + public File getProjectDirectory(File sourceFile, String projectName) { + File parent = sourceFile.getParentFile(); + while (parent != null && !parent.getName().equals(projectName)) { + parent = parent.getParentFile(); + } + + return parent; + } + + public List getSrcDirectories(SourceFile sourceFile) { + List srcDirs = new ArrayList(); + Path sourcePath = sourceFile.getSourcePath(); + + String projectName = sourceFile.getMarkers() + .findFirst(JavaProject.class) + .map(JavaProject::getProjectName) + .orElse(""); + + File projectDirctory = getProjectDirectory(new File(sourcePath.toAbsolutePath().toString()), projectName); + if (projectDirctory != null) { + File[] subDirs = projectDirctory.listFiles(File::isDirectory); + if (subDirs != null) { + for (File subDir : subDirs) { + String dirName = subDir.getName().toLowerCase(); + if (dirName.endsWith("src") || dirName.equals("source")) { + srcDirs.add(subDir); + } + } + } + } + + return srcDirs; + } + + @Override + public TreeVisitor getVisitor() { + return new TreeVisitor() { + @Nullable + @Override + public Tree visit(@Nullable Tree tree, ExecutionContext executionContext) { + if (tree instanceof SourceFile) { + SourceFile sourceFile = ((SourceFile) tree); + + Path sourcePath = ((SourceFile) tree).getSourcePath(); + if (sourcePath.getFileName().toString().equals("persistence.xml")) { + String projectName = sourceFile.getMarkers() + .findFirst(JavaProject.class) + .map(JavaProject::getProjectName) + .orElse(""); + + List srcDirs = getSrcDirectories(sourceFile); + boolean isValidPath = false; + boolean correctFileExists = false; + Path correctPath = null; + if (!srcDirs.isEmpty()) { + for (File srcDir : srcDirs) { + correctPath = srcDir.toPath().resolve("META-INF").resolve("persistence.xml"); + if (sourcePath.toAbsolutePath().equals(correctPath.toAbsolutePath())) { + isValidPath = true; + break; + } + + if (correctPath.toFile().exists()) { + correctFileExists = true; + } + } + } else { + if (!sourcePath.toAbsolutePath().endsWith("src" + File.separator + "META-INF" + File.separator + "persistence.xml")) { + File projectFile = getProjectDirectory(new File(sourcePath.toAbsolutePath().toString()), projectName); + correctPath = projectFile.toPath().resolve("src").resolve("META-INF").resolve("persistence.xml"); + return ((SourceFile) tree).withSourcePath(correctPath); + } + } + + if (!isValidPath && !correctFileExists && correctPath != null) { + return ((SourceFile) tree).withSourcePath(correctPath); + } else { + return sourceFile; + } + } + } + return super.visit(tree, executionContext); + } + }; + } +} \ No newline at end of file diff --git a/src/main/resources/META-INF/rewrite/openliberty-23.yml b/src/main/resources/META-INF/rewrite/openliberty-23.yml deleted file mode 100644 index bef3968..0000000 --- a/src/main/resources/META-INF/rewrite/openliberty-23.yml +++ /dev/null @@ -1,17 +0,0 @@ -# -# 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. -# - ---- diff --git a/src/main/resources/META-INF/rewrite/was-to-liberty.yml b/src/main/resources/META-INF/rewrite/was-to-liberty.yml new file mode 100644 index 0000000..4887967 --- /dev/null +++ b/src/main/resources/META-INF/rewrite/was-to-liberty.yml @@ -0,0 +1,131 @@ +# +# 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. +# + +######################################################################################################################## +# WebSphere traditional to Liberty +--- +type: specs.openrewrite.org/v1beta/recipe +name: org.openrewrite.java.liberty +displayName: Migrate from WebSphere traditional to Liberty +description: > + Use this category of rules to identify code changes needed when migrating + from WebSphere Application Server traditional to Liberty. +recipeList: + - org.openrewrite.java.liberty.RemoveWas2LibertyNonPortableJndiLookup + - org.openrewrite.java.liberty.ServerName + - org.openrewrite.xml.liberty.AppDDNamespaceRule + - org.openrewrite.xml.liberty.ConnectorDDNamespaceRule + - org.openrewrite.xml.liberty.EJBDDNamespaceRule + - org.openrewrite.xml.liberty.PersistenceXmlLocationRule + - org.openrewrite.xml.liberty.WebDDNamespaceRule +--- +type: specs.openrewrite.org/v1beta/recipe +name: org.openrewrite.java.liberty.RemoveWas2LibertyNonPortableJndiLookup +recipeList: + - org.openrewrite.java.liberty.RemoveWas2LibertyNonPortableJndiLookup +--- +type: specs.openrewrite.org/v1beta/recipe +name: org.openrewrite.java.liberty.ServerName +recipeList: + - org.openrewrite.java.liberty.ChangeMethodInvocation: + methodPattern: com.ibm.websphere.runtime.ServerName getDisplayName() + newMethodPattern: java.lang.System getProperty("wlp.server.name") + performStaticCall: true + - org.openrewrite.java.liberty.ChangeMethodInvocation: + methodPattern: com.ibm.websphere.runtime.ServerName getFullName() + newMethodPattern: java.lang.System getProperty("wlp.server.name") + performStaticCall: true +--- +type: specs.openrewrite.org/v1beta/recipe +name: org.openrewrite.xml.liberty.AppDDNamespaceRule +recipeList: + - org.openrewrite.xml.ChangeNamespaceValue: + elementName: application + newValue: http://java.sun.com/xml/ns/j2ee + versionMatcher: 1.4 + searchAllNamespaces: false + - org.openrewrite.xml.ChangeNamespaceValue: + elementName: application + newValue: http://java.sun.com/xml/ns/javaee + versionMatcher: 5,6 + searchAllNamespaces: false + - org.openrewrite.xml.ChangeNamespaceValue: + elementName: application + newValue: http://xmlns.jcp.org/xml/ns/javaee + versionMatcher: 7+ + searchAllNamespaces: false +--- +type: specs.openrewrite.org/v1beta/recipe +name: org.openrewrite.xml.liberty.ConnectorDDNamespaceRule +recipeList: + - org.openrewrite.xml.ChangeNamespaceValue: + elementName: connector + newValue: http://java.sun.com/xml/ns/j2ee + versionMatcher: 1.5 + searchAllNamespaces: false + - org.openrewrite.xml.ChangeNamespaceValue: + elementName: connector + newValue: http://java.sun.com/xml/ns/javaee + versionMatcher: 1.6 + searchAllNamespaces: false + - org.openrewrite.xml.ChangeNamespaceValue: + elementName: connector + newValue: http://xmlns.jcp.org/xml/ns/javaee + versionMatcher: 1.7+ + searchAllNamespaces: false +--- +type: specs.openrewrite.org/v1beta/recipe +name: org.openrewrite.xml.liberty.EJBDDNamespaceRule +recipeList: + - org.openrewrite.xml.ChangeNamespaceValue: + elementName: ejb-jar + newValue: http://java.sun.com/xml/ns/j2ee + versionMatcher: 2.1 + searchAllNamespaces: false + - org.openrewrite.xml.ChangeNamespaceValue: + elementName: ejb-jar + newValue: http://java.sun.com/xml/ns/javaee + versionMatcher: 3.0,3.1 + searchAllNamespaces: false + - org.openrewrite.xml.ChangeNamespaceValue: + elementName: ejb-jar + newValue: http://xmlns.jcp.org/xml/ns/javaee + versionMatcher: 3.2+ + searchAllNamespaces: false +--- +type: specs.openrewrite.org/v1beta/recipe +name: org.openrewrite.xml.liberty.PersistenceXmlLocationRule +recipeList: + - org.openrewrite.xml.liberty.PersistenceXmlLocationRule +--- +type: specs.openrewrite.org/v1beta/recipe +name: org.openrewrite.xml.liberty.WebDDNamespaceRule +recipeList: + - org.openrewrite.xml.ChangeNamespaceValue: + elementName: web-app + newValue: http://java.sun.com/xml/ns/j2ee + versionMatcher: 2.4 + searchAllNamespaces: false + - org.openrewrite.xml.ChangeNamespaceValue: + elementName: web-app + newValue: http://java.sun.com/xml/ns/java + versionMatcher: 2.5,3.0 + searchAllNamespaces: false + - org.openrewrite.xml.ChangeNamespaceValue: + elementName: web-app + newValue: http://xmlns.jcp.org/xml/ns/javaee + versionMatcher: 3.1+ + searchAllNamespaces: false diff --git a/src/test/java/org/openrewrite/.editorconfig b/src/test/java/org/openrewrite/.editorconfig new file mode 100644 index 0000000..a482493 --- /dev/null +++ b/src/test/java/org/openrewrite/.editorconfig @@ -0,0 +1,5 @@ +root = true + +[*.java] +indent_size = 4 +ij_continuation_indent_size = 2 diff --git a/src/test/java/org/openrewrite/java/liberty/InvalidInitialContextTest.java b/src/test/java/org/openrewrite/java/liberty/InvalidInitialContextTest.java new file mode 100644 index 0000000..b99a4e6 --- /dev/null +++ b/src/test/java/org/openrewrite/java/liberty/InvalidInitialContextTest.java @@ -0,0 +1,86 @@ +/* + * 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.liberty; + +import org.junit.jupiter.api.Test; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; + +public class InvalidInitialContextTest implements RewriteTest { + + String initialContextClass = """ + package javax.naming; + + public class InitialContext { + + public InitialContext() { + } + + public void lookup() { + } + + } + """; + + @Test + void replaceTimeoutTest() { + rewriteRun( + spec -> spec.recipe(new ChangeStringLiteral("^java:/comp(.*)$", "java:comp$1")), + java(initialContextClass), + java( + """ + package com.test; + + import javax.naming.InitialContext; + import javax.naming.NamingException; + + public class TestDetectInvalidInitialContext { + public static final String BAD_ENV = "java:/comp"; + public static final String GOOD_ENV = "java:comp"; + + private void doX(){ + InitialContext ic = new InitialContext(); + ic.lookup("java:/comp"); + ic.lookup("java:/comp/BadEntry"); + ic.lookup("java:comp/GoodEntry"); + } + } + """, + """ + package com.test; + + import javax.naming.InitialContext; + import javax.naming.NamingException; + + public class TestDetectInvalidInitialContext { + public static final String BAD_ENV = java:comp; + public static final String GOOD_ENV = "java:comp"; + + private void doX(){ + InitialContext ic = new InitialContext(); + ic.lookup(java:comp); + ic.lookup(java:comp/BadEntry); + ic.lookup("java:comp/GoodEntry"); + } + } + """ + ) + ); + } + +} diff --git a/src/test/java/org/openrewrite/java/liberty/RemoveWas2LibertyNonPortableJndiLookupTest.java b/src/test/java/org/openrewrite/java/liberty/RemoveWas2LibertyNonPortableJndiLookupTest.java new file mode 100644 index 0000000..992e802 --- /dev/null +++ b/src/test/java/org/openrewrite/java/liberty/RemoveWas2LibertyNonPortableJndiLookupTest.java @@ -0,0 +1,70 @@ +/* + * 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.liberty; + +import org.junit.jupiter.api.Test; +import org.openrewrite.config.Environment; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; + +public class RemoveWas2LibertyNonPortableJndiLookupTest implements RewriteTest { + + @Test + void removeInvalidPropertiesTest() { + rewriteRun( + spec -> spec.recipe(Environment.builder().scanRuntimeClasspath("org.openrewrite.java.liberty").build().activateRecipes("org.openrewrite.java.liberty.RemoveWas2LibertyNonPortableJndiLookup")), + java( + """ + package com.ibm; + + import java.util.Hashtable; + import javax.naming.InitialContext; + + public class ServerNameUsage { + + public void doX() { + Hashtable ht = new Hashtable(); + ht.put("java.naming.factory.initial", "com.ibm.websphere.naming.WsnInitialContextFactory"); + ht.put("java.naming.provider.url", "corbaloc:iiop:localhost:2809"); + + InitialContext ctx = new InitialContext(ht); + } + + } + """, + """ + package com.ibm; + + import java.util.Hashtable; + import javax.naming.InitialContext; + + public class ServerNameUsage { + + public void doX() { + Hashtable ht = new Hashtable(); + + InitialContext ctx = new InitialContext(ht); + } + + } + """ + ) + ); + } + +} diff --git a/src/test/java/org/openrewrite/java/liberty/ServerNameTest.java b/src/test/java/org/openrewrite/java/liberty/ServerNameTest.java new file mode 100644 index 0000000..1402cde --- /dev/null +++ b/src/test/java/org/openrewrite/java/liberty/ServerNameTest.java @@ -0,0 +1,110 @@ +/* + * 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.liberty; + +import org.junit.jupiter.api.Test; +import org.openrewrite.config.Environment; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; + +public class ServerNameTest implements RewriteTest { + + String serverNameClass = """ + package com.ibm.websphere.runtime; + + public class ServerName { + + public static String getDisplayName() { + return ""; + } + + public static String getFullName() { + return ""; + } + + } + """; + + @Test + void replaceGetFullNameTest() { + rewriteRun( + spec -> spec.recipe(Environment.builder().scanRuntimeClasspath("org.openrewrite.java.liberty").build().activateRecipes("org.openrewrite.java.liberty.ServerName")), + java(serverNameClass), + java( + """ + package com.ibm; + + import com.ibm.websphere.runtime.ServerName; + + public class ServerNameUsage { + + public void doX() { + ServerName.getFullName(); + } + + } + """, + """ + package com.ibm; + + public class ServerNameUsage { + + public void doX() { + System.getProperty("wlp.server.name"); + } + + } + """ + ) + ); + } + + @Test + void replaceGetDisplayNameTest() { + rewriteRun( + spec -> spec.recipe(Environment.builder().scanRuntimeClasspath("org.openrewrite.java.liberty").build().activateRecipes("org.openrewrite.java.liberty.ServerName")), + java(serverNameClass), + java( + """ + package com.ibm; + + import com.ibm.websphere.runtime.ServerName; + + public class ServerNameUsage { + + public void doX() { + ServerName.getDisplayName(); + } + + } + """, + """ + package com.ibm; + + public class ServerNameUsage { + + public void doX() { + System.getProperty("wlp.server.name"); + } + + } + """ + ) + ); + } +} diff --git a/src/test/java/org/openrewrite/xml/liberty/AppDDNamespaceTest.java b/src/test/java/org/openrewrite/xml/liberty/AppDDNamespaceTest.java new file mode 100644 index 0000000..1aac361 --- /dev/null +++ b/src/test/java/org/openrewrite/xml/liberty/AppDDNamespaceTest.java @@ -0,0 +1,295 @@ +/* + * 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.xml.liberty; + +import org.junit.jupiter.api.Test; +import org.openrewrite.config.Environment; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.xml.Assertions.xml; + +class AppDDNamespaceTest implements RewriteTest { + @Override + public void defaults(RecipeSpec spec) { + spec.recipe( + Environment.builder() + .scanRuntimeClasspath("org.openrewrite.java.liberty") + .build() + .activateRecipes("org.openrewrite.xml.liberty.AppDDNamespaceRule")); + } + + @Test + void replaceVersion14Test() { + rewriteRun( + //language=xml + xml( + """ + + DayTrader Stock Trading Performance Benchmark Sample + Trade + + daytrader-streamer-1.0.jar + + + daytrader-wsappclient-1.0.jar + + + + daytrader-web-1.0.war + /daytrader + + + + daytrader-ejb-1.0.jar + + + """, + """ + + DayTrader Stock Trading Performance Benchmark Sample + Trade + + daytrader-streamer-1.0.jar + + + daytrader-wsappclient-1.0.jar + + + + daytrader-web-1.0.war + /daytrader + + + + daytrader-ejb-1.0.jar + + + """ + ) + ); + } + + @Test + void replaceVersion5Test() { + rewriteRun( + //language=xml + xml( + """ + + + + test-client.jar + + + + test-ejb.jar + + + + + test.war + test + + + + lib + + """, + """ + + + + test-client.jar + + + + test-ejb.jar + + + + + test.war + test + + + + lib + + """ + ) + ); + } + + @Test + void replaceVersion6Test() { + rewriteRun( + //language=xml + xml( + """ + + + + test-client.jar + + + + test-ejb.jar + + + + + test.war + test + + + + lib + + """, + """ + + + + test-client.jar + + + + test-ejb.jar + + + + + test.war + test + + + + lib + + """ + ) + ); + } + + @Test + void replaceVersion7Test() { + rewriteRun( + //language=xml + xml( + """ + + + test-app + true + + + test-web.war + test + + + + + test-ejb.jar + + lib + + """, + """ + + + test-app + true + + + test-web.war + test + + + + + test-ejb.jar + + lib + + """ + ) + ); + } + + @Test + void replaceVersion8Test() { + rewriteRun( + //language=xml + xml( + """ + + + test-app + true + + + test-web.war + test + + + + + test-ejb.jar + + lib + + """, + """ + + + test-app + true + + + test-web.war + test + + + + + test-ejb.jar + + lib + + """ + ) + ); + } +} + diff --git a/src/test/java/org/openrewrite/xml/liberty/ConnectorDDNamespaceTest.java b/src/test/java/org/openrewrite/xml/liberty/ConnectorDDNamespaceTest.java new file mode 100644 index 0000000..58e508a --- /dev/null +++ b/src/test/java/org/openrewrite/xml/liberty/ConnectorDDNamespaceTest.java @@ -0,0 +1,213 @@ +/* + * 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.xml.liberty; + +import org.junit.jupiter.api.Test; +import org.openrewrite.config.Environment; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.xml.Assertions.xml; + + class ConnectorDDNamespaceTest implements RewriteTest { + @Override + public void defaults(RecipeSpec spec) { + spec.recipe( + Environment.builder() + .scanRuntimeClasspath("org.openrewrite.java.liberty") + .build() + .activateRecipes("org.openrewrite.xml.liberty.ConnectorDDNamespaceRule")); + } + + @Test + void replaceVersion15Test() { + rewriteRun( + //language=xml + xml( + """ + + Generic JCA + adam-bien.com + Generic JCA + 1.0 + + + + ...genericjca.GenericManagedConnectionFactory + ...genericjca.DataSource + ...genericjca.FileDataSource + ...genericjca.Connection + ...genericjca.FileConnection + + LocalTransaction + + BasicPassword + javax.resource.spi.security.PasswordCredential + + false + + + + """, + """ + + Generic JCA + adam-bien.com + Generic JCA + 1.0 + + + + ...genericjca.GenericManagedConnectionFactory + ...genericjca.DataSource + ...genericjca.FileDataSource + ...genericjca.Connection + ...genericjca.FileConnection + + LocalTransaction + + BasicPassword + javax.resource.spi.security.PasswordCredential + + false + + + + """ + ) + ); + } + + @Test + void replaceVersion16Test() { + rewriteRun( + //language=xml + xml( + """ + + Generic JCA + adam-bien.com + Generic JCA + 1.0 + + + + ...genericjca.GenericManagedConnectionFactory + ...genericjca.DataSource + ...genericjca.FileDataSource + ...genericjca.Connection + ...genericjca.FileConnection + + LocalTransaction + + BasicPassword + javax.resource.spi.security.PasswordCredential + + false + + + + """, + """ + + Generic JCA + adam-bien.com + Generic JCA + 1.0 + + + + ...genericjca.GenericManagedConnectionFactory + ...genericjca.DataSource + ...genericjca.FileDataSource + ...genericjca.Connection + ...genericjca.FileConnection + + LocalTransaction + + BasicPassword + javax.resource.spi.security.PasswordCredential + + false + + + + """ + ) + ); + } + + @Test + void replaceVersion17Test() { + rewriteRun( + //language=xml + xml( + """ + + Generic JCA + adam-bien.com + Generic JCA + 1.0 + + + + ...genericjca.GenericManagedConnectionFactory + ...genericjca.DataSource + ...genericjca.FileDataSource + ...genericjca.Connection + ...genericjca.FileConnection + + LocalTransaction + + BasicPassword + javax.resource.spi.security.PasswordCredential + + false + + + + """, + """ + + Generic JCA + adam-bien.com + Generic JCA + 1.0 + + + + ...genericjca.GenericManagedConnectionFactory + ...genericjca.DataSource + ...genericjca.FileDataSource + ...genericjca.Connection + ...genericjca.FileConnection + + LocalTransaction + + BasicPassword + javax.resource.spi.security.PasswordCredential + + false + + + + """ + ) + ); + } +} + diff --git a/src/test/java/org/openrewrite/xml/liberty/EJBDDNamespaceTest.java b/src/test/java/org/openrewrite/xml/liberty/EJBDDNamespaceTest.java new file mode 100644 index 0000000..d3e6cc5 --- /dev/null +++ b/src/test/java/org/openrewrite/xml/liberty/EJBDDNamespaceTest.java @@ -0,0 +1,311 @@ +/* + * 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.xml.liberty; + +import org.junit.jupiter.api.Test; +import org.openrewrite.config.Environment; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.xml.Assertions.xml; + +class EJBDDNamespaceTest implements RewriteTest { + @Override + public void defaults(RecipeSpec spec) { + spec.recipe( + Environment.builder() + .scanRuntimeClasspath("org.openrewrite.java.liberty") + .build() + .activateRecipes("org.openrewrite.xml.liberty.EJBDDNamespaceRule")); + } + + @Test + void replaceVersion21Test() { + rewriteRun( + //language=xml + xml( + """ + + + EchoEJBProject + + + EchoEJB + test.EchoEJBHome + test.EchoEJB + test.EchoEJB + test.EchoEJBBean + Stateless + Container + + + + """, + """ + + + EchoEJBProject + + + EchoEJB + test.EchoEJBHome + test.EchoEJB + test.EchoEJB + test.EchoEJBBean + Stateless + Container + + + + """ + ) + ); + } + + @Test + void replaceVersion30Test() { + rewriteRun( + //language=xml + xml( + """ + + + + TestBean + + ejb/fooremote + Session + test.FooRemoteIF + + + + + + + test.Interceptor1 + + + + + + * + test.Interceptor1 + + + + """, + """ + + + + TestBean + + ejb/fooremote + Session + test.FooRemoteIF + + + + + + + test.Interceptor1 + + + + + + * + test.Interceptor1 + + + + """ + ) + ); + } + + @Test + void replaceVersion31Test() { + rewriteRun( + //language=xml + xml( + """ + + + + TestBean + + ejb/fooremote + Session + test.FooRemoteIF + + + + + + + test.Interceptor1 + + + + + + * + test.Interceptor1 + + + + """, + """ + + + + TestBean + + ejb/fooremote + Session + test.FooRemoteIF + + + + + + + test.Interceptor1 + + + + + + * + test.Interceptor1 + + + + """ + ) + ); + } + + @Test + void replaceVersion32Test() { + rewriteRun( + //language=xml + xml( + """ + + Enterprise JavaBeans 3.1 + Enterprise JavaBeans 3.1 + + + WorkerBean + com.sample.ejb3.slsb.simple2.WorkerBusinessLocal + com.sample.ejb3.slsb.simple2.WorkerBusinessRemote + com.sample.ejb3.slsb.simple2.WorkerBase + Stateless + true + Container + + FILTER + java.lang.Long + 11011 + + + + + """, + """ + + Enterprise JavaBeans 3.1 + Enterprise JavaBeans 3.1 + + + WorkerBean + com.sample.ejb3.slsb.simple2.WorkerBusinessLocal + com.sample.ejb3.slsb.simple2.WorkerBusinessRemote + com.sample.ejb3.slsb.simple2.WorkerBase + Stateless + true + Container + + FILTER + java.lang.Long + 11011 + + + + + """ + ) + ); + } + + @Test + void replaceVersion33Test() { + rewriteRun( + //language=xml + xml( + """ + + Enterprise JavaBeans 3.1 + Enterprise JavaBeans 3.1 + + + WorkerBean + com.sample.ejb3.slsb.simple2.WorkerBusinessLocal + com.sample.ejb3.slsb.simple2.WorkerBusinessRemote + com.sample.ejb3.slsb.simple2.WorkerBase + Stateless + true + Container + + FILTER + java.lang.Long + 11011 + + + + + """, + """ + + Enterprise JavaBeans 3.1 + Enterprise JavaBeans 3.1 + + + WorkerBean + com.sample.ejb3.slsb.simple2.WorkerBusinessLocal + com.sample.ejb3.slsb.simple2.WorkerBusinessRemote + com.sample.ejb3.slsb.simple2.WorkerBase + Stateless + true + Container + + FILTER + java.lang.Long + 11011 + + + + + """ + ) + ); + } +} + diff --git a/src/test/java/org/openrewrite/xml/liberty/PersistenceXmlLocationRuleTest.java b/src/test/java/org/openrewrite/xml/liberty/PersistenceXmlLocationRuleTest.java new file mode 100644 index 0000000..256bc17 --- /dev/null +++ b/src/test/java/org/openrewrite/xml/liberty/PersistenceXmlLocationRuleTest.java @@ -0,0 +1,58 @@ +/* + * 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.xml.liberty; + +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.config.Environment; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import java.nio.file.Paths; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.openrewrite.java.Assertions.project; +import static org.openrewrite.test.SourceSpecs.text; + +class PersistenceXmlLocationRuleTest implements RewriteTest { + @Override + public void defaults(RecipeSpec spec) { + spec.recipe( + Environment.builder() + .scanRuntimeClasspath("org.openrewrite.java.liberty") + .build() + .activateRecipes("org.openrewrite.xml.liberty.PersistenceXmlLocationRule")); + } + + @DocumentExample + @Test + void movePersistenceXMLFileTest() { + rewriteRun( + text( + //language=xml + """ + + + + + """, + spec -> project(spec, "testEjbWithJpa").path("testEjbWithJpa/notsrc/META-INF/persistence.xml") + .afterRecipe(pt -> assertThat(pt.getSourcePath()).isEqualTo(Paths.get(System.getProperty("user.dir"), "testEjbWithJpa/src/META-INF/persistence.xml"))) + ) + ); + } +} diff --git a/src/test/java/org/openrewrite/xml/liberty/WebDDNamespaceTest.java b/src/test/java/org/openrewrite/xml/liberty/WebDDNamespaceTest.java new file mode 100644 index 0000000..3286aa9 --- /dev/null +++ b/src/test/java/org/openrewrite/xml/liberty/WebDDNamespaceTest.java @@ -0,0 +1,132 @@ +/* + * 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.xml.liberty; + +import org.junit.jupiter.api.Test; +import org.openrewrite.config.Environment; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.xml.Assertions.xml; + +class WebDDNamespaceTest implements RewriteTest { + @Override + public void defaults(RecipeSpec spec) { + spec.recipe( + Environment.builder() + .scanRuntimeClasspath("org.openrewrite.java.liberty") + .build() + .activateRecipes("org.openrewrite.xml.liberty.WebDDNamespaceRule")); + } + + @Test + void replaceVersion24Test() { + rewriteRun( + //language=xml + xml( + """ + + testWebDDNamespace + + """, + """ + + testWebDDNamespace + + """ + ) + ); + } + + @Test + void replaceVersion25Test() { + rewriteRun( + //language=xml + xml( + """ + + testWebDDNamespace + + """, + """ + + testWebDDNamespace + + """ + ) + ); + } + + @Test + void replaceVersion30Test() { + //language=xml + rewriteRun( + //language=xml + xml( + """ + + testWebDDNamespace + + """, + """ + + testWebDDNamespace + + """ + ) + ); + } + + @Test + void replaceVersion31Test() { + rewriteRun( + //language=xml + xml( + """ + + testWebDDNamespace + + """, + """ + + testWebDDNamespace + + """ + ) + ); + } + + @Test + void replaceVersion32Test() { + rewriteRun( + //language=xml + xml( + """ + + testWebDDNamespace + + """, + """ + + testWebDDNamespace + + """ + ) + ); + } +} +