[MSHARED-562] new improved styled message API, avoiding chicken and egg issue with Maven core

git-svn-id: https://svn.apache.org/repos/asf/maven/shared/trunk@1750590 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index fafb5e5..5921cff 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,6 +62,12 @@
 
   <dependencies>
     <dependency>
+      <groupId>org.fusesource.jansi</groupId>
+      <artifactId>jansi</artifactId>
+      <version>1.13</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>4.11</version>
diff --git a/src/main/java/org/apache/maven/shared/utils/logging/AnsiMessageBuffer.java b/src/main/java/org/apache/maven/shared/utils/logging/AnsiMessageBuffer.java
new file mode 100644
index 0000000..11ae124
--- /dev/null
+++ b/src/main/java/org/apache/maven/shared/utils/logging/AnsiMessageBuffer.java
@@ -0,0 +1,189 @@
+package org.apache.maven.shared.utils.logging;
+
+/*
+ * 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.
+ */
+
+import org.fusesource.jansi.Ansi;
+
+/**
+ * Message buffer implementation that supports ANSI colors through JAnsi.
+ */
+class AnsiMessageBuffer
+    implements MessageBuffer
+{
+    private Ansi ansi;
+
+    AnsiMessageBuffer()
+    {
+        ansi = Ansi.ansi();
+    }
+
+    AnsiMessageBuffer( StringBuilder builder )
+    {
+        ansi = Ansi.ansi( builder );
+    }
+
+    AnsiMessageBuffer( int size )
+    {
+        ansi = Ansi.ansi( size );
+    }
+
+    // consistent color management
+    // TODO make configurable
+    // settings.xml? during systemInstall(Settings)?
+    // or project properties (that can be injected by settings)?
+    //
+    public AnsiMessageBuffer debug()
+    {
+        ansi.bold().fgCyan();
+        return this;
+    }
+    
+    public AnsiMessageBuffer info()
+    {
+        ansi.bold().fgBlue();
+        return this;
+    }
+    
+    public AnsiMessageBuffer warning()
+    {
+        ansi.bold().fgYellow();
+        return this;
+    }
+    
+    public AnsiMessageBuffer warning( Object message )
+    {
+        return warning().a( message ).reset();
+    }
+    
+    public AnsiMessageBuffer error()
+    {
+        ansi.bold().fgRed();
+        return this;
+    }
+
+    public AnsiMessageBuffer success()
+    {
+        ansi.bold().fgGreen();
+        return this;
+    }
+
+    public AnsiMessageBuffer success( Object message )
+    {
+        return success().a( message ).reset();
+    }
+
+    public AnsiMessageBuffer failure()
+    {
+        ansi.bold().fgRed();
+        return this;
+    }
+
+    public AnsiMessageBuffer failure( Object message )
+    {
+        return failure().a( message ).reset();
+    }
+
+    public AnsiMessageBuffer strong()
+    {
+        ansi.bold();
+        return this;
+    }
+
+    public AnsiMessageBuffer strong( Object message )
+    {
+        return strong().a( message ).reset();
+    }
+
+    public AnsiMessageBuffer mojo()
+    {
+        ansi.fgGreen();
+        return this;
+    }
+
+    public AnsiMessageBuffer mojo( Object message )
+    {
+        return mojo().a( message ).reset();
+    }
+    
+
+    public AnsiMessageBuffer project()
+    {
+        ansi.fgCyan();
+        return this;
+    }
+
+    public AnsiMessageBuffer project( Object message )
+    {
+        return project().a( message ).reset();
+    }
+    public AnsiMessageBuffer reset()
+    {
+        ansi.reset();
+        return this;
+    }
+
+    public AnsiMessageBuffer a( char[] value, int offset, int len )
+    {
+        ansi.a( value, offset, len );
+        return this;
+    }
+
+    public AnsiMessageBuffer a( char[] value )
+    {
+        ansi.a( value );
+        return this;
+    }
+
+    public AnsiMessageBuffer a( CharSequence value, int start, int end )
+    {
+        ansi.a( value, start, end );
+        return this;
+    }
+
+    public AnsiMessageBuffer a( CharSequence value )
+    {
+        ansi.a( value );
+        return this;
+    }
+
+    public AnsiMessageBuffer a( Object value )
+    {
+        ansi.a( value );
+        return this;
+    }
+
+    public AnsiMessageBuffer newline()
+    {
+        ansi.newline();
+        return this;
+    }
+
+    public AnsiMessageBuffer format( String pattern, Object... args )
+    {
+        ansi.format( pattern, args );
+        return this;
+    }
+
+    @Override
+    public String toString()
+    {
+        return ansi.toString();
+    }
+}
diff --git a/src/main/java/org/apache/maven/shared/utils/logging/MessageBuffer.java b/src/main/java/org/apache/maven/shared/utils/logging/MessageBuffer.java
new file mode 100644
index 0000000..58283cf
--- /dev/null
+++ b/src/main/java/org/apache/maven/shared/utils/logging/MessageBuffer.java
@@ -0,0 +1,130 @@
+package org.apache.maven.shared.utils.logging;
+
+/*
+ * 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.
+ */
+
+/**
+ * Message buffer that supports configurable styling.
+ * @see MessageUtils
+ */
+public interface MessageBuffer
+{
+    /**
+     * Insert color for DEBUG level display.
+     * By default, bold cyan
+     */
+    MessageBuffer debug();
+    
+    /**
+     * Insert color for INFO level display.
+     * By default, bold blue
+     */
+    MessageBuffer info();
+    
+    /**
+     * Insert color for WARNING level or warning message display.
+     * By default, bold yellow
+     */
+    MessageBuffer warning();
+    
+    /**
+     * Append warning message: equivalent to appending warning color, then message, then reset.
+     */
+    MessageBuffer warning( Object message );
+    
+    /**
+     * Insert color for ERROR level display.
+     * By default, bold red
+     */
+    MessageBuffer error();
+    
+    /**
+     * Insert color for success message display.
+     * By default, bold green
+     */
+    MessageBuffer success();
+    
+    /**
+     * Append success message: equivalent to appending success color, then message, then reset.
+     */
+    MessageBuffer success( Object message );
+    
+    /**
+     * Insert color for failure message display.
+     * By default, bold red
+     */
+    MessageBuffer failure();
+
+    /**
+     * Append failure message: equivalent to appending failure color, then message, then reset.
+     */
+    MessageBuffer failure( Object message );
+    
+    /**
+     * Insert color for strong message display.
+     * By default, bold
+     */
+    MessageBuffer strong();
+
+    /**
+     * Append strong message: equivalent to appending strong color, then message, then reset.
+     */
+    MessageBuffer strong( Object message );
+    
+    /**
+     * Insert color for mojo message display.
+     * By default, green
+     */
+    MessageBuffer mojo();
+
+    /**
+     * Append mojo message: equivalent to appending mojo color, then message, then reset.
+     */
+    MessageBuffer mojo( Object message );
+    
+    /**
+     * Insert color for project message display.
+     * By default, cyan
+     */
+    MessageBuffer project();
+
+    /**
+     * Append project message: equivalent to appending project color, then message, then reset.
+     */
+    MessageBuffer project( Object message );
+    
+    //
+    // message building methods (modelled after Ansi methods)
+    //
+    MessageBuffer reset();
+
+    MessageBuffer a( char[] value, int offset, int len );
+
+    MessageBuffer a( char[] value );
+
+    MessageBuffer a( CharSequence value, int start, int end );
+
+    MessageBuffer a( CharSequence value );
+
+    MessageBuffer a( Object value );
+
+    MessageBuffer newline();
+
+    MessageBuffer format( String pattern, Object... args );
+}
diff --git a/src/main/java/org/apache/maven/shared/utils/logging/MessageUtils.java b/src/main/java/org/apache/maven/shared/utils/logging/MessageUtils.java
new file mode 100644
index 0000000..b273c83
--- /dev/null
+++ b/src/main/java/org/apache/maven/shared/utils/logging/MessageUtils.java
@@ -0,0 +1,90 @@
+package org.apache.maven.shared.utils.logging;
+
+/*
+ * 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.
+ */
+
+import org.fusesource.jansi.Ansi;
+import org.fusesource.jansi.AnsiConsole;
+
+/**
+ * Colored message utils, to manage colors colors consistently across plugins (only if Maven version is at least 3.4).
+ */
+public class MessageUtils
+{
+    private static final boolean JANSI;
+
+    static
+    {
+        boolean jansi = true;
+        try
+        {
+            // JAnsi is provided by Maven core since 3.4.0
+            Class.forName( "org.fusesource.jansi.Ansi" );
+        }
+        catch ( ClassNotFoundException cnfe )
+        {
+            jansi = false;
+        }
+        JANSI = jansi;
+    }
+
+    public static void systemInstall()
+    {
+        if ( JANSI )
+        {
+            AnsiConsole.systemInstall();
+        }
+    }
+
+    public static void systemUninstall()
+    {
+        if ( JANSI )
+        {
+            AnsiConsole.systemUninstall();
+        }
+    }
+
+    public static void setColor( boolean flag )
+    {
+        if ( JANSI )
+        {
+            Ansi.setEnabled( flag );
+        }
+    }
+
+    public static boolean isColor()
+    {
+        return JANSI ? Ansi.isEnabled() : false;
+    }
+
+    public static MessageBuffer buffer()
+    {
+        return JANSI ? new AnsiMessageBuffer() : new PlainMessageBuffer();
+    }
+
+    public static MessageBuffer buffer( StringBuilder builder )
+    {
+        return JANSI ? new AnsiMessageBuffer( builder ) : new PlainMessageBuffer( builder );
+    }
+
+    public static MessageBuffer buffer( int size )
+    {
+        return JANSI ? new AnsiMessageBuffer( size ) : new PlainMessageBuffer( size );
+    }
+}
diff --git a/src/main/java/org/apache/maven/shared/utils/logging/PlainMessageBuffer.java b/src/main/java/org/apache/maven/shared/utils/logging/PlainMessageBuffer.java
new file mode 100644
index 0000000..7dadc41
--- /dev/null
+++ b/src/main/java/org/apache/maven/shared/utils/logging/PlainMessageBuffer.java
@@ -0,0 +1,172 @@
+package org.apache.maven.shared.utils.logging;
+
+/*
+ * 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.
+ */
+
+/**
+ * Message buffer implementation that just ignores styling, for Maven version earlier than 3.4.0.
+ */
+class PlainMessageBuffer
+    implements MessageBuffer
+{
+    private StringBuilder buffer;
+
+    PlainMessageBuffer()
+    {
+        buffer = new StringBuilder();
+    }
+
+    PlainMessageBuffer( StringBuilder builder )
+    {
+        buffer = builder;
+    }
+
+    PlainMessageBuffer( int size )
+    {
+        buffer = new StringBuilder( size );
+    }
+
+    public PlainMessageBuffer debug()
+    {
+        return this;
+    }
+    
+    public PlainMessageBuffer info()
+    {
+        return this;
+    }
+    
+    public PlainMessageBuffer warning()
+    {
+        return this;
+    }
+    
+    public PlainMessageBuffer warning( Object message )
+    {
+        return a( message );
+    }
+    
+    public PlainMessageBuffer error()
+    {
+        return this;
+    }
+
+    public PlainMessageBuffer success()
+    {
+        return this;
+    }
+
+    public PlainMessageBuffer success( Object message )
+    {
+        return a( message );
+    }
+
+    public PlainMessageBuffer failure()
+    {
+        return this;
+    }
+
+    public PlainMessageBuffer failure( Object message )
+    {
+        return a( message );
+    }
+
+    public PlainMessageBuffer strong()
+    {
+        return this;
+    }
+
+    public PlainMessageBuffer strong( Object message )
+    {
+        return a( message );
+    }
+
+    public PlainMessageBuffer mojo()
+    {
+        return this;
+    }
+
+    public PlainMessageBuffer mojo( Object message )
+    {
+        return a( message );
+    }
+
+    public PlainMessageBuffer project()
+    {
+        return this;
+    }
+
+    public PlainMessageBuffer project( Object message )
+    {
+        return a( message );
+    }
+
+    public PlainMessageBuffer reset()
+    {
+        return this;
+    }
+
+    public PlainMessageBuffer a( char[] value, int offset, int len )
+    {
+        buffer.append( value, offset, len );
+        return this;
+    }
+
+    public PlainMessageBuffer a( char[] value )
+    {
+        buffer.append( value );
+        return this;
+    }
+
+    public PlainMessageBuffer a( CharSequence value, int start, int end )
+    {
+        buffer.append( value, start, end );
+        return this;
+    }
+
+    public PlainMessageBuffer a( CharSequence value )
+    {
+        buffer.append( value );
+        return this;
+    }
+
+    public PlainMessageBuffer a( Object value )
+    {
+        buffer.append( value );
+        return this;
+    }
+
+    public PlainMessageBuffer newline()
+    {
+        buffer.append( System.getProperty( "line.separator" ) );
+        return this;
+    }
+
+    public PlainMessageBuffer format( String pattern, Object... args )
+    {
+        buffer.append( String.format( pattern, args ) );
+        return this;
+    }
+
+    @Override
+    public String toString()
+    {
+        return buffer.toString();
+    }
+}