diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java index baa3f0aacc..bce7e2a630 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java @@ -28,13 +28,22 @@ */ public interface MessageBuilder { /** - * Append message content in success style. - * By default, bold green + * Append message content in debug style. + * By default, bold cyan * @param message the message to append * @return the current builder */ @Nonnull - MessageBuilder success(Object message); + MessageBuilder debug(Object message); + + /** + * Append message content in info style. + * By default, bold blue + * @param message the message to append + * @return the current builder + */ + @Nonnull + MessageBuilder info(Object message); /** * Append message content in warning style. @@ -45,6 +54,24 @@ public interface MessageBuilder { @Nonnull MessageBuilder warning(Object message); + /** + * Append message content in error style. + * By default, bold red + * @param message the message to append + * @return the current builder + */ + @Nonnull + MessageBuilder error(Object message); + + /** + * Append message content in success style. + * By default, bold green + * @param message the message to append + * @return the current builder + */ + @Nonnull + MessageBuilder success(Object message); + /** * Append message content in failure style. * By default, bold red diff --git a/maven-core/pom.xml b/maven-core/pom.xml index 83ad8ff157..5e49ad184e 100644 --- a/maven-core/pom.xml +++ b/maven-core/pom.xml @@ -99,10 +99,6 @@ under the License. org.apache.maven.resolver maven-resolver-util - - org.apache.maven.shared - maven-shared-utils - org.eclipse.sisu org.eclipse.sisu.plexus diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilder.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilder.java index 74f3729cc4..9c593e37bd 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilder.java @@ -24,106 +24,128 @@ @Experimental public class DefaultMessageBuilder implements MessageBuilder { - private final @Nonnull org.apache.maven.shared.utils.logging.MessageBuilder delegate; - public DefaultMessageBuilder(@Nonnull org.apache.maven.shared.utils.logging.MessageBuilder delegate) { - this.delegate = delegate; + private final StringBuilder buffer; + + public DefaultMessageBuilder() { + this(new StringBuilder()); + } + + public DefaultMessageBuilder(StringBuilder buffer) { + this.buffer = buffer; } @Override @Nonnull - public MessageBuilder success(Object o) { - delegate.success(o); - return this; + public MessageBuilder debug(Object o) { + return a(o); + } + + @Override + @Nonnull + public MessageBuilder info(Object o) { + return a(o); } @Override @Nonnull public MessageBuilder warning(Object o) { - delegate.warning(o); - return this; + return a(o); + } + + @Override + @Nonnull + public MessageBuilder error(Object o) { + return a(o); + } + + @Override + @Nonnull + public MessageBuilder success(Object o) { + return a(o); } @Override @Nonnull public MessageBuilder failure(Object o) { - delegate.failure(o); - return this; + return a(o); } @Override @Nonnull public MessageBuilder strong(Object o) { - delegate.strong(o); - return this; + return a(o); } @Override @Nonnull public MessageBuilder mojo(Object o) { - delegate.mojo(o); - return this; + return a(o); } @Override @Nonnull public MessageBuilder project(Object o) { - delegate.project(o); - return this; + return a(o); } @Override @Nonnull public MessageBuilder a(char[] chars, int i, int i1) { - delegate.a(chars, i, i1); + buffer.append(chars, i, i1); return this; } @Override @Nonnull public MessageBuilder a(char[] chars) { - delegate.a(chars); + buffer.append(chars); return this; } @Override @Nonnull public MessageBuilder a(CharSequence charSequence, int i, int i1) { - delegate.a(charSequence, i, i1); + buffer.append(charSequence, i, i1); return this; } @Override @Nonnull public MessageBuilder a(CharSequence charSequence) { - delegate.a(charSequence); + buffer.append(charSequence); return this; } @Override @Nonnull public MessageBuilder a(Object o) { - delegate.a(o); + buffer.append(o); return this; } @Override @Nonnull public MessageBuilder newline() { - delegate.newline(); + buffer.append(System.getProperty("line.separator")); return this; } @Override @Nonnull public MessageBuilder format(String s, Object... objects) { - delegate.format(s, objects); + buffer.append(String.format(s, objects)); return this; } @Override @Nonnull public String build() { - return delegate.toString(); + return buffer.toString(); + } + + @Override + public String toString() { + return build(); } } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilderFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilderFactory.java index c163f6b896..196af164b6 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilderFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilderFactory.java @@ -18,6 +18,8 @@ */ package org.apache.maven.internal.impl; +import javax.annotation.Priority; +import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; @@ -27,32 +29,35 @@ import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.services.MessageBuilder; import org.apache.maven.api.services.MessageBuilderFactory; -import org.apache.maven.shared.utils.logging.MessageUtils; @Experimental @Named @Singleton +@Priority(-1) public class DefaultMessageBuilderFactory implements MessageBuilderFactory { + @Inject + public DefaultMessageBuilderFactory() {} + @Override public boolean isColorEnabled() { - return MessageUtils.isColorEnabled(); + return false; } @Override public int getTerminalWidth() { - return MessageUtils.getTerminalWidth(); + return -1; } @Override @Nonnull public MessageBuilder builder() { - return new DefaultMessageBuilder(MessageUtils.buffer()); + return new DefaultMessageBuilder(); } @Override @Nonnull public MessageBuilder builder(@Nonnull StringBuilder stringBuilder) { - return new DefaultMessageBuilder(MessageUtils.buffer(Objects.requireNonNull(stringBuilder))); + return new DefaultMessageBuilder(Objects.requireNonNull(stringBuilder)); } } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/LifecycleExecutionException.java b/maven-core/src/main/java/org/apache/maven/lifecycle/LifecycleExecutionException.java index c7b8c085e6..feab79477a 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/LifecycleExecutionException.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/LifecycleExecutionException.java @@ -18,11 +18,11 @@ */ package org.apache.maven.lifecycle; +import org.apache.maven.api.services.MessageBuilder; +import org.apache.maven.api.services.MessageBuilderFactory; +import org.apache.maven.internal.impl.DefaultMessageBuilderFactory; import org.apache.maven.plugin.MojoExecution; import org.apache.maven.project.MavenProject; -import org.apache.maven.shared.utils.logging.MessageBuilder; - -import static org.apache.maven.shared.utils.logging.MessageUtils.buffer; /** * @author Jason van Zyl @@ -58,15 +58,27 @@ public LifecycleExecutionException(String message, MojoExecution execution, Mave } public LifecycleExecutionException(MojoExecution execution, MavenProject project, Throwable cause) { - this(createMessage(execution, project, cause), execution, project, cause); + this(new DefaultMessageBuilderFactory(), execution, project, cause); + } + + public LifecycleExecutionException( + MessageBuilderFactory messageBuilderFactory, + MojoExecution execution, + MavenProject project, + Throwable cause) { + this(createMessage(messageBuilderFactory, execution, project, cause), execution, project, cause); } public MavenProject getProject() { return project; } - private static String createMessage(MojoExecution execution, MavenProject project, Throwable cause) { - MessageBuilder buffer = buffer(256); + private static String createMessage( + MessageBuilderFactory messageBuilderFactory, + MojoExecution execution, + MavenProject project, + Throwable cause) { + MessageBuilder buffer = messageBuilderFactory.builder(256); buffer.a("Failed to execute goal"); diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java index 9a6755a5f0..99df99a51d 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java @@ -18,6 +18,7 @@ */ package org.apache.maven.lifecycle.internal; +import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; @@ -26,6 +27,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.apache.maven.api.services.MessageBuilder; +import org.apache.maven.api.services.MessageBuilderFactory; import org.apache.maven.api.xml.XmlNode; import org.apache.maven.internal.xml.XmlNodeImpl; import org.apache.maven.lifecycle.MojoExecutionConfigurator; @@ -35,8 +38,6 @@ import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.Parameter; import org.apache.maven.project.MavenProject; -import org.apache.maven.shared.utils.logging.MessageBuilder; -import org.apache.maven.shared.utils.logging.MessageUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,6 +51,9 @@ public class DefaultMojoExecutionConfigurator implements MojoExecutionConfigurator { private final Logger logger = LoggerFactory.getLogger(getClass()); + @Inject + MessageBuilderFactory messageBuilderFactory; + @Override public void configure(MavenProject project, MojoExecution mojoExecution, boolean allowPluginLevelConfig) { String g = mojoExecution.getPlugin().getGroupId(); @@ -136,7 +140,8 @@ private void checkUnknownMojoConfigurationParameters(MojoExecution mojoExecution unknownParameters = getUnknownParameters(mojoExecution, parametersNamesAll); unknownParameters.forEach(name -> { - MessageBuilder messageBuilder = MessageUtils.buffer() + MessageBuilder messageBuilder = messageBuilderFactory + .builder() .warning("Parameter '") .warning(name) .warning("' is unknown for plugin '") diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java index f7a4d484fb..f963263a3c 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java @@ -33,6 +33,7 @@ import java.util.stream.Collectors; import org.apache.maven.RepositoryUtils; +import org.apache.maven.api.services.MessageBuilderFactory; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.eventspy.internal.EventSpyDispatcher; @@ -75,16 +76,20 @@ public class LifecycleDependencyResolver { private final ProjectArtifactsCache projectArtifactsCache; + private final MessageBuilderFactory messageBuilderFactory; + @Inject public LifecycleDependencyResolver( ProjectDependenciesResolver dependenciesResolver, ProjectArtifactFactory artifactFactory, EventSpyDispatcher eventSpyDispatcher, - ProjectArtifactsCache projectArtifactsCache) { + ProjectArtifactsCache projectArtifactsCache, + MessageBuilderFactory messageBuilderFactory) { this.dependenciesResolver = dependenciesResolver; this.artifactFactory = artifactFactory; this.eventSpyDispatcher = eventSpyDispatcher; this.projectArtifactsCache = projectArtifactsCache; + this.messageBuilderFactory = messageBuilderFactory; } public static List getProjects(MavenProject project, MavenSession session, boolean aggregator) { @@ -253,7 +258,7 @@ private Set getDependencies( logger.warn("Try running the build up to the lifecycle phase \"package\""); } else { - throw new LifecycleExecutionException(null, project, e); + throw new LifecycleExecutionException(messageBuilderFactory, null, project, e); } } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java index e1edb38f3c..e67a068d28 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java @@ -36,6 +36,7 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import org.apache.maven.api.services.MessageBuilderFactory; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.resolver.filter.ArtifactFilter; import org.apache.maven.artifact.resolver.filter.CumulativeScopeArtifactFilter; @@ -86,6 +87,8 @@ public class MojoExecutor { private final Provider mojosExecutionStrategy; + private final MessageBuilderFactory messageBuilderFactory; + private final Map mojos = new ConcurrentHashMap<>(); @Inject @@ -94,12 +97,14 @@ public MojoExecutor( MavenPluginManager mavenPluginManager, LifecycleDependencyResolver lifeCycleDependencyResolver, ExecutionEventCatapult eventCatapult, - Provider mojosExecutionStrategy) { + Provider mojosExecutionStrategy, + MessageBuilderFactory messageBuilderFactory) { this.pluginManager = pluginManager; this.mavenPluginManager = mavenPluginManager; this.lifeCycleDependencyResolver = lifeCycleDependencyResolver; this.eventCatapult = eventCatapult; this.mojosExecutionStrategy = mojosExecutionStrategy; + this.messageBuilderFactory = messageBuilderFactory; } public DependencyContext newDependencyContext(MavenSession session, List mojoExecutions) { @@ -185,7 +190,7 @@ private void execute( try { mavenPluginManager.checkPrerequisites(mojoDescriptor.getPluginDescriptor()); } catch (PluginIncompatibleException e) { - throw new LifecycleExecutionException(mojoExecution, session.getCurrentProject(), e); + throw new LifecycleExecutionException(messageBuilderFactory, mojoExecution, session.getCurrentProject(), e); } if (mojoDescriptor.isProjectRequired() && !session.getRequest().isProjectPresent()) { @@ -193,14 +198,15 @@ private void execute( "Goal requires a project to execute" + " but there is no POM in this directory (" + session.getExecutionRootDirectory() + ")." + " Please verify you invoked Maven from the correct directory."); - throw new LifecycleExecutionException(mojoExecution, null, cause); + throw new LifecycleExecutionException(messageBuilderFactory, mojoExecution, null, cause); } if (mojoDescriptor.isOnlineRequired() && session.isOffline()) { if (MojoExecution.Source.CLI.equals(mojoExecution.getSource())) { Throwable cause = new IllegalStateException( "Goal requires online mode for execution" + " but Maven is currently offline."); - throw new LifecycleExecutionException(mojoExecution, session.getCurrentProject(), cause); + throw new LifecycleExecutionException( + messageBuilderFactory, mojoExecution, session.getCurrentProject(), cause); } else { eventCatapult.fire(ExecutionEvent.Type.MojoSkipped, session, mojoExecution); @@ -329,7 +335,8 @@ private void doExecute2(MavenSession session, MojoExecution mojoExecution) throw | PluginManagerException | PluginConfigurationException | MojoExecutionException e) { - throw new LifecycleExecutionException(mojoExecution, session.getCurrentProject(), e); + throw new LifecycleExecutionException( + messageBuilderFactory, mojoExecution, session.getCurrentProject(), e); } eventCatapult.fire(ExecutionEvent.Type.MojoSucceeded, session, mojoExecution); diff --git a/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedPluginValidator.java b/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedPluginValidator.java index 5544a74f34..198e50df0f 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedPluginValidator.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedPluginValidator.java @@ -22,11 +22,11 @@ import javax.inject.Named; import javax.inject.Singleton; +import org.apache.maven.api.services.MessageBuilderFactory; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.PluginValidationManager; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.Parameter; -import org.apache.maven.shared.utils.logging.MessageUtils; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; import org.codehaus.plexus.configuration.PlexusConfiguration; @@ -39,9 +39,13 @@ @Named class DeprecatedPluginValidator extends AbstractMavenPluginDescriptorSourcedParametersValidator { + private final MessageBuilderFactory messageBuilderFactory; + @Inject - DeprecatedPluginValidator(PluginValidationManager pluginValidationManager) { + DeprecatedPluginValidator( + PluginValidationManager pluginValidationManager, MessageBuilderFactory messageBuilderFactory) { super(pluginValidationManager); + this.messageBuilderFactory = messageBuilderFactory; } @Override @@ -94,7 +98,8 @@ private void checkParameter( } private String logDeprecatedMojo(MojoDescriptor mojoDescriptor) { - return MessageUtils.buffer() + return messageBuilderFactory + .builder() .warning("Goal '") .warning(mojoDescriptor.getGoal()) .warning("' is deprecated: ") diff --git a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/MojoExecutorStub.java b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/MojoExecutorStub.java index 8c58cc3b9f..aa393fd505 100644 --- a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/MojoExecutorStub.java +++ b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/MojoExecutorStub.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.List; +import org.apache.maven.api.services.MessageBuilderFactory; import org.apache.maven.execution.MavenSession; import org.apache.maven.lifecycle.LifecycleExecutionException; import org.apache.maven.lifecycle.internal.ExecutionEventCatapult; @@ -47,7 +48,7 @@ public class MojoExecutorStub extends MojoExecutor { // This is being lazy inste public final List executions = Collections.synchronizedList(new ArrayList<>()); public MojoExecutorStub() { - super(null, null, null, null, null); + super(null, null, null, null, null, null); } public MojoExecutorStub( @@ -55,8 +56,15 @@ public MojoExecutorStub( MavenPluginManager mavenPluginManager, LifecycleDependencyResolver lifeCycleDependencyResolver, ExecutionEventCatapult eventCatapult, - Provider mojosExecutionStrategy) { - super(pluginManager, mavenPluginManager, lifeCycleDependencyResolver, eventCatapult, mojosExecutionStrategy); + Provider mojosExecutionStrategy, + MessageBuilderFactory messageBuilderFactory) { + super( + pluginManager, + mavenPluginManager, + lifeCycleDependencyResolver, + eventCatapult, + mojosExecutionStrategy, + messageBuilderFactory); } @Override diff --git a/maven-embedder/pom.xml b/maven-embedder/pom.xml index 4f7bd0c165..91255af56e 100644 --- a/maven-embedder/pom.xml +++ b/maven-embedder/pom.xml @@ -72,10 +72,6 @@ under the License. org.apache.maven.resolver maven-resolver-util - - org.apache.maven.shared - maven-shared-utils - org.apache.maven maven-slf4j-wrapper @@ -146,6 +142,11 @@ under the License. commons-cli commons-cli + + org.fusesource.jansi + jansi + true + org.junit.jupiter junit-jupiter-params @@ -156,11 +157,6 @@ under the License. mockito-core test - - org.fusesource.jansi - jansi - test - commons-io commons-io diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java b/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java index e643f1a67e..1a04983931 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java @@ -28,7 +28,7 @@ import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; -import org.apache.maven.shared.utils.logging.MessageUtils; +import org.apache.maven.cli.jansi.MessageUtils; /** * @author Jason van Zyl diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/CLIReportingUtils.java b/maven-embedder/src/main/java/org/apache/maven/cli/CLIReportingUtils.java index 704212be57..2f1befe6ec 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/CLIReportingUtils.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/CLIReportingUtils.java @@ -25,11 +25,10 @@ import java.util.Locale; import java.util.Properties; +import org.apache.maven.cli.jansi.MessageUtils; import org.codehaus.plexus.util.Os; import org.slf4j.Logger; -import static org.apache.maven.shared.utils.logging.MessageUtils.buffer; - /** * Utility class used to report errors, statistics, application version info, etc. * @@ -54,7 +53,8 @@ public static String showVersion() { final String ls = System.lineSeparator(); Properties properties = getBuildProperties(); StringBuilder version = new StringBuilder(256); - version.append(buffer().strong(createMavenVersionString(properties))).append(ls); + version.append(MessageUtils.builder().strong(createMavenVersionString(properties))) + .append(ls); version.append(reduce(properties.getProperty("distributionShortName") + " home: " + System.getProperty("maven.home", ""))) .append(ls); diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java index d5700c310e..f387a67526 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java @@ -46,6 +46,8 @@ import org.apache.maven.BuildAbort; import org.apache.maven.InternalErrorException; import org.apache.maven.Maven; +import org.apache.maven.api.services.MessageBuilder; +import org.apache.maven.api.services.MessageBuilderFactory; import org.apache.maven.building.FileSource; import org.apache.maven.building.Problem; import org.apache.maven.building.Source; @@ -56,6 +58,8 @@ import org.apache.maven.cli.internal.BootstrapCoreExtensionManager; import org.apache.maven.cli.internal.extension.model.CoreExtension; import org.apache.maven.cli.internal.extension.model.io.xpp3.CoreExtensionsXpp3Reader; +import org.apache.maven.cli.jansi.JansiMessageBuilderFactory; +import org.apache.maven.cli.jansi.MessageUtils; import org.apache.maven.cli.logging.Slf4jConfiguration; import org.apache.maven.cli.logging.Slf4jConfigurationFactory; import org.apache.maven.cli.logging.Slf4jLoggerManager; @@ -87,8 +91,6 @@ import org.apache.maven.properties.internal.EnvironmentUtils; import org.apache.maven.properties.internal.SystemProperties; import org.apache.maven.session.scope.internal.SessionScopeModule; -import org.apache.maven.shared.utils.logging.MessageBuilder; -import org.apache.maven.shared.utils.logging.MessageUtils; import org.apache.maven.toolchain.building.DefaultToolchainsBuildingRequest; import org.apache.maven.toolchain.building.ToolchainsBuilder; import org.apache.maven.toolchain.building.ToolchainsBuildingResult; @@ -124,7 +126,6 @@ import static org.apache.maven.cli.CLIManager.FORCE_INTERACTIVE; import static org.apache.maven.cli.CLIManager.NON_INTERACTIVE; import static org.apache.maven.cli.ResolveFile.resolveFile; -import static org.apache.maven.shared.utils.logging.MessageUtils.buffer; // TODO push all common bits back to plexus cli and prepare for transition to Guice. We don't need 50 ways to make CLIs @@ -177,6 +178,8 @@ public class MavenCli { private CLIManager cliManager; + private MessageBuilderFactory messageBuilderFactory; + private static final Pattern NEXT_LINE = Pattern.compile("\r?\n"); public MavenCli() { @@ -186,6 +189,7 @@ public MavenCli() { // This supports painless invocation by the Verifier during embedded execution of the core ITs public MavenCli(ClassWorld classWorld) { this.classWorld = classWorld; + this.messageBuilderFactory = new JansiMessageBuilderFactory(); } public static void main(String[] args) { @@ -589,13 +593,12 @@ private void commands(CliRequest cliRequest) { if (slf4jLogger.isDebugEnabled()) { slf4jLogger.debug("Message scheme: {}", (MessageUtils.isColorEnabled() ? "color" : "plain")); if (MessageUtils.isColorEnabled()) { - MessageBuilder buff = MessageUtils.buffer(); + MessageBuilder buff = MessageUtils.builder(); buff.a("Message styles: "); - buff.a(MessageUtils.level().debug("debug")).a(' '); - buff.a(MessageUtils.level().info("info")).a(' '); - buff.a(MessageUtils.level().warning("warning")).a(' '); - buff.a(MessageUtils.level().error("error")).a(' '); - + buff.debug("debug").a(' '); + buff.info("info").a(' '); + buff.warning("warning").a(' '); + buff.error("error").a(' '); buff.success("success").a(' '); buff.failure("failure").a(' '); buff.strong("strong").a(' '); @@ -679,6 +682,7 @@ PlexusContainer container(CliRequest cliRequest) throws Exception { protected void configure() { bind(ILoggerFactory.class).toInstance(slf4jLoggerFactory); bind(CoreExports.class).toInstance(exports); + bind(MessageBuilderFactory.class).toInstance(messageBuilderFactory); } }); @@ -964,10 +968,12 @@ private int execute(CliRequest cliRequest) throws MavenExecutionRequestPopulatio if (!cliRequest.showErrors) { slf4jLogger.error( "To see the full stack trace of the errors, re-run Maven with the '{}' switch", - buffer().strong("-e")); + MessageUtils.builder().strong("-e")); } if (!slf4jLogger.isDebugEnabled()) { - slf4jLogger.error("Re-run Maven using the '{}' switch to enable verbose output", buffer().strong("-X")); + slf4jLogger.error( + "Re-run Maven using the '{}' switch to enable verbose output", + MessageUtils.builder().strong("-X")); } if (!references.isEmpty()) { @@ -976,7 +982,7 @@ private int execute(CliRequest cliRequest) throws MavenExecutionRequestPopulatio + ", please read the following articles:"); for (Map.Entry entry : references.entrySet()) { - slf4jLogger.error("{} {}", buffer().strong(entry.getValue()), entry.getKey()); + slf4jLogger.error("{} {}", MessageUtils.builder().strong(entry.getValue()), entry.getKey()); } } @@ -1010,7 +1016,7 @@ private int execute(CliRequest cliRequest) throws MavenExecutionRequestPopulatio private void logBuildResumeHint(String resumeBuildHint) { slf4jLogger.error(""); slf4jLogger.error("After correcting the problems, you can resume the build with the command"); - slf4jLogger.error(buffer().a(" ").strong(resumeBuildHint).toString()); + slf4jLogger.error(MessageUtils.builder().a(" ").strong(resumeBuildHint).toString()); } /** @@ -1059,9 +1065,9 @@ private void logSummary( if (referenceKey != null && !referenceKey.isEmpty()) { if (msg.indexOf('\n') < 0) { - msg += " -> " + buffer().strong(referenceKey); + msg += " -> " + MessageUtils.builder().strong(referenceKey); } else { - msg += "\n-> " + buffer().strong(referenceKey); + msg += "\n-> " + MessageUtils.builder().strong(referenceKey); } } @@ -1425,7 +1431,7 @@ static void performProfileActivation(final CommandLine commandLine, final Profil } private ExecutionListener determineExecutionListener() { - ExecutionListener executionListener = new ExecutionEventLogger(); + ExecutionListener executionListener = new ExecutionEventLogger(messageBuilderFactory); if (eventSpyDispatcher != null) { return eventSpyDispatcher.chainListener(executionListener); } else { diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/event/ExecutionEventLogger.java b/maven-embedder/src/main/java/org/apache/maven/cli/event/ExecutionEventLogger.java index ae591850be..26b4bcc531 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/event/ExecutionEventLogger.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/event/ExecutionEventLogger.java @@ -23,6 +23,8 @@ import java.util.List; import java.util.Objects; +import org.apache.maven.api.services.MessageBuilder; +import org.apache.maven.api.services.MessageBuilderFactory; import org.apache.maven.execution.AbstractExecutionListener; import org.apache.maven.execution.BuildFailure; import org.apache.maven.execution.BuildSuccess; @@ -35,8 +37,6 @@ import org.apache.maven.plugin.MojoExecution; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.project.MavenProject; -import org.apache.maven.shared.utils.logging.MessageBuilder; -import org.apache.maven.shared.utils.logging.MessageUtils; import org.codehaus.plexus.util.StringUtils; import org.slf4j.ILoggerFactory; import org.slf4j.Logger; @@ -44,7 +44,6 @@ import static org.apache.maven.cli.CLIReportingUtils.formatDuration; import static org.apache.maven.cli.CLIReportingUtils.formatTimestamp; -import static org.apache.maven.shared.utils.logging.MessageUtils.buffer; /** * Logs execution events to logger, eventually user-supplied. @@ -52,8 +51,6 @@ * @author Benjamin Bentmann */ public class ExecutionEventLogger extends AbstractExecutionListener { - private final Logger logger; - private static final int MAX_LOG_PREFIX_SIZE = 8; // "[ERROR] " private static final int PROJECT_STATUS_SUFFIX_SIZE = 20; // "SUCCESS [ 0.000 s]" private static final int MIN_TERMINAL_WIDTH = 60; @@ -61,26 +58,25 @@ public class ExecutionEventLogger extends AbstractExecutionListener { private static final int MAX_TERMINAL_WIDTH = 130; private static final int MAX_PADDED_BUILD_TIME_DURATION_LENGTH = 9; + private final MessageBuilderFactory messageBuilderFactory; + private final Logger logger; private final int terminalWidth; private final int lineLength; private final int maxProjectNameLength; private int totalProjects; private volatile int currentVisitedProjectCount; - public ExecutionEventLogger() { - this(LoggerFactory.getLogger(ExecutionEventLogger.class)); + public ExecutionEventLogger(MessageBuilderFactory messageBuilderFactory) { + this(messageBuilderFactory, LoggerFactory.getLogger(ExecutionEventLogger.class)); } - public ExecutionEventLogger(int terminalWidth) { - this(LoggerFactory.getLogger(ExecutionEventLogger.class), terminalWidth); + public ExecutionEventLogger(MessageBuilderFactory messageBuilderFactory, Logger logger) { + this(messageBuilderFactory, logger, messageBuilderFactory.getTerminalWidth()); } - public ExecutionEventLogger(Logger logger) { - this(logger, MessageUtils.getTerminalWidth()); - } - - public ExecutionEventLogger(Logger logger, int terminalWidth) { + public ExecutionEventLogger(MessageBuilderFactory messageBuilderFactory, Logger logger, int terminalWidth) { this.logger = Objects.requireNonNull(logger, "logger cannot be null"); + this.messageBuilderFactory = messageBuilderFactory; this.terminalWidth = Math.min( MAX_TERMINAL_WIDTH, Math.max(terminalWidth < 0 ? DEFAULT_TERMINAL_WIDTH : terminalWidth, MIN_TERMINAL_WIDTH)); @@ -103,7 +99,7 @@ private void infoLine(char c) { } private void infoMain(String msg) { - logger.info(buffer().strong(msg).toString()); + logger.info(builder().strong(msg).toString()); } @Override @@ -225,9 +221,9 @@ private void logReactorSummary(MavenSession session) { BuildSummary buildSummary = result.getBuildSummary(project); if (buildSummary == null) { - buffer.append(buffer().warning("SKIPPED")); + buffer.append(builder().warning("SKIPPED")); } else if (buildSummary instanceof BuildSuccess) { - buffer.append(buffer().success("SUCCESS")); + buffer.append(builder().success("SUCCESS")); buffer.append(" ["); String buildTimeDuration = formatDuration(buildSummary.getTime()); int padSize = MAX_PADDED_BUILD_TIME_DURATION_LENGTH - buildTimeDuration.length(); @@ -237,7 +233,7 @@ private void logReactorSummary(MavenSession session) { buffer.append(buildTimeDuration); buffer.append(']'); } else if (buildSummary instanceof BuildFailure) { - buffer.append(buffer().failure("FAILURE")); + buffer.append(builder().failure("FAILURE")); buffer.append(" ["); String buildTimeDuration = formatDuration(buildSummary.getTime()); int padSize = MAX_PADDED_BUILD_TIME_DURATION_LENGTH - buildTimeDuration.length(); @@ -254,7 +250,7 @@ private void logReactorSummary(MavenSession session) { private void logResult(MavenSession session) { infoLine('-'); - MessageBuilder buffer = buffer(); + MessageBuilder buffer = builder(); if (session.getResult().hasExceptions()) { buffer.failure("BUILD FAILURE"); @@ -264,6 +260,10 @@ private void logResult(MavenSession session) { logger.info(buffer.toString()); } + private MessageBuilder builder() { + return messageBuilderFactory.builder(); + } + private void logStats(MavenSession session) { infoLine('-'); @@ -312,7 +312,7 @@ public void projectStarted(ExecutionEvent event) { postHeader + chars('-', Math.max(0, lineLength - headerLen - prefix.length() + preHeader.length())); logger.info( - buffer().strong(prefix).project(projectKey).strong(suffix).toString()); + builder().strong(prefix).project(projectKey).strong(suffix).toString()); // Building Project Name Version [i/n] String building = "Building " + event.getProject().getName() + " " @@ -369,7 +369,7 @@ public void mojoStarted(ExecutionEvent event) { if (logger.isInfoEnabled()) { logger.info(""); - MessageBuilder buffer = buffer().strong("--- "); + MessageBuilder buffer = builder().strong("--- "); append(buffer, event.getMojoExecution()); append(buffer, event.getProject()); buffer.strong(" ---"); @@ -389,7 +389,7 @@ public void forkStarted(ExecutionEvent event) { if (logger.isInfoEnabled()) { logger.info(""); - MessageBuilder buffer = buffer().strong(">>> "); + MessageBuilder buffer = builder().strong(">>> "); append(buffer, event.getMojoExecution()); buffer.strong(" > "); appendForkInfo(buffer, event.getMojoExecution().getMojoDescriptor()); @@ -411,7 +411,7 @@ public void forkSucceeded(ExecutionEvent event) { if (logger.isInfoEnabled()) { logger.info(""); - MessageBuilder buffer = buffer().strong("<<< "); + MessageBuilder buffer = builder().strong("<<< "); append(buffer, event.getMojoExecution()); buffer.strong(" < "); appendForkInfo(buffer, event.getMojoExecution().getMojoDescriptor()); diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/jansi/JansiMessageBuilder.java b/maven-embedder/src/main/java/org/apache/maven/cli/jansi/JansiMessageBuilder.java new file mode 100644 index 0000000000..08a28ae911 --- /dev/null +++ b/maven-embedder/src/main/java/org/apache/maven/cli/jansi/JansiMessageBuilder.java @@ -0,0 +1,156 @@ +/* + * 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.cli.jansi; + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.MessageBuilder; +import org.fusesource.jansi.Ansi; + +@Experimental +public class JansiMessageBuilder implements MessageBuilder { + private final Ansi ansi; + + public JansiMessageBuilder() { + this.ansi = Ansi.ansi(); + } + + public JansiMessageBuilder(StringBuilder sb) { + this.ansi = Ansi.ansi(sb); + } + + @Override + @Nonnull + public MessageBuilder debug(Object o) { + return style(Style.DEBUG, o); + } + + @Override + @Nonnull + public MessageBuilder info(Object o) { + return style(Style.INFO, o); + } + + @Override + @Nonnull + public MessageBuilder warning(Object o) { + return style(Style.WARNING, o); + } + + @Override + @Nonnull + public MessageBuilder error(Object o) { + return style(Style.ERROR, o); + } + + @Override + @Nonnull + public MessageBuilder success(Object o) { + return style(Style.SUCCESS, o); + } + + @Override + @Nonnull + public MessageBuilder failure(Object o) { + return style(Style.FAILURE, o); + } + + @Override + @Nonnull + public MessageBuilder strong(Object o) { + return style(Style.STRONG, o); + } + + @Override + @Nonnull + public MessageBuilder mojo(Object o) { + return style(Style.MOJO, o); + } + + @Override + @Nonnull + public MessageBuilder project(Object o) { + return style(Style.PROJECT, o); + } + + private MessageBuilder style(Style style, Object o) { + style.apply(ansi).a(o).reset(); + return this; + } + + @Override + @Nonnull + public MessageBuilder a(char[] chars, int i, int i1) { + ansi.a(chars, i, i1); + return this; + } + + @Override + @Nonnull + public MessageBuilder a(char[] chars) { + ansi.a(chars); + return this; + } + + @Override + @Nonnull + public MessageBuilder a(CharSequence charSequence, int i, int i1) { + ansi.a(charSequence, i, i1); + return this; + } + + @Override + @Nonnull + public MessageBuilder a(CharSequence charSequence) { + ansi.a(charSequence); + return this; + } + + @Override + @Nonnull + public MessageBuilder a(Object o) { + ansi.a(o); + return this; + } + + @Override + @Nonnull + public MessageBuilder newline() { + ansi.newline(); + return this; + } + + @Override + @Nonnull + public MessageBuilder format(String s, Object... objects) { + ansi.format(s, objects); + return this; + } + + @Override + @Nonnull + public String build() { + return ansi.toString(); + } + + @Override + public String toString() { + return build(); + } +} diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/jansi/JansiMessageBuilderFactory.java b/maven-embedder/src/main/java/org/apache/maven/cli/jansi/JansiMessageBuilderFactory.java new file mode 100644 index 0000000000..c7d3225183 --- /dev/null +++ b/maven-embedder/src/main/java/org/apache/maven/cli/jansi/JansiMessageBuilderFactory.java @@ -0,0 +1,55 @@ +/* + * 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.cli.jansi; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.MessageBuilder; +import org.apache.maven.api.services.MessageBuilderFactory; + +@Experimental +@Named +@Singleton +public class JansiMessageBuilderFactory implements MessageBuilderFactory { + + @Override + public boolean isColorEnabled() { + return MessageUtils.isColorEnabled(); + } + + @Override + public int getTerminalWidth() { + return MessageUtils.getTerminalWidth(); + } + + @Override + @Nonnull + public MessageBuilder builder() { + return builder(new StringBuilder()); + } + + @Override + @Nonnull + public MessageBuilder builder(@Nonnull StringBuilder stringBuilder) { + return MessageUtils.builder(stringBuilder); + } +} diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/jansi/MessageUtils.java b/maven-embedder/src/main/java/org/apache/maven/cli/jansi/MessageUtils.java new file mode 100644 index 0000000000..379e1e00e3 --- /dev/null +++ b/maven-embedder/src/main/java/org/apache/maven/cli/jansi/MessageUtils.java @@ -0,0 +1,193 @@ +/* + * 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.cli.jansi; + +import org.apache.maven.api.services.MessageBuilder; +import org.apache.maven.internal.impl.DefaultMessageBuilder; +import org.fusesource.jansi.Ansi; +import org.fusesource.jansi.AnsiConsole; +import org.fusesource.jansi.AnsiMode; + +/** + * Colored message utils, to manage colors consistently across plugins (only if Maven version is at least 3.5.0). + * For Maven version before 3.5.0, message built with this util will never add color. + *

+ * Internally, Jansi is used to render + * ANSI colors on any platform. + * @since 3.1.0 + */ +public class MessageUtils { + private static final boolean JANSI; + + /** Reference to the JVM shutdown hook, if registered */ + private static Thread shutdownHook; + + /** Synchronization monitor for the "uninstall" */ + private static final Object STARTUP_SHUTDOWN_MONITOR = new Object(); + + static { + boolean jansi = true; + try { + // Jansi is provided by Maven core since 3.5.0 + Class.forName("org.fusesource.jansi.Ansi"); + } catch (ClassNotFoundException cnfe) { + jansi = false; + } + JANSI = jansi; + } + + /** + * Install color support. + * This method is called by Maven core, and calling it is not necessary in plugins. + */ + public static void systemInstall() { + if (JANSI) { + AnsiConsole.systemInstall(); + } + } + + /** + * Undo a previous {@link #systemInstall()}. If {@link #systemInstall()} was called + * multiple times, {@link #systemUninstall()} must be called call the same number of times before + * it is actually uninstalled. + */ + public static void systemUninstall() { + synchronized (STARTUP_SHUTDOWN_MONITOR) { + doSystemUninstall(); + + // hook can only set when Jansi is true + if (shutdownHook != null) { + try { + Runtime.getRuntime().removeShutdownHook(shutdownHook); + } catch (IllegalStateException ex) { + // ignore - VM is already shutting down + } + } + } + } + + private static void doSystemUninstall() { + if (JANSI) { + AnsiConsole.systemUninstall(); + } + } + + /** + * Enables message color (if Jansi is available). + * @param flag to enable Jansi + */ + public static void setColorEnabled(boolean flag) { + if (JANSI) { + AnsiConsole.out().setMode(flag ? AnsiMode.Force : AnsiMode.Strip); + Ansi.setEnabled(flag); + System.setProperty( + AnsiConsole.JANSI_MODE, flag ? AnsiConsole.JANSI_MODE_FORCE : AnsiConsole.JANSI_MODE_STRIP); + boolean installed = AnsiConsole.isInstalled(); + while (AnsiConsole.isInstalled()) { + AnsiConsole.systemUninstall(); + } + if (installed) { + AnsiConsole.systemInstall(); + } + } + } + + /** + * Is message color enabled: requires Jansi available (through Maven) and the color has not been disabled. + * @return whether colored messages are enabled + */ + public static boolean isColorEnabled() { + return JANSI ? Ansi.isEnabled() : false; + } + + /** + * Create a default message buffer. + * @return a new buffer + */ + public static MessageBuilder builder() { + return builder(new StringBuilder()); + } + + /** + * Create a message buffer with an internal buffer of defined size. + * @param size size of the buffer + * @return a new buffer + */ + public static MessageBuilder builder(int size) { + return builder(new StringBuilder(size)); + } + + /** + * Create a message buffer with defined String builder. + * @param builder initial content of the message buffer + * @return a new buffer + */ + public static MessageBuilder builder(StringBuilder builder) { + return JANSI && isColorEnabled() ? new JansiMessageBuilder(builder) : new DefaultMessageBuilder(builder); + } + + /** + * Remove any ANSI code from a message (colors or other escape sequences). + * @param msg message eventually containing ANSI codes + * @return the message with ANSI codes removed + */ + public static String stripAnsiCodes(String msg) { + return msg.replaceAll("\u001B\\[[;\\d]*[ -/]*[@-~]", ""); + } + + /** + * Register a shutdown hook with the JVM runtime, uninstalling Ansi support on + * JVM shutdown unless is has already been uninstalled at that time. + *

Delegates to {@link #doSystemUninstall()} for the actual uninstall procedure + * + * @see Runtime#addShutdownHook(Thread) + * @see MessageUtils#systemUninstall() + * @see #doSystemUninstall() + */ + public static void registerShutdownHook() { + if (JANSI && shutdownHook == null) { + // No shutdown hook registered yet. + shutdownHook = new Thread() { + @Override + public void run() { + synchronized (STARTUP_SHUTDOWN_MONITOR) { + while (AnsiConsole.isInstalled()) { + doSystemUninstall(); + } + } + } + }; + Runtime.getRuntime().addShutdownHook(shutdownHook); + } + } + + /** + * Get the terminal width or -1 if the width cannot be determined. + * + * @return the terminal width + */ + public static int getTerminalWidth() { + if (JANSI) { + int width = AnsiConsole.getTerminalWidth(); + return width > 0 ? width : -1; + } else { + return -1; + } + } +} diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/jansi/Style.java b/maven-embedder/src/main/java/org/apache/maven/cli/jansi/Style.java new file mode 100644 index 0000000000..194bf64b55 --- /dev/null +++ b/maven-embedder/src/main/java/org/apache/maven/cli/jansi/Style.java @@ -0,0 +1,147 @@ +/* + * 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.cli.jansi; + +import java.util.Locale; + +import org.fusesource.jansi.Ansi; +import org.fusesource.jansi.Ansi.Color; + +/** + * Configurable message styles. + * @since 3.1.0 + */ +enum Style { + DEBUG("bold,cyan"), + INFO("bold,blue"), + WARNING("bold,yellow"), + ERROR("bold,red"), + SUCCESS("bold,green"), + FAILURE("bold,red"), + STRONG("bold"), + MOJO("green"), + PROJECT("cyan"); + + private final boolean bold; + + private final boolean bright; + + private final Color color; + + private final boolean bgBright; + + private final Color bgColor; + + Style(String defaultValue) { + boolean currentBold = false; + boolean currentBright = false; + Color currentColor = null; + boolean currentBgBright = false; + Color currentBgColor = null; + + String value = System.getProperty("style." + name().toLowerCase(Locale.ENGLISH), defaultValue) + .toLowerCase(Locale.ENGLISH); + + for (String token : value.split(",")) { + if ("bold".equals(token)) { + currentBold = true; + } else if (token.startsWith("bg")) { + token = token.substring(2); + if (token.startsWith("bright")) { + currentBgBright = true; + token = token.substring(6); + } + currentBgColor = toColor(token); + } else { + if (token.startsWith("bright")) { + currentBright = true; + token = token.substring(6); + } + currentColor = toColor(token); + } + } + + this.bold = currentBold; + this.bright = currentBright; + this.color = currentColor; + this.bgBright = currentBgBright; + this.bgColor = currentBgColor; + } + + private static Color toColor(String token) { + for (Color color : Color.values()) { + if (color.toString().equalsIgnoreCase(token)) { + return color; + } + } + return null; + } + + Ansi apply(Ansi ansi) { + if (bold) { + ansi.bold(); + } + if (color != null) { + if (bright) { + ansi.fgBright(color); + } else { + ansi.fg(color); + } + } + if (bgColor != null) { + if (bgBright) { + ansi.bgBright(bgColor); + } else { + ansi.bg(bgColor); + } + } + return ansi; + } + + @Override + public String toString() { + if (!bold && color == null && bgColor == null) { + return name(); + } + StringBuilder sb = new StringBuilder(name() + '='); + if (bold) { + sb.append("bold"); + } + if (color != null) { + if (sb.length() > 0) { + sb.append(','); + } + if (bright) { + sb.append("bright"); + } + sb.append(color.name()); + } + if (bgColor != null) { + if (sb.length() > 0) { + sb.append(','); + } + sb.append("bg"); + if (bgBright) { + sb.append("bright"); + } + sb.append(bgColor.name()); + } + return sb.toString(); + } +} diff --git a/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java b/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java index 7ba238dbc1..a68976bb37 100644 --- a/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java +++ b/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java @@ -35,6 +35,7 @@ import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.maven.Maven; +import org.apache.maven.cli.jansi.MessageUtils; import org.apache.maven.cli.transfer.ConsoleMavenTransferListener; import org.apache.maven.cli.transfer.QuietMavenTransferListener; import org.apache.maven.cli.transfer.Slf4jMavenTransferListener; @@ -44,7 +45,6 @@ import org.apache.maven.execution.ProjectActivation; import org.apache.maven.model.root.DefaultRootLocator; import org.apache.maven.project.MavenProject; -import org.apache.maven.shared.utils.logging.MessageUtils; import org.apache.maven.toolchain.building.ToolchainsBuildingRequest; import org.apache.maven.toolchain.building.ToolchainsBuildingResult; import org.codehaus.plexus.DefaultPlexusContainer; diff --git a/maven-embedder/src/test/java/org/apache/maven/cli/event/ExecutionEventLoggerTest.java b/maven-embedder/src/test/java/org/apache/maven/cli/event/ExecutionEventLoggerTest.java index 59b8dc282a..3e260124b5 100644 --- a/maven-embedder/src/test/java/org/apache/maven/cli/event/ExecutionEventLoggerTest.java +++ b/maven-embedder/src/test/java/org/apache/maven/cli/event/ExecutionEventLoggerTest.java @@ -22,10 +22,11 @@ import com.google.common.collect.ImmutableList; import org.apache.commons.io.FilenameUtils; +import org.apache.maven.cli.jansi.JansiMessageBuilderFactory; +import org.apache.maven.cli.jansi.MessageUtils; import org.apache.maven.execution.ExecutionEvent; import org.apache.maven.execution.MavenSession; import org.apache.maven.project.MavenProject; -import org.apache.maven.shared.utils.logging.MessageUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -44,6 +45,7 @@ class ExecutionEventLoggerTest { private Logger logger; private ExecutionEventLogger executionEventLogger; + private JansiMessageBuilderFactory messageBuilderFactory = new JansiMessageBuilderFactory(); @BeforeAll static void setUp() { @@ -59,7 +61,7 @@ static void tearDown() { void beforeEach() { logger = mock(Logger.class); when(logger.isInfoEnabled()).thenReturn(true); - executionEventLogger = new ExecutionEventLogger(logger); + executionEventLogger = new ExecutionEventLogger(messageBuilderFactory, logger); } @Test @@ -143,25 +145,25 @@ void testTerminalWidth() { when(event.getProject()).thenReturn(project); // default width - new ExecutionEventLogger(logger, -1).projectStarted(event); + new ExecutionEventLogger(messageBuilderFactory, logger, -1).projectStarted(event); Mockito.verify(logger).info("----------------------------[ maven-plugin ]----------------------------"); // terminal width: 30 - new ExecutionEventLogger(logger, 30).projectStarted(event); + new ExecutionEventLogger(messageBuilderFactory, logger, 30).projectStarted(event); Mockito.verify(logger).info("------------------[ maven-plugin ]------------------"); // terminal width: 70 - new ExecutionEventLogger(logger, 70).projectStarted(event); + new ExecutionEventLogger(messageBuilderFactory, logger, 70).projectStarted(event); Mockito.verify(logger).info("-----------------------[ maven-plugin ]-----------------------"); // terminal width: 110 - new ExecutionEventLogger(logger, 110).projectStarted(event); + new ExecutionEventLogger(messageBuilderFactory, logger, 110).projectStarted(event); Mockito.verify(logger) .info( "-------------------------------------------[ maven-plugin ]-------------------------------------------"); // terminal width: 200 - new ExecutionEventLogger(logger, 200).projectStarted(event); + new ExecutionEventLogger(messageBuilderFactory, logger, 200).projectStarted(event); Mockito.verify(logger) .info( "-----------------------------------------------------[ maven-plugin ]-----------------------------------------------------"); diff --git a/maven-slf4j-provider/pom.xml b/maven-slf4j-provider/pom.xml index 5721c27316..dcc964f387 100644 --- a/maven-slf4j-provider/pom.xml +++ b/maven-slf4j-provider/pom.xml @@ -38,12 +38,16 @@ under the License. slf4j-api - org.apache.maven.shared - maven-shared-utils + org.apache.maven + maven-slf4j-wrapper org.apache.maven - maven-slf4j-wrapper + maven-api-core + + + org.apache.maven + maven-embedder diff --git a/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLogger.java b/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLogger.java index 7ab8eabfc6..ff7c1ccd21 100644 --- a/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLogger.java +++ b/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLogger.java @@ -20,8 +20,8 @@ import java.io.PrintStream; -import static org.apache.maven.shared.utils.logging.MessageUtils.buffer; -import static org.apache.maven.shared.utils.logging.MessageUtils.level; +import org.apache.maven.api.services.MessageBuilder; +import org.apache.maven.cli.jansi.MessageUtils; /** * Logger for Maven, that support colorization of levels and stacktraces. This class implements 2 methods introduced in @@ -38,16 +38,16 @@ public class MavenSimpleLogger extends SimpleLogger { protected String renderLevel(int level) { switch (level) { case LOG_LEVEL_TRACE: - return level().debug("TRACE"); + return builder().debug("TRACE").build(); case LOG_LEVEL_DEBUG: - return level().debug("DEBUG"); + return builder().debug("DEBUG").build(); case LOG_LEVEL_INFO: - return level().info("INFO"); + return builder().info("INFO").build(); case LOG_LEVEL_WARN: - return level().warning("WARNING"); + return builder().warning("WARNING").build(); case LOG_LEVEL_ERROR: default: - return level().error("ERROR"); + return builder().error("ERROR").build(); } } @@ -56,10 +56,10 @@ protected void writeThrowable(Throwable t, PrintStream stream) { if (t == null) { return; } - stream.print(buffer().failure(t.getClass().getName())); + stream.print(builder().failure(t.getClass().getName())); if (t.getMessage() != null) { stream.print(": "); - stream.print(buffer().failure(t.getMessage())); + stream.print(builder().failure(t.getMessage())); } stream.println(); @@ -70,9 +70,9 @@ private void printStackTrace(Throwable t, PrintStream stream, String prefix) { for (StackTraceElement e : t.getStackTrace()) { stream.print(prefix); stream.print(" "); - stream.print(buffer().strong("at")); + stream.print(builder().strong("at")); stream.print(" " + e.getClassName() + "." + e.getMethodName()); - stream.print(buffer().a(" (").strong(getLocation(e)).a(")")); + stream.print(builder().a(" (").strong(getLocation(e)).a(")")); stream.println(); } for (Throwable se : t.getSuppressed()) { @@ -85,10 +85,10 @@ private void printStackTrace(Throwable t, PrintStream stream, String prefix) { } private void writeThrowable(Throwable t, PrintStream stream, String caption, String prefix) { - stream.print(buffer().a(prefix).strong(caption).a(": ").a(t.getClass().getName())); + stream.print(builder().a(prefix).strong(caption).a(": ").a(t.getClass().getName())); if (t.getMessage() != null) { stream.print(": "); - stream.print(buffer().failure(t.getMessage())); + stream.print(builder().failure(t.getMessage())); } stream.println(); @@ -108,4 +108,8 @@ protected String getLocation(final StackTraceElement e) { return e.getFileName(); } } + + private MessageBuilder builder() { + return MessageUtils.builder(); + } } diff --git a/pom.xml b/pom.xml index ae4ce0a908..a095ac8957 100644 --- a/pom.xml +++ b/pom.xml @@ -299,18 +299,6 @@ under the License. plexus-interpolation ${plexusInterpolationVersion} - - org.apache.maven.shared - maven-shared-utils - 3.3.4 - - - - commons-io - commons-io - - - org.fusesource.jansi jansi