diff --git a/core-it-suite/src/test/java/org/apache/maven/it/MavenITOutputCapabilitiesTest.java b/core-it-suite/src/test/java/org/apache/maven/it/MavenITOutputCapabilitiesTest.java new file mode 100644 index 000000000..a76dfbb25 --- /dev/null +++ b/core-it-suite/src/test/java/org/apache/maven/it/MavenITOutputCapabilitiesTest.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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.apache.maven.it; + +import java.io.File; +import java.util.Properties; + +import org.apache.maven.shared.verifier.Verifier; +import org.apache.maven.shared.verifier.util.ResourceExtractor; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class MavenITOutputCapabilitiesTest extends AbstractMavenIntegrationTestCase { + MavenITOutputCapabilitiesTest() { + super("[3.10.0-SNAPSHOT,)"); + } + + @Test + void injectsCapabilitiesIntoLegacyPluginsInParallelReactor() throws Exception { + File directory = ResourceExtractor.simpleExtractResources(getClass(), "/output-capabilities"); + Verifier plugin = newVerifier(new File(directory, "plugin").getPath(), "remote"); + plugin.addCliArgument("install"); + plugin.execute(); + plugin.verifyErrorFreeLog(); + Verifier legacyPlugin = newVerifier(new File(directory, "legacy-plugin").getPath(), "remote"); + legacyPlugin.addCliArgument("install"); + legacyPlugin.execute(); + legacyPlugin.verifyErrorFreeLog(); + + for (String color : new String[] {"never", "always"}) { + Verifier consumer = newVerifier(new File(directory, "consumer").getPath()); + consumer.addCliArgument("-T2"); + consumer.addCliArgument("-l"); + consumer.addCliArgument("build.log"); + consumer.addCliArgument("-B"); + consumer.addCliArgument("--color=" + color); + consumer.addCliArgument("validate"); + consumer.execute(); + consumer.verifyErrorFreeLog(); + for (String prefix : new String[] {"", "child/"}) { + Properties properties = consumer.loadProperties(prefix + "target/output-capabilities.properties"); + Properties legacy = consumer.loadProperties(prefix + "target/legacy-output-capabilities.properties"); + assertEquals("true", legacy.getProperty("available")); + assertEquals(properties.getProperty("destination"), legacy.getProperty("destination")); + assertEquals(properties.getProperty("encoding"), legacy.getProperty("encoding")); + // Maven 3 opens -l output with the JVM default charset. + assertEquals("FILE", properties.getProperty("destination")); + assertEquals(properties.getProperty("defaultEncoding"), properties.getProperty("encoding")); + } + } + } +} diff --git a/core-it-suite/src/test/java/org/apache/maven/it/TestSuiteOrdering.java b/core-it-suite/src/test/java/org/apache/maven/it/TestSuiteOrdering.java index 14da52359..c6db8066e 100644 --- a/core-it-suite/src/test/java/org/apache/maven/it/TestSuiteOrdering.java +++ b/core-it-suite/src/test/java/org/apache/maven/it/TestSuiteOrdering.java @@ -131,6 +131,7 @@ public TestSuiteOrdering() { suite.addTestSuite(MavenITmng7228LeakyModelTest.class); suite.addTestSuite(MavenITmng7819FileLockingWithSnapshotsTest.class); suite.addTestSuite(MavenITmng7587Jsr330.class); + suite.addTestSuite(MavenITOutputCapabilitiesTest.class); suite.addTestSuite(MavenITmng7038RootdirTest.class); suite.addTestSuite(MavenITmng7697PomWithEmojiTest.class); suite.addTestSuite(MavenITmng7737ProfileActivationTest.class); diff --git a/core-it-suite/src/test/resources/output-capabilities/consumer/child/pom.xml b/core-it-suite/src/test/resources/output-capabilities/consumer/child/pom.xml new file mode 100644 index 000000000..73671cbdb --- /dev/null +++ b/core-it-suite/src/test/resources/output-capabilities/consumer/child/pom.xml @@ -0,0 +1,29 @@ + + + + 4.0.0 + + org.apache.maven.its.output + consumer + 1.0 + + child + pom + diff --git a/core-it-suite/src/test/resources/output-capabilities/consumer/pom.xml b/core-it-suite/src/test/resources/output-capabilities/consumer/pom.xml new file mode 100644 index 000000000..70eceae68 --- /dev/null +++ b/core-it-suite/src/test/resources/output-capabilities/consumer/pom.xml @@ -0,0 +1,74 @@ + + + + 4.0.0 + org.apache.maven.its.output + consumer + 1.0 + pom + + child + + + + + org.apache.maven.its.output + legacy-output-capabilities-maven-plugin + 1.0 + + + + report + + validate + + + + + + + + typed + + true + + + + + org.apache.maven.its.output + output-capabilities-maven-plugin + 1.0 + + + + report + + validate + + + + + + + + legacy-only + + + diff --git a/core-it-suite/src/test/resources/output-capabilities/legacy-plugin/pom.xml b/core-it-suite/src/test/resources/output-capabilities/legacy-plugin/pom.xml new file mode 100644 index 000000000..36f1cccb7 --- /dev/null +++ b/core-it-suite/src/test/resources/output-capabilities/legacy-plugin/pom.xml @@ -0,0 +1,63 @@ + + + + 4.0.0 + org.apache.maven.its.output + legacy-output-capabilities-maven-plugin + 1.0 + maven-plugin + + 3.6.3 + 8 + UTF-8 + + + + org.apache.maven + maven-core + ${maven.version} + provided + + + org.apache.maven + maven-plugin-api + ${maven.version} + provided + + + org.apache.maven.plugin-tools + maven-plugin-annotations + 3.15.2 + provided + + + + + + maven-compiler-plugin + 3.14.1 + + + maven-plugin-plugin + 3.15.2 + + + + diff --git a/core-it-suite/src/test/resources/output-capabilities/legacy-plugin/src/main/java/org/apache/maven/its/output/LegacyOutputMojo.java b/core-it-suite/src/test/resources/output-capabilities/legacy-plugin/src/main/java/org/apache/maven/its/output/LegacyOutputMojo.java new file mode 100644 index 000000000..e8df6b547 --- /dev/null +++ b/core-it-suite/src/test/resources/output-capabilities/legacy-plugin/src/main/java/org/apache/maven/its/output/LegacyOutputMojo.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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.apache.maven.its.output; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +/** This fixture must compile and run using only Maven 3.6.3 APIs. */ +@Mojo(name = "report", threadSafe = true) +public class LegacyOutputMojo extends AbstractMojo { + @Parameter(defaultValue = "${session}", readonly = true) + private MavenSession session; + + @Parameter(defaultValue = "${project.build.directory}/legacy-output-capabilities.properties", readonly = true) + private File output; + + @Parameter(property = "capabilities.available", defaultValue = "true") + private boolean expectedAvailable; + + @Override + public void execute() throws MojoExecutionException { + Object value = session.getRequest().getData().get("maven.logging.outputCapabilities"); + boolean available = value instanceof Map; + if (expectedAvailable != available) { + throw new MojoExecutionException("Unexpected compatibility service availability: " + available); + } + Properties properties = new Properties(); + properties.setProperty("available", Boolean.toString(available)); + properties.setProperty("destination", "UNKNOWN"); + properties.setProperty("encoding", "unknown"); + properties.setProperty("defaultEncoding", Charset.defaultCharset().name()); + if (available) { + Map snapshot = new HashMap<>((Map) value); + Object destination = snapshot.get("destination"); + if (Arrays.asList("CONSOLE", "FILE", "REDIRECTED", "UNKNOWN").contains(destination)) { + properties.setProperty("destination", (String) destination); + } + Object encoding = snapshot.get("encoding"); + if (encoding instanceof String) { + properties.setProperty("encoding", (String) encoding); + } + } + try { + Files.createDirectories(output.toPath().getParent()); + try (OutputStream stream = Files.newOutputStream(output.toPath())) { + properties.store(stream, "Maven logging compatibility information"); + } + } catch (IOException e) { + throw new MojoExecutionException("Unable to write capabilities", e); + } + getLog().info("legacy-output-capabilities-marker caf\u00e9 \u251c\u2500"); + } +} diff --git a/core-it-suite/src/test/resources/output-capabilities/plugin/pom.xml b/core-it-suite/src/test/resources/output-capabilities/plugin/pom.xml new file mode 100644 index 000000000..a7584a93e --- /dev/null +++ b/core-it-suite/src/test/resources/output-capabilities/plugin/pom.xml @@ -0,0 +1,69 @@ + + + + 4.0.0 + org.apache.maven.its.output + output-capabilities-maven-plugin + 1.0 + maven-plugin + + 3.10.0-SNAPSHOT + 8 + UTF-8 + + + + org.apache.maven + maven-core + ${maven.version} + provided + + + org.apache.maven + maven-plugin-api + ${maven.version} + provided + + + javax.inject + javax.inject + 1 + provided + + + org.apache.maven.plugin-tools + maven-plugin-annotations + 3.15.2 + provided + + + + + + maven-compiler-plugin + 3.14.1 + + + maven-plugin-plugin + 3.15.2 + + + + diff --git a/core-it-suite/src/test/resources/output-capabilities/plugin/src/main/java/org/apache/maven/its/output/OutputMojo.java b/core-it-suite/src/test/resources/output-capabilities/plugin/src/main/java/org/apache/maven/its/output/OutputMojo.java new file mode 100644 index 000000000..8f1205158 --- /dev/null +++ b/core-it-suite/src/test/resources/output-capabilities/plugin/src/main/java/org/apache/maven/its/output/OutputMojo.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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.apache.maven.its.output; + +import javax.inject.Inject; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.Properties; + +import org.apache.maven.logging.OutputCapabilities; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +@Mojo(name = "report", threadSafe = true) +public class OutputMojo extends AbstractMojo { + @Inject + private OutputCapabilities capabilities; + + @Parameter(defaultValue = "${project.build.directory}/output-capabilities.properties", readonly = true) + private File output; + + @Override + public void execute() throws MojoExecutionException { + Properties properties = new Properties(); + properties.setProperty("destination", capabilities.getDestination().name()); + properties.setProperty( + "encoding", capabilities.getEncoding().map(Charset::name).orElse("unknown")); + properties.setProperty("defaultEncoding", Charset.defaultCharset().name()); + try { + Files.createDirectories(output.toPath().getParent()); + try (OutputStream stream = Files.newOutputStream(output.toPath())) { + properties.store(stream, "Maven logging capabilities"); + } + } catch (IOException e) { + throw new MojoExecutionException("Unable to write capabilities", e); + } + getLog().info("output-capabilities-marker caf\u00e9 \u251c\u2500"); + } +}