You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ti...@apache.org on 2016/09/16 22:55:02 UTC

[1/5] maven-surefire git commit: [SUREFIRE-1254] add color messages

Repository: maven-surefire
Updated Branches:
  refs/heads/master 2c9edf062 -> 6a79127ab


http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategiesTest.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategiesTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategiesTest.java
index a47030c..98c3721 100644
--- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategiesTest.java
+++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategiesTest.java
@@ -19,14 +19,15 @@ package org.apache.maven.surefire.junitcore.pc;
  * under the License.
  */
 
-import org.apache.maven.surefire.junitcore.Logger;
-import org.apache.maven.surefire.util.internal.DaemonThreadFactory;
+import org.apache.maven.surefire.report.ConsoleStream;
+import org.apache.maven.surefire.report.DefaultDirectConsoleReporter;
 import org.junit.Test;
 
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;
 
+import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThreadFactory;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -46,13 +47,14 @@ import static org.junit.Assert.assertTrue;
  */
 public class SchedulingStrategiesTest
 {
-    private static final ThreadFactory DAEMON_THREAD_FACTORY = DaemonThreadFactory.newDaemonThreadFactory();
+    private static final ThreadFactory DAEMON_THREAD_FACTORY = newDaemonThreadFactory();
+    private final ConsoleStream logger = new DefaultDirectConsoleReporter( System.out );
 
     @Test
     public void invokerStrategy()
         throws InterruptedException
     {
-        SchedulingStrategy strategy = SchedulingStrategies.createInvokerStrategy( new Logger() );
+        SchedulingStrategy strategy = SchedulingStrategies.createInvokerStrategy( logger );
         assertFalse( strategy.hasSharedThreadPool() );
         assertTrue( strategy.canSchedule() );
 
@@ -72,7 +74,7 @@ public class SchedulingStrategiesTest
     public void nonSharedPoolStrategy()
         throws InterruptedException
     {
-        SchedulingStrategy strategy = SchedulingStrategies.createParallelStrategy( new Logger(),  2 );
+        SchedulingStrategy strategy = SchedulingStrategies.createParallelStrategy( logger,  2 );
         assertFalse( strategy.hasSharedThreadPool() );
         assertTrue( strategy.canSchedule() );
 
@@ -94,7 +96,7 @@ public class SchedulingStrategiesTest
     @Test(expected = NullPointerException.class)
     public void sharedPoolStrategyNullPool()
     {
-        SchedulingStrategies.createParallelSharedStrategy( new Logger(), null );
+        SchedulingStrategies.createParallelSharedStrategy( logger, null );
     }
 
     @Test
@@ -103,11 +105,11 @@ public class SchedulingStrategiesTest
     {
         ExecutorService sharedPool = Executors.newCachedThreadPool( DAEMON_THREAD_FACTORY );
 
-        SchedulingStrategy strategy1 = SchedulingStrategies.createParallelSharedStrategy( new Logger(), sharedPool );
+        SchedulingStrategy strategy1 = SchedulingStrategies.createParallelSharedStrategy( logger, sharedPool );
         assertTrue( strategy1.hasSharedThreadPool() );
         assertTrue( strategy1.canSchedule() );
 
-        SchedulingStrategy strategy2 = SchedulingStrategies.createParallelSharedStrategy( new Logger(), sharedPool );
+        SchedulingStrategy strategy2 = SchedulingStrategies.createParallelSharedStrategy( logger, sharedPool );
         assertTrue( strategy2.hasSharedThreadPool() );
         assertTrue( strategy2.canSchedule() );
 
@@ -140,7 +142,7 @@ public class SchedulingStrategiesTest
     public void infinitePoolStrategy()
         throws InterruptedException
     {
-        SchedulingStrategy strategy = SchedulingStrategies.createParallelStrategyUnbounded( new Logger() );
+        SchedulingStrategy strategy = SchedulingStrategies.createParallelStrategyUnbounded( logger );
         assertFalse( strategy.hasSharedThreadPool() );
         assertTrue( strategy.canSchedule() );
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-report-parser/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-report-parser/pom.xml b/surefire-report-parser/pom.xml
index 9f418f5..33c535f 100644
--- a/surefire-report-parser/pom.xml
+++ b/surefire-report-parser/pom.xml
@@ -38,6 +38,10 @@
 
   <dependencies>
     <dependency>
+      <groupId>org.apache.maven.surefire</groupId>
+      <artifactId>surefire-logger-api</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.apache.maven.shared</groupId>
       <artifactId>maven-shared-utils</artifactId>
     </dependency>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportParser.java
----------------------------------------------------------------------
diff --git a/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportParser.java b/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportParser.java
index 0c9bdbd..62240e5 100644
--- a/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportParser.java
+++ b/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportParser.java
@@ -24,7 +24,6 @@ import java.io.IOException;
 import java.text.NumberFormat;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
@@ -32,11 +31,14 @@ import java.util.Map;
 
 import javax.xml.parsers.ParserConfigurationException;
 
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.reporting.MavenReportException;
 import org.apache.maven.shared.utils.StringUtils;
 import org.apache.maven.shared.utils.io.DirectoryScanner;
 import org.xml.sax.SAXException;
 
+import static java.util.Collections.singletonList;
+
 /**
  *
  */
@@ -53,12 +55,15 @@ public final class SurefireReportParser
 
     private final NumberFormat numberFormat;
 
+    private final ConsoleLogger consoleLogger;
+
     private List<File> reportsDirectories;
 
-    public SurefireReportParser( List<File> reportsDirectoriesFiles, Locale locale )
+    public SurefireReportParser( List<File> reportsDirectories, Locale locale, ConsoleLogger consoleLogger )
     {
-        reportsDirectories = reportsDirectoriesFiles;
+        this.reportsDirectories = reportsDirectories;
         numberFormat = NumberFormat.getInstance( locale );
+        this.consoleLogger = consoleLogger;
     }
 
     public List<ReportTestSuite> parseXMLReportFiles()
@@ -75,7 +80,7 @@ public final class SurefireReportParser
                 }
             }
         }
-        final TestSuiteXmlParser parser = new TestSuiteXmlParser();
+        final TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger );
         for ( File aXmlReportFileList : xmlReportFiles )
         {
             try
@@ -161,7 +166,7 @@ public final class SurefireReportParser
 
     public void setReportsDirectory( File reportsDirectory )
     {
-        reportsDirectories = Collections.singletonList( reportsDirectory );
+        reportsDirectories = singletonList( reportsDirectory );
     }
 
     public NumberFormat getNumberFormat()

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParser.java
----------------------------------------------------------------------
diff --git a/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParser.java b/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParser.java
index f027b29..c28b4b1 100644
--- a/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParser.java
+++ b/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParser.java
@@ -28,26 +28,30 @@ import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
 
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.shared.utils.StringUtils;
 import org.xml.sax.Attributes;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.DefaultHandler;
 
+import static java.util.Locale.ENGLISH;
+
 /**
  *
  */
 public final class TestSuiteXmlParser
     extends DefaultHandler
 {
-    private final NumberFormat numberFormat = NumberFormat.getInstance( Locale.ENGLISH );
+    private final NumberFormat numberFormat = NumberFormat.getInstance( ENGLISH );
+
+    private final ConsoleLogger consoleLogger;
 
     private ReportTestSuite defaultSuite;
 
@@ -63,6 +67,11 @@ public final class TestSuiteXmlParser
 
     private boolean valid;
 
+    public TestSuiteXmlParser( ConsoleLogger consoleLogger )
+    {
+        this.consoleLogger = consoleLogger;
+    }
+
     public List<ReportTestSuite> parse( String xmlPath )
         throws ParserConfigurationException, SAXException, IOException
     {
@@ -129,7 +138,7 @@ public final class TestSuiteXmlParser
                     }
                     catch ( NullPointerException e )
                     {
-                        System.err.println( "WARNING: no time attribute found on testsuite element" );
+                        consoleLogger.error( "WARNING: no time attribute found on testsuite element" );
                     }
 
                     final String name = attributes.getValue( "name" );

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportParserTest.java
----------------------------------------------------------------------
diff --git a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportParserTest.java b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportParserTest.java
index de25c4d..0fad166 100644
--- a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportParserTest.java
+++ b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportParserTest.java
@@ -26,12 +26,15 @@ import java.net.URLDecoder;
 import java.text.NumberFormat;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
+
+import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger;
 import org.apache.maven.reporting.MavenReportException;
 
 import junit.framework.TestCase;
 
+import static java.util.Locale.ENGLISH;
+
 /**
  *
  */
@@ -47,7 +50,7 @@ public class SurefireReportParserTest
         throws Exception
     {
         super.setUp();
-        report = new SurefireReportParser( null, Locale.ENGLISH );
+        report = new SurefireReportParser( null, ENGLISH, new NullConsoleLogger() );
     }
 
     public void testParseXMLReportFiles()

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParserTest.java
----------------------------------------------------------------------
diff --git a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParserTest.java b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParserTest.java
index da06451..6e0a325 100644
--- a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParserTest.java
+++ b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParserTest.java
@@ -23,14 +23,18 @@ import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 
 import static org.junit.Assert.*;
 import static org.junit.Assume.assumeTrue;
-import static org.hamcrest.CoreMatchers.*;
+import static org.hamcrest.Matchers.*;
 import static org.hamcrest.MatcherAssert.assertThat;
 
 /**
@@ -40,11 +44,56 @@ public class TestSuiteXmlParserTest
 {
     private static final String[] linePatterns = { "at org.apache.Test.", "at org.apache.Test$" };
 
+    private final Collection<String> loggedErrors = new ArrayList<String>();
+
+    private ConsoleLogger consoleLogger;
+
+    @Before
+    public void instantiateLogger()
+    {
+        consoleLogger = new ConsoleLogger()
+        {
+            public void debug( String message )
+            {
+            }
+
+            public void info( String message )
+            {
+            }
+
+            public void warning( String message )
+            {
+                loggedErrors.add( message );
+            }
+
+            public void error( String message )
+            {
+                loggedErrors.add( message );
+            }
+
+            public void error( String message, Throwable t )
+            {
+                loggedErrors.add( message );
+            }
+
+            public void error( Throwable t )
+            {
+                loggedErrors.add( t.getLocalizedMessage() );
+            }
+        };
+    }
+
+    @After
+    public void verifyErrorFreeLogger()
+    {
+        assertThat( loggedErrors, is( empty() ) );
+    }
+
     @Test
     public void testParse()
         throws Exception
     {
-        TestSuiteXmlParser testSuiteXmlParser = new TestSuiteXmlParser();
+        TestSuiteXmlParser testSuiteXmlParser = new TestSuiteXmlParser( consoleLogger );
         String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
             "<testsuite failures=\"4\" time=\"0.005\" errors=\"0\" skipped=\"0\" tests=\"4\" name=\"wellFormedXmlFailures.TestSurefire3\">\n"
             +
@@ -154,7 +203,7 @@ public class TestSuiteXmlParserTest
     public void testParser()
         throws Exception
     {
-        TestSuiteXmlParser parser = new TestSuiteXmlParser();
+        TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger );
 
         Collection<ReportTestSuite> oldResult = parser.parse(
             "src/test/resources/fixture/testsuitexmlparser/TEST-org.apache.maven.surefire.test.FailingTest.xml" );
@@ -170,7 +219,7 @@ public class TestSuiteXmlParserTest
     public void successfulSurefireTestReport()
         throws Exception
     {
-        TestSuiteXmlParser parser = new TestSuiteXmlParser();
+        TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger );
         File surefireReport = new File( "src/test/resources/junit-pathWith�mlaut/TEST-umlautTest.BasicTest.xml" );
         assumeTrue( surefireReport.isFile() );
         Collection<ReportTestSuite> suites = parser.parse( surefireReport.getCanonicalPath() );
@@ -203,7 +252,7 @@ public class TestSuiteXmlParserTest
     public void testParserHitsFailsafeSummary()
         throws Exception
     {
-        TestSuiteXmlParser parser = new TestSuiteXmlParser();
+        TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger );
 
         parser.parse( "src/test/resources/fixture/testsuitexmlparser/failsafe-summary.xml" );
 
@@ -283,7 +332,7 @@ public class TestSuiteXmlParserTest
     public void shouldParserEverythingInOrdinalTest()
         throws Exception
     {
-        TestSuiteXmlParser parser = new TestSuiteXmlParser();
+        TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger );
         List<ReportTestSuite> tests =
             parser.parse( "src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest.xml" );
         assertTrue( parser.isValid() );
@@ -347,7 +396,7 @@ public class TestSuiteXmlParserTest
     public void shouldParserEverythingInEnclosedTest()
         throws Exception
     {
-        TestSuiteXmlParser parser = new TestSuiteXmlParser();
+        TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger );
         List<ReportTestSuite> tests =
             parser.parse( "src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-enclosed.xml" );
         assertTrue( parser.isValid() );
@@ -423,7 +472,7 @@ public class TestSuiteXmlParserTest
     public void shouldParserEverythingInEnclosedTrimStackTraceTest()
         throws Exception
     {
-        TestSuiteXmlParser parser = new TestSuiteXmlParser();
+        TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger );
         List<ReportTestSuite> tests = parser.parse( "src/test/resources/fixture/testsuitexmlparser/"
                                                         + "TEST-surefire.MyTest-enclosed-trimStackTrace.xml" );
         assertTrue( parser.isValid() );
@@ -465,7 +514,7 @@ public class TestSuiteXmlParserTest
     public void shouldParserEverythingInNestedClassTest()
         throws Exception
     {
-        TestSuiteXmlParser parser = new TestSuiteXmlParser();
+        TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger );
         List<ReportTestSuite> tests = parser.parse( "src/test/resources/fixture/testsuitexmlparser/"
                                                         + "TEST-surefire.MyTest-nestedClass.xml" );
         assertTrue( parser.isValid() );
@@ -532,7 +581,7 @@ public class TestSuiteXmlParserTest
     public void shouldParserEverythingInNestedClassTrimStackTraceTest()
         throws Exception
     {
-        TestSuiteXmlParser parser = new TestSuiteXmlParser();
+        TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger );
         List<ReportTestSuite> tests = parser.parse( "src/test/resources/fixture/testsuitexmlparser/"
                                                         + "TEST-surefire.MyTest-nestedClass-trimStackTrace.xml" );
         assertTrue( parser.isValid() );

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-setup-integration-tests/src/test/java/org/apache/maven/surefire/its/StagedLocalRepoHelper.java
----------------------------------------------------------------------
diff --git a/surefire-setup-integration-tests/src/test/java/org/apache/maven/surefire/its/StagedLocalRepoHelper.java b/surefire-setup-integration-tests/src/test/java/org/apache/maven/surefire/its/StagedLocalRepoHelper.java
index 1252553..202d665 100644
--- a/surefire-setup-integration-tests/src/test/java/org/apache/maven/surefire/its/StagedLocalRepoHelper.java
+++ b/surefire-setup-integration-tests/src/test/java/org/apache/maven/surefire/its/StagedLocalRepoHelper.java
@@ -67,6 +67,8 @@ public final class StagedLocalRepoHelper
         Random entropy = new Random();
         try
         {
+            System.out.println( Settings.class.getClassLoader()
+                                        .getResource( "org/apache/maven/settings/Server.class" ) );
             Settings settings = new SettingsXpp3Reader().read( ReaderFactory.newXmlReader( originalSettingsXml ) );
 
             String localRepo = System.getProperty( "maven.repo.local" );


[3/5] maven-surefire git commit: [SUREFIRE-1254] add color messages

Posted by ti...@apache.org.
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/resources/META-INF/services/org.apache.maven.surefire.spi.IDefault
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/resources/META-INF/services/org.apache.maven.surefire.spi.IDefault b/maven-surefire-common/src/test/resources/META-INF/services/org.apache.maven.surefire.spi.IDefault
new file mode 100644
index 0000000..09fbc28
--- /dev/null
+++ b/maven-surefire-common/src/test/resources/META-INF/services/org.apache.maven.surefire.spi.IDefault
@@ -0,0 +1,22 @@
+#
+# 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.
+#
+
+
+org.apache.maven.surefire.spi.DefaultImpl
+org.apache.maven.surefire.spi.CustomizedImpl

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/pom.xml b/maven-surefire-plugin/pom.xml
index 978ad1a..848922f 100644
--- a/maven-surefire-plugin/pom.xml
+++ b/maven-surefire-plugin/pom.xml
@@ -120,6 +120,32 @@
           </execution>
         </executions>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+            <configuration>
+              <minimizeJar>true</minimizeJar>
+              <artifactSet>
+                <includes>
+                  <include>org.apache.maven.shared:maven-shared-utils</include>
+                </includes>
+              </artifactSet>
+              <relocations>
+                <relocation>
+                  <pattern>org.apache.maven.shared</pattern>
+                  <shadedPattern>org.apache.maven.surefire.shade.org.apache.maven.shared</shadedPattern>
+                </relocation>
+              </relocations>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
     </plugins>
   </build>
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
index 291bf25..bfb68e0 100644
--- a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
+++ b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
@@ -31,6 +31,8 @@ import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.surefire.suite.RunResult;
 
+import static org.apache.maven.plugin.surefire.SurefireHelper.reportExecution;
+
 /**
  * Run tests using Surefire.
  *
@@ -318,7 +320,7 @@ public class SurefirePlugin
     {
         assertNoException( firstForkException );
 
-        SurefireHelper.reportExecution( this, summary, getLog() );
+        reportExecution( this, summary, getConsoleLogger() );
     }
 
     private void assertNoException( Exception firstForkException )

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-plugin/src/site/apt/index.apt.vm
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/apt/index.apt.vm b/maven-surefire-plugin/src/site/apt/index.apt.vm
index 6774491..85c4d66 100644
--- a/maven-surefire-plugin/src/site/apt/index.apt.vm
+++ b/maven-surefire-plugin/src/site/apt/index.apt.vm
@@ -30,6 +30,10 @@
 
 Maven ${thisPlugin} Plugin
 
+
+  Requirements: Maven 2.2.1 or 3.x, and JDK 1.5 or higher. Due to wrong formatting of console text messages
+  in Maven Version prior to 3.1.0 it is highly recommended to use Maven 3.1.0 or higher.
+
 #{if}(${project.artifactId}=="maven-surefire-plugin")
   The Surefire Plugin is used during the <<<test>>> phase of the build
   lifecycle to execute the unit tests of an application. It generates reports

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-report-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/maven-surefire-report-plugin/pom.xml b/maven-surefire-report-plugin/pom.xml
index 9fc60d7..e911c6e 100644
--- a/maven-surefire-report-plugin/pom.xml
+++ b/maven-surefire-report-plugin/pom.xml
@@ -48,6 +48,10 @@
 
   <dependencies>
     <dependency>
+      <groupId>org.apache.maven.surefire</groupId>
+      <artifactId>surefire-logger-api</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-project</artifactId>
     </dependency>
@@ -92,6 +96,12 @@
       <version>3.0.15</version>
     </dependency>
     <dependency>
+      <groupId>org.fusesource.jansi</groupId>
+      <artifactId>jansi</artifactId>
+      <version>1.13</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
       <groupId>org.apache.maven.plugin-testing</groupId>
       <artifactId>maven-plugin-testing-harness</artifactId>
       <version>1.2</version>
@@ -123,6 +133,51 @@
           </execution>
         </executions>
       </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <version>1.12</version>
+        <executions>
+          <execution>
+            <id>add-source</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${project.build.directory}/generated-sources</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>shared-logging-generated-sources</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>unpack</goal>
+            </goals>
+            <configuration>
+              <outputDirectory>${project.build.directory}/generated-sources</outputDirectory>
+              <overWriteIfNewer>false</overWriteIfNewer>
+              <artifact>org.apache.maven.shared:maven-shared-utils:3.1.0:jar:sources</artifact>
+              <includes>org/apache/maven/shared/utils/logging/*.java</includes>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <classpathDependencyExcludes>
+            <classpathDependencyExclude>org.fusesource.jansi:jansi</classpathDependencyExclude>
+          </classpathDependencyExcludes>
+        </configuration>
+      </plugin>
     </plugins>
   </build>
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/AbstractSurefireReportMojo.java
----------------------------------------------------------------------
diff --git a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/AbstractSurefireReportMojo.java b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/AbstractSurefireReportMojo.java
index ea3b08c..9621fa1 100644
--- a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/AbstractSurefireReportMojo.java
+++ b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/AbstractSurefireReportMojo.java
@@ -26,15 +26,16 @@ import java.util.List;
 import java.util.Locale;
 import java.util.ResourceBundle;
 import org.apache.maven.model.ReportPlugin;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.reporting.AbstractMavenReport;
 import org.apache.maven.reporting.MavenReportException;
 import org.apache.maven.shared.utils.PathTool;
-import org.apache.maven.shared.utils.StringUtils;
 
 import static java.util.Collections.addAll;
 import static org.apache.maven.plugins.surefire.report.SurefireReportParser.hasReportFiles;
+import static org.apache.maven.shared.utils.StringUtils.isEmpty;
 
 /**
  * Abstract base class for reporting test results using Surefire.
@@ -44,6 +45,7 @@ import static org.apache.maven.plugins.surefire.report.SurefireReportParser.hasR
 public abstract class AbstractSurefireReportMojo
     extends AbstractMavenReport
 {
+
     /**
      * If set to false, only failures are shown.
      *
@@ -102,6 +104,8 @@ public abstract class AbstractSurefireReportMojo
     @Parameter( defaultValue = "false", property = "aggregate" )
     private boolean aggregate;
 
+    private List<File> resolvedReportsDirectories;
+
     /**
      * Whether the report should be generated or not.
      *
@@ -130,47 +134,32 @@ public abstract class AbstractSurefireReportMojo
     public void executeReport( Locale locale )
         throws MavenReportException
     {
-        if ( isSkipped() )
-        {
-            return;
-        }
-
-        final List<File> reportsDirectoryList = getReportsDirectories();
-
-        if ( reportsDirectoryList == null )
+        if ( !hasReportDirectories() )
         {
             return;
         }
 
-        if ( !isGeneratedWhenNoResults() )
-        {
-            boolean atLeastOneDirectoryExists = false;
-            for ( Iterator<File> i = reportsDirectoryList.iterator(); i.hasNext() && !atLeastOneDirectoryExists; )
-            {
-                atLeastOneDirectoryExists = hasReportFiles( i.next() );
-            }
-            if ( !atLeastOneDirectoryExists )
-            {
-                return;
-            }
-        }
-
-        SurefireReportGenerator report =
-            new SurefireReportGenerator( reportsDirectoryList, locale, showSuccess, determineXrefLocation() );
-
-        report.doGenerateReport( getBundle( locale ), getSink() );
+        new SurefireReportGenerator( getReportsDirectories(), locale, showSuccess, determineXrefLocation(),
+                                           getConsoleLogger() )
+                .doGenerateReport( getBundle( locale ), getSink() );
     }
 
+    @Override
     public boolean canGenerateReport()
     {
+        return hasReportDirectories() && super.canGenerateReport();
+    }
+
+    private boolean hasReportDirectories()
+    {
         if ( isSkipped() )
         {
             return false;
         }
 
-        final List<File> reportsDirectoryList = getReportsDirectories();
+        final List<File> reportsDirectories = getReportsDirectories();
 
-        if ( reportsDirectoryList == null )
+        if ( reportsDirectories == null )
         {
             return false;
         }
@@ -178,7 +167,7 @@ public abstract class AbstractSurefireReportMojo
         if ( !isGeneratedWhenNoResults() )
         {
             boolean atLeastOneDirectoryExists = false;
-            for ( Iterator<File> i = reportsDirectoryList.iterator(); i.hasNext() && !atLeastOneDirectoryExists; )
+            for ( Iterator<File> i = reportsDirectories.iterator(); i.hasNext() && !atLeastOneDirectoryExists; )
             {
                 atLeastOneDirectoryExists = hasReportFiles( i.next() );
             }
@@ -187,23 +176,27 @@ public abstract class AbstractSurefireReportMojo
                 return false;
             }
         }
-
-        return super.canGenerateReport();
+        return true;
     }
 
     private List<File> getReportsDirectories()
     {
-        final List<File> reportsDirectories = new ArrayList<File>();
+        if ( resolvedReportsDirectories != null )
+        {
+            return resolvedReportsDirectories;
+        }
+
+        resolvedReportsDirectories = new ArrayList<File>();
 
         if ( this.reportsDirectories != null )
         {
-            addAll( reportsDirectories, this.reportsDirectories );
+            addAll( resolvedReportsDirectories, this.reportsDirectories );
         }
         //noinspection deprecation
         if ( reportsDirectory != null )
         {
             //noinspection deprecation
-            reportsDirectories.add( reportsDirectory );
+            resolvedReportsDirectories.add( reportsDirectory );
         }
         if ( aggregate )
         {
@@ -215,7 +208,7 @@ public abstract class AbstractSurefireReportMojo
             {
                 for ( MavenProject mavenProject : getProjectsWithoutRoot() )
                 {
-                    reportsDirectories.add( getSurefireReportsDirectory( mavenProject ) );
+                    resolvedReportsDirectories.add( getSurefireReportsDirectory( mavenProject ) );
                 }
             }
             else
@@ -236,8 +229,8 @@ public abstract class AbstractSurefireReportMojo
                         File reportsDirectory = new File( moduleBaseDir, reportDir );
                         if ( reportsDirectory.exists() && reportsDirectory.isDirectory() )
                         {
-                            getLog().debug( "Adding report dir : " + moduleBaseDir + reportDir );
-                            reportsDirectories.add( reportsDirectory );
+                            getConsoleLogger().debug( "Adding report dir : " + moduleBaseDir + reportDir );
+                            resolvedReportsDirectories.add( reportsDirectory );
                         }
                     }
                 }
@@ -245,13 +238,13 @@ public abstract class AbstractSurefireReportMojo
         }
         else
         {
-            if ( reportsDirectories.isEmpty() )
+            if ( resolvedReportsDirectories.isEmpty() )
             {
 
-                reportsDirectories.add( getSurefireReportsDirectory( project ) );
+                resolvedReportsDirectories.add( getSurefireReportsDirectory( project ) );
             }
         }
-        return reportsDirectories;
+        return resolvedReportsDirectories;
     }
 
     /**
@@ -283,7 +276,7 @@ public abstract class AbstractSurefireReportMojo
         if ( linkXRef )
         {
             String relativePath = PathTool.getRelativePath( getOutputDirectory(), xrefLocation.getAbsolutePath() );
-            if ( StringUtils.isEmpty( relativePath ) )
+            if ( isEmpty( relativePath ) )
             {
                 relativePath = ".";
             }
@@ -310,7 +303,7 @@ public abstract class AbstractSurefireReportMojo
 
             if ( location == null )
             {
-                getLog().warn( "Unable to locate Test Source XRef to link to - DISABLED" );
+                getConsoleLogger().warning( "Unable to locate Test Source XRef to link to - DISABLED" );
             }
         }
         return location;
@@ -339,6 +332,11 @@ public abstract class AbstractSurefireReportMojo
 
     private ResourceBundle getBundle( Locale locale )
     {
-        return ResourceBundle.getBundle( "surefire-report", locale, this.getClass().getClassLoader() );
+        return ResourceBundle.getBundle( "surefire-report", locale, getClass().getClassLoader() );
+    }
+
+    protected final ConsoleLogger getConsoleLogger()
+    {
+        return new PluginConsoleLogger( getLog() );
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/FailsafeReportMojo.java
----------------------------------------------------------------------
diff --git a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/FailsafeReportMojo.java b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/FailsafeReportMojo.java
index 071ac44..4cf51fc 100644
--- a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/FailsafeReportMojo.java
+++ b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/FailsafeReportMojo.java
@@ -111,6 +111,6 @@ public class FailsafeReportMojo
     */
     private ResourceBundle getBundle( Locale locale )
     {
-        return ResourceBundle.getBundle( "surefire-report", locale, this.getClass().getClassLoader() );
+        return ResourceBundle.getBundle( "surefire-report", locale, getClass().getClassLoader() );
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/PluginConsoleLogger.java
----------------------------------------------------------------------
diff --git a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/PluginConsoleLogger.java b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/PluginConsoleLogger.java
new file mode 100644
index 0000000..ba83734
--- /dev/null
+++ b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/PluginConsoleLogger.java
@@ -0,0 +1,140 @@
+package org.apache.maven.plugins.surefire.report;
+
+/*
+ * 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.apache.maven.plugin.logging.Log;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.shared.utils.logging.MessageBuilder;
+
+import static java.lang.Integer.numberOfLeadingZeros;
+import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
+
+/**
+ * Wrapper logger of miscellaneous (Maven 2.2.1 or 3.1) implementations of {@link Log}.
+ * Calling {@link Log#isInfoEnabled()} before {@link Log#info(CharSequence)} due to Maven 2.2.1.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19.2
+ * @see ConsoleLogger
+ */
+final class PluginConsoleLogger
+    implements ConsoleLogger
+{
+    private final Log mojoLogger;
+
+    public PluginConsoleLogger( Log mojoLogger )
+    {
+        this.mojoLogger = mojoLogger;
+    }
+
+    public boolean isDebugEnabled()
+    {
+        return mojoLogger.isDebugEnabled();
+    }
+
+    public void debug( String message )
+    {
+        if ( mojoLogger.isDebugEnabled() )
+        {
+            mojoLogger.debug( createAnsiBuilder( message ).debug( message ).toString() );
+        }
+    }
+
+    public void debug( CharSequence content, Throwable error )
+    {
+        if ( mojoLogger.isDebugEnabled() )
+        {
+            mojoLogger.debug( content, error );
+        }
+    }
+
+    public boolean isInfoEnabled()
+    {
+        return mojoLogger.isInfoEnabled();
+    }
+
+    public void info( String message )
+    {
+        if ( mojoLogger.isInfoEnabled() )
+        {
+            mojoLogger.info( createAnsiBuilder( message ).info( message ).toString() );
+        }
+    }
+
+    public boolean isWarnEnabled()
+    {
+        return mojoLogger.isWarnEnabled();
+    }
+
+    public void warning( String message )
+    {
+        if ( mojoLogger.isWarnEnabled() )
+        {
+            mojoLogger.warn( createAnsiBuilder( message ).warning( message ).toString() );
+        }
+    }
+
+    public void warn( CharSequence content, Throwable error )
+    {
+        if ( mojoLogger.isWarnEnabled() )
+        {
+            mojoLogger.warn( content, error );
+        }
+    }
+
+    public boolean isErrorEnabled()
+    {
+        return mojoLogger.isErrorEnabled();
+    }
+
+    public void error( String message )
+    {
+        if ( mojoLogger.isErrorEnabled() )
+        {
+            mojoLogger.error( createAnsiBuilder( message ).error( message ).toString() );
+        }
+    }
+
+    public void error( String message, Throwable t )
+    {
+        if ( mojoLogger.isErrorEnabled() )
+        {
+            mojoLogger.error( message, t );
+        }
+    }
+
+    public void error( Throwable t )
+    {
+        if ( mojoLogger.isErrorEnabled() )
+        {
+            mojoLogger.error( t );
+        }
+    }
+
+    private static MessageBuilder createAnsiBuilder( CharSequence message )
+    {
+        return buffer( bufferSize( message ) );
+    }
+
+    private static int bufferSize( CharSequence message )
+    {
+        return 32 - numberOfLeadingZeros( message.length() );
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportGenerator.java
----------------------------------------------------------------------
diff --git a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportGenerator.java b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportGenerator.java
index a6e49cd..7cebfe7 100644
--- a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportGenerator.java
+++ b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportGenerator.java
@@ -30,35 +30,36 @@ import org.apache.maven.doxia.sink.Sink;
 import org.apache.maven.doxia.sink.SinkEventAttributeSet;
 import org.apache.maven.doxia.sink.SinkEventAttributes;
 import org.apache.maven.doxia.util.DoxiaUtils;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.reporting.MavenReportException;
 
+import static org.apache.maven.doxia.sink.Sink.JUSTIFY_LEFT;
+
 /**
  *
  */
 public final class SurefireReportGenerator
 {
-    private static final Object[] TAG_TYPE_START = new Object[]{ HtmlMarkup.TAG_TYPE_START };
+    private static final int LEFT = JUSTIFY_LEFT;
 
-    private static final Object[] TAG_TYPE_END = new Object[]{ HtmlMarkup.TAG_TYPE_END };
+    private static final Object[] TAG_TYPE_START = { HtmlMarkup.TAG_TYPE_START };
 
-    private final SurefireReportParser report;
+    private static final Object[] TAG_TYPE_END = { HtmlMarkup.TAG_TYPE_END };
 
-    private List<ReportTestSuite> testSuites;
+    private final SurefireReportParser report;
 
     private final boolean showSuccess;
 
     private final String xrefLocation;
-    
-    private static final int LEFT = Sink.JUSTIFY_LEFT;
+
+    private List<ReportTestSuite> testSuites;
 
     public SurefireReportGenerator( List<File> reportsDirectories, Locale locale, boolean showSuccess,
-                                    String xrefLocation )
+                                    String xrefLocation, ConsoleLogger consoleLogger )
     {
-        report = new SurefireReportParser( reportsDirectories, locale );
-
-        this.xrefLocation = xrefLocation;
-
+        report = new SurefireReportParser( reportsDirectories, locale, consoleLogger );
         this.showSuccess = showSuccess;
+        this.xrefLocation = xrefLocation;
     }
 
     public void doGenerateReport( ResourceBundle bundle, Sink sink )

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire597Test.java
----------------------------------------------------------------------
diff --git a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire597Test.java b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire597Test.java
index 35182d0..b78edcb 100644
--- a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire597Test.java
+++ b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire597Test.java
@@ -20,6 +20,8 @@ package org.apache.maven.plugins.surefire.report;
  */
 
 import org.apache.maven.doxia.module.xhtml.XhtmlSink;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger;
 import org.junit.Test;
 
 import java.io.File;
@@ -43,7 +45,8 @@ public class Surefire597Test
     {
         File basedir = new File( "." ).getCanonicalFile();
         File report = new File( basedir, "target/test-classes/surefire-597" );
-        SurefireReportGenerator gen = new SurefireReportGenerator( singletonList( report ), ENGLISH, true, null );
+        ConsoleLogger log = new NullConsoleLogger();
+        SurefireReportGenerator gen = new SurefireReportGenerator( singletonList( report ), ENGLISH, true, null, log );
         ResourceBundle resourceBundle = ResourceBundle.getBundle( "surefire-report", ENGLISH );
         StringWriter writer = new StringWriter();
         gen.doGenerateReport( resourceBundle, new XhtmlSink( writer ) {} );

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 95198cf..609ec15 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
   </contributors>
 
   <modules>
+    <module>surefire-logger-api</module>
     <module>surefire-shadefire</module>
     <module>surefire-api</module>
     <module>surefire-booter</module>
@@ -116,6 +117,11 @@
       </dependency>
       <dependency>
         <groupId>org.apache.maven.surefire</groupId>
+        <artifactId>surefire-logger-api</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven.surefire</groupId>
         <artifactId>surefire-grouper</artifactId>
         <version>${project.version}</version>
       </dependency>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-api/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-api/pom.xml b/surefire-api/pom.xml
index 18e2c25..f8c8be9 100644
--- a/surefire-api/pom.xml
+++ b/surefire-api/pom.xml
@@ -33,6 +33,10 @@
 
   <dependencies>
     <dependency>
+      <groupId>org.apache.maven.surefire</groupId>
+      <artifactId>surefire-logger-api</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.apache.maven.shared</groupId>
       <artifactId>maven-shared-utils</artifactId>
     </dependency>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
index c72e2f7..66f28ad 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
@@ -21,7 +21,7 @@ package org.apache.maven.surefire.booter;
 
 import org.apache.maven.surefire.cli.CommandLineOption;
 import org.apache.maven.surefire.providerapi.ProviderParameters;
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.surefire.report.ConsoleStream;
 import org.apache.maven.surefire.report.DefaultDirectConsoleReporter;
 import org.apache.maven.surefire.report.ReporterConfiguration;
 import org.apache.maven.surefire.report.ReporterFactory;
@@ -41,6 +41,8 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
+import static java.util.Collections.emptyList;
+
 /**
  * @author Kristian Rosenvold
  */
@@ -55,7 +57,7 @@ public class BaseProviderFactory
 
     private final boolean insideFork;
 
-    private List<CommandLineOption> mainCliOptions = Collections.emptyList();
+    private List<CommandLineOption> mainCliOptions = emptyList();
 
     private Map<String, String> providerProperties;
 
@@ -128,7 +130,7 @@ public class BaseProviderFactory
         this.testClassLoader = testClassLoader;
     }
 
-    public ConsoleLogger getConsoleLogger()
+    public ConsoleStream getConsoleLogger()
     {
         boolean trim = reporterConfiguration.isTrimStackTrace();
         PrintStream out = reporterConfiguration.getOriginalSystemOut();

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java
index 2bb4504..4287080 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java
@@ -19,6 +19,8 @@ package org.apache.maven.surefire.booter;
  * under the License.
  */
 
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger;
 import org.apache.maven.surefire.testset.TestSetFailedException;
 
 import java.io.DataInputStream;
@@ -46,10 +48,11 @@ import static org.apache.maven.surefire.booter.MasterProcessCommand.SHUTDOWN;
 import static org.apache.maven.surefire.booter.MasterProcessCommand.SKIP_SINCE_NEXT_TEST;
 import static org.apache.maven.surefire.booter.MasterProcessCommand.TEST_SET_FINISHED;
 import static org.apache.maven.surefire.booter.MasterProcessCommand.decode;
+import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThread;
 import static org.apache.maven.surefire.util.internal.StringUtils.encodeStringForForkCommunication;
-import static org.apache.maven.surefire.util.internal.StringUtils.isNotBlank;
 import static org.apache.maven.surefire.util.internal.StringUtils.isBlank;
-import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThread;
+import static org.apache.maven.surefire.util.internal.StringUtils.isNotBlank;
+import static org.apache.maven.surefire.util.internal.StringUtils.requireNonNull;
 
 /**
  * Reader of commands coming from plugin(master) process.
@@ -80,6 +83,12 @@ public final class CommandReader
 
     private int iteratedCount;
 
+    private volatile ConsoleLogger logger = new NullConsoleLogger();
+
+    private CommandReader()
+    {
+    }
+
     public static CommandReader getReader()
     {
         final CommandReader reader = READER;
@@ -96,6 +105,12 @@ public final class CommandReader
         return this;
     }
 
+    public CommandReader setLogger( ConsoleLogger logger )
+    {
+        this.logger = requireNonNull( logger, "null logger" );
+        return this;
+    }
+
     public boolean awaitStarted()
         throws TestSetFailedException
     {
@@ -360,7 +375,7 @@ public final class CommandReader
                     Command command = decode( stdIn );
                     if ( command == null )
                     {
-                        System.err.println( "[SUREFIRE] std/in stream corrupted: first sequence not recognized" );
+                        logger.error( "[SUREFIRE] std/in stream corrupted: first sequence not recognized" );
                         break;
                     }
                     else
@@ -409,8 +424,7 @@ public final class CommandReader
                 // If #stop() method is called, reader thread is interrupted and cause is InterruptedException.
                 if ( !( e.getCause() instanceof InterruptedException ) )
                 {
-                    System.err.println( "[SUREFIRE] std/in stream corrupted" );
-                    e.printStackTrace();
+                    logger.error( "[SUREFIRE] std/in stream corrupted", e );
                 }
             }
             finally

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java
index e56b94b..d0d8cca 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java
@@ -20,20 +20,24 @@ package org.apache.maven.surefire.booter;
  */
 
 import java.io.PrintStream;
-import java.nio.charset.Charset;
 import java.util.Enumeration;
 import java.util.Properties;
 
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLoggerUtils;
 import org.apache.maven.surefire.report.ConsoleOutputReceiver;
+import org.apache.maven.surefire.report.ConsoleStream;
 import org.apache.maven.surefire.report.ReportEntry;
 import org.apache.maven.surefire.report.RunListener;
 import org.apache.maven.surefire.report.SafeThrowable;
 import org.apache.maven.surefire.report.SimpleReportEntry;
 import org.apache.maven.surefire.report.StackTraceWriter;
-import org.apache.maven.surefire.util.internal.StringUtils;
 
+import static java.lang.Integer.toHexString;
+import static java.nio.charset.Charset.defaultCharset;
 import static org.apache.maven.surefire.util.internal.StringUtils.encodeStringForForkCommunication;
+import static org.apache.maven.surefire.util.internal.StringUtils.escapeBytesToPrintable;
+import static org.apache.maven.surefire.util.internal.StringUtils.escapeToPrintable;
 
 /**
  * Encodes the full output of the test run to the stdout stream.
@@ -53,7 +57,7 @@ import static org.apache.maven.surefire.util.internal.StringUtils.encodeStringFo
  * @author Kristian Rosenvold
  */
 public class ForkingRunListener
-    implements RunListener, ConsoleLogger, ConsoleOutputReceiver
+    implements RunListener, ConsoleLogger, ConsoleOutputReceiver, ConsoleStream
 {
     public static final byte BOOTERCODE_TESTSET_STARTING = (byte) '1';
 
@@ -75,6 +79,10 @@ public class ForkingRunListener
 
     public static final byte BOOTERCODE_TEST_ASSUMPTIONFAILURE = (byte) 'G';
 
+    /**
+     * INFO logger
+     * @see ConsoleLogger#info(String)
+     */
     public static final byte BOOTERCODE_CONSOLE = (byte) 'H';
 
     public static final byte BOOTERCODE_SYSPROPS = (byte) 'I';
@@ -83,10 +91,27 @@ public class ForkingRunListener
 
     public static final byte BOOTERCODE_STOP_ON_NEXT_TEST = (byte) 'S';
 
+    /**
+     * ERROR logger
+     * @see ConsoleLogger#error(String)
+     */
     public static final byte BOOTERCODE_ERROR = (byte) 'X';
 
     public static final byte BOOTERCODE_BYE = (byte) 'Z';
 
+    /**
+     * DEBUG logger
+     * @see ConsoleLogger#debug(String)
+     */
+    public static final byte BOOTERCODE_DEBUG = (byte) 'D';
+
+    /**
+     * WARNING logger
+     * @see ConsoleLogger#warning(String)
+     */
+    public static final byte BOOTERCODE_WARNING = (byte) 'W';
+
+
     private final PrintStream target;
 
     private final int testSetChannelId;
@@ -172,7 +197,7 @@ public class ForkingRunListener
         byte[] header = stdout ? stdOutHeader : stdErrHeader;
         byte[] content =
             new byte[buf.length * 3 + 1]; // Hex-escaping can be up to 3 times length of a regular byte.
-        int i = StringUtils.escapeBytesToPrintable( content, 0, buf, off, len );
+        int i = escapeBytesToPrintable( content, 0, buf, off, len );
         content[i++] = (byte) '\n';
 
         synchronized ( target ) // See notes about synchronization/thread safety in class javadoc
@@ -187,24 +212,54 @@ public class ForkingRunListener
         return encodeStringForForkCommunication( String.valueOf( (char) booterCode )
                 + ','
                 + Integer.toString( testSetChannel, 16 )
-                + ',' + Charset.defaultCharset().name()
+                + ',' + defaultCharset().name()
                 + ',' );
     }
 
-    public void info( String message )
+    private void log( byte bootCode, String message )
     {
         if ( message != null )
         {
             StringBuilder sb = new StringBuilder( 7 + message.length() * 5 );
-            append( sb, BOOTERCODE_CONSOLE ); comma( sb );
-            append( sb, Integer.toHexString( testSetChannelId ) ); comma( sb );
-            StringUtils.escapeToPrintable( sb, message );
+            append( sb, bootCode ); comma( sb );
+            append( sb, toHexString( testSetChannelId ) ); comma( sb );
+            escapeToPrintable( sb, message );
 
             sb.append( '\n' );
             encodeAndWriteToTarget( sb.toString() );
         }
     }
 
+    public void debug( String message )
+    {
+        log( BOOTERCODE_DEBUG, message );
+    }
+
+    public void info( String message )
+    {
+        log( BOOTERCODE_CONSOLE, message );
+    }
+
+    public void warning( String message )
+    {
+        log( BOOTERCODE_WARNING, message );
+    }
+
+    public void error( String message )
+    {
+        log( BOOTERCODE_ERROR, message );
+    }
+
+    public void error( String message, Throwable t )
+    {
+        error( ConsoleLoggerUtils.toString( message, t ) );
+    }
+
+    public void error( Throwable t )
+    {
+        error( null, t );
+    }
+
     private void encodeAndWriteToTarget( String string )
     {
         byte[] encodeBytes = encodeStringForForkCommunication( string );
@@ -219,11 +274,11 @@ public class ForkingRunListener
         StringBuilder stringBuilder = new StringBuilder();
 
         append( stringBuilder, BOOTERCODE_SYSPROPS ); comma( stringBuilder );
-        append( stringBuilder, Integer.toHexString( testSetChannelId ) ); comma( stringBuilder );
+        append( stringBuilder, toHexString( testSetChannelId ) ); comma( stringBuilder );
 
-        StringUtils.escapeToPrintable( stringBuilder, key );
+        escapeToPrintable( stringBuilder, key );
         comma( stringBuilder );
-        StringUtils.escapeToPrintable( stringBuilder, value );
+        escapeToPrintable( stringBuilder, value );
         stringBuilder.append( "\n" );
         return stringBuilder.toString();
     }
@@ -232,7 +287,7 @@ public class ForkingRunListener
     {
         StringBuilder stringBuilder = new StringBuilder();
         append( stringBuilder, operationCode ); comma( stringBuilder );
-        append( stringBuilder, Integer.toHexString( testSetChannelId ) ); comma( stringBuilder );
+        append( stringBuilder, toHexString( testSetChannelId ) ); comma( stringBuilder );
 
         nullableEncoding( stringBuilder, reportEntry.getSourceName() );
         comma( stringBuilder );
@@ -291,7 +346,7 @@ public class ForkingRunListener
         }
         else
         {
-            StringUtils.escapeToPrintable( stringBuilder, source );
+            escapeToPrintable( stringBuilder, source );
         }
     }
 
@@ -320,4 +375,15 @@ public class ForkingRunListener
                 : stackTraceWriter.writeTraceToString() );
         }
     }
+
+    public void println( String message )
+    {
+        byte[] buf = message.getBytes();
+        println( buf, 0, buf.length );
+    }
+
+    public void println( byte[] buf, int off, int len )
+    {
+        writeTestOutput( buf, off, len, true );
+    }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
index bd73908..b25c04b 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
@@ -29,6 +29,8 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLoggerDecorator;
 import org.apache.maven.surefire.cli.CommandLineOption;
 import org.apache.maven.surefire.providerapi.ProviderParameters;
 import org.apache.maven.surefire.report.ReporterConfiguration;
@@ -42,6 +44,8 @@ import org.apache.maven.surefire.testset.TestRequest;
 import org.apache.maven.surefire.util.RunOrder;
 import org.apache.maven.surefire.util.SurefireReflectionException;
 
+import javax.annotation.Nonnull;
+
 import static java.util.Collections.checkedList;
 
 import static org.apache.maven.surefire.util.ReflectionUtils.getConstructor;
@@ -102,7 +106,6 @@ public class SurefireReflector
 
     private final Class<Enum> shutdownClass;
 
-
     @SuppressWarnings( "unchecked" )
     public SurefireReflector( ClassLoader surefireClassLoader )
     {
@@ -408,6 +411,11 @@ public class SurefireReflector
         return runResult.isAssignableFrom( o.getClass() );
     }
 
+    public Object createConsoleLogger( @Nonnull ConsoleLogger consoleLogger )
+    {
+        return createConsoleLogger( consoleLogger, surefireClassLoader );
+    }
+
     private static Collection<Integer> toOrdinals( Collection<? extends Enum> enums )
     {
         Collection<Integer> ordinals = new ArrayList<Integer>( enums.size() );
@@ -418,4 +426,17 @@ public class SurefireReflector
         return ordinals;
     }
 
+    public static Object createConsoleLogger( ConsoleLogger consoleLogger, ClassLoader cl )
+    {
+        try
+        {
+            Class<?> decoratorClass = cl.loadClass( ConsoleLoggerDecorator.class.getName() );
+            return getConstructor( decoratorClass, Object.class ).newInstance( consoleLogger );
+        }
+        catch ( Exception e )
+        {
+            throw new SurefireReflectionException( e );
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java b/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java
index a511345..e8c5a84 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java
@@ -21,7 +21,7 @@ package org.apache.maven.surefire.providerapi;
 
 import org.apache.maven.surefire.booter.Shutdown;
 import org.apache.maven.surefire.cli.CommandLineOption;
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.surefire.report.ConsoleStream;
 import org.apache.maven.surefire.report.ReporterConfiguration;
 import org.apache.maven.surefire.report.ReporterFactory;
 import org.apache.maven.surefire.testset.DirectoryScannerParameters;
@@ -84,9 +84,9 @@ public interface ProviderParameters
      * This output is intended for provider-oriented messages that are not attached to a single test-set
      * and will normally be written to something console-like immediately.
      *
-     * @return A console logger
+     * @return A console stream logger
      */
-    ConsoleLogger getConsoleLogger();
+    ConsoleStream getConsoleLogger();
 
     /**
      * The raw parameters used in creating the directory scanner

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleLogger.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleLogger.java b/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleLogger.java
deleted file mode 100644
index 4382428..0000000
--- a/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleLogger.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.apache.maven.surefire.report;
-
-/*
- * 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.
- */
-
-/**
- * Allows providers to write console messages on the running maven process.
- * <p/>
- * This output is associated with the entire test run and not a specific
- * test, which means it just goes "straight" to the console "immediately".
- * <p/>
- * s* <p/>
- */
-public interface ConsoleLogger
-{
-    void info( String message );
-}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleOutputCapture.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleOutputCapture.java b/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleOutputCapture.java
index 27b0ee2..bb33b3a 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleOutputCapture.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleOutputCapture.java
@@ -23,6 +23,9 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.PrintStream;
 
+import static java.lang.System.setErr;
+import static java.lang.System.setOut;
+
 /**
  * Deals with system.out/err.
  * <p/>
@@ -31,16 +34,16 @@ public class ConsoleOutputCapture
 {
     public static void startCapture( ConsoleOutputReceiver target )
     {
-        System.setOut( new ForwardingPrintStream( true, target ) );
-
-        System.setErr( new ForwardingPrintStream( false, target ) );
+        setOut( new ForwardingPrintStream( true, target ) );
+        setErr( new ForwardingPrintStream( false, target ) );
     }
 
     private static class ForwardingPrintStream
         extends PrintStream
     {
-        private final boolean isStdout;
+        private static final String NL = System.getProperty( "line.separator" );
 
+        private final boolean isStdout;
         private final ConsoleOutputReceiver target;
 
         ForwardingPrintStream( boolean stdout, ConsoleOutputReceiver target )
@@ -83,7 +86,7 @@ public class ConsoleOutputCapture
             {
                 s = "null"; // Shamelessly taken from super.print
             }
-            final byte[] bytes = ( s + "\n" ).getBytes();
+            final byte[] bytes = ( s + NL ).getBytes();
             target.writeTestOutput( bytes, 0, bytes.length, isStdout );
         }
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleStream.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleStream.java b/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleStream.java
new file mode 100644
index 0000000..8a22ef0
--- /dev/null
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleStream.java
@@ -0,0 +1 @@
+package org.apache.maven.surefire.report;

/*
 * 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.
 */

/**
 * Delegates to {@link System#out}.
 */
public interface ConsoleStream
{
    void println( String message );
    void println( byte[] buf, 
 int off, int len );
}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-api/src/main/java/org/apache/maven/surefire/report/DefaultConsoleReporter.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/report/DefaultConsoleReporter.java b/surefire-api/src/main/java/org/apache/maven/surefire/report/DefaultConsoleReporter.java
deleted file mode 100644
index 6c5c850..0000000
--- a/surefire-api/src/main/java/org/apache/maven/surefire/report/DefaultConsoleReporter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.apache.maven.surefire.report;
-
-/*
- * 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 java.io.PrintStream;
-
-/**
- * @author <a href="mailto:kristian@zenior.no">Kristian Rosenvold</a>
- */
-public class DefaultConsoleReporter
-    implements ConsoleLogger
-{
-    private final PrintStream systemOut;
-
-    public DefaultConsoleReporter( PrintStream systemOut )
-    {
-        this.systemOut = systemOut;
-    }
-
-    public void info( String message )
-    {
-        systemOut.println( message );
-    }
-}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-api/src/main/java/org/apache/maven/surefire/report/DefaultDirectConsoleReporter.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/report/DefaultDirectConsoleReporter.java b/surefire-api/src/main/java/org/apache/maven/surefire/report/DefaultDirectConsoleReporter.java
index f9273ba..f1e0f48 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/report/DefaultDirectConsoleReporter.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/report/DefaultDirectConsoleReporter.java
@@ -24,8 +24,8 @@ import java.io.PrintStream;
 /**
  * @author <a href="mailto:kristian@zenior.no">Kristian Rosenvold</a>
  */
-public class DefaultDirectConsoleReporter
-    implements ConsoleLogger
+public final class DefaultDirectConsoleReporter
+    implements ConsoleStream
 {
     private final PrintStream systemOut;
 
@@ -34,8 +34,13 @@ public class DefaultDirectConsoleReporter
         this.systemOut = systemOut;
     }
 
-    public void info( String message )
+    public void println( String message )
     {
         systemOut.println( message );
     }
+
+    public void println( byte[] buf, int off, int len )
+    {
+        println( new String( buf, off, len ) );
+    }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-api/src/test/java/org/apache/maven/surefire/report/MockReporter.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/report/MockReporter.java b/surefire-api/src/test/java/org/apache/maven/surefire/report/MockReporter.java
deleted file mode 100644
index 91ff446..0000000
--- a/surefire-api/src/test/java/org/apache/maven/surefire/report/MockReporter.java
+++ /dev/null
@@ -1,183 +0,0 @@
-package org.apache.maven.surefire.report;
-
-/*
- * 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 java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Internal use only
- */
-public class MockReporter
-    implements RunListener, ConsoleLogger
-{
-    private final List<String> events = new ArrayList<String>();
-
-    private final List<Object> data = new ArrayList<Object>();
-
-    public static final String SET_STARTING = "SET_STARTED";
-
-    public static final String SET_COMPLETED = "SET_COMPLETED";
-
-    public static final String TEST_STARTING = "TEST_STARTED";
-
-    public static final String TEST_SUCCEEDED = "TEST_COMPLETED";
-
-    public static final String TEST_FAILED = "TEST_FAILED";
-
-    public static final String TEST_ERROR = "TEST_ERROR";
-
-    public static final String TEST_SKIPPED = "TEST_SKIPPED";
-
-    public static final String TEST_ASSUMPTION_FAIL = "TEST_ASSUMPTION_SKIPPED";
-
-    public static final String CONSOLE_OUTPUT = "CONSOLE_OUTPUT";
-
-    public static final String STDOUT = "STDOUT";
-
-    public static final String STDERR = "STDERR";
-
-    private final AtomicInteger testSucceeded = new AtomicInteger();
-
-    private final AtomicInteger testIgnored = new AtomicInteger();
-
-    private final AtomicInteger testFailed = new AtomicInteger();
-
-    private final AtomicInteger testError = new AtomicInteger();
-
-    public MockReporter()
-    {
-    }
-
-    public void testSetStarting( ReportEntry report )
-    {
-        events.add( SET_STARTING );
-        data.add( report );
-    }
-
-    public void testSetCompleted( ReportEntry report )
-    {
-        events.add( SET_COMPLETED );
-        data.add( report );
-    }
-
-    public void testStarting( ReportEntry report )
-    {
-        events.add( TEST_STARTING );
-        data.add( report );
-    }
-
-    public void testSucceeded( ReportEntry report )
-    {
-        events.add( TEST_SUCCEEDED );
-        testSucceeded.incrementAndGet();
-        data.add( report );
-    }
-
-    public void testError( ReportEntry report )
-    {
-        events.add( TEST_ERROR );
-        data.add( report );
-        testFailed.incrementAndGet();
-    }
-
-    public void testFailed( ReportEntry report )
-    {
-        events.add( TEST_FAILED );
-        data.add( report );
-        testFailed.incrementAndGet();
-    }
-
-
-    public void testSkipped( ReportEntry report )
-    {
-        events.add( TEST_SKIPPED );
-        data.add( report );
-        testIgnored.incrementAndGet();
-    }
-
-    public void testExecutionSkippedByUser()
-    {
-    }
-
-    public void testSkippedByUser( ReportEntry report )
-    {
-        testSkipped( report );
-    }
-
-
-    public String getFirstEvent()
-    {
-        return events.get( 0 );
-    }
-
-    public ReportEntry getFirstData()
-    {
-        return (ReportEntry) data.get( 0 );
-    }
-
-    public String getFirstStringData()
-    {
-        return (String) data.get( 0 );
-    }
-
-    public int getTestSucceeded()
-    {
-        return testSucceeded.get();
-    }
-
-    public int getTestIgnored()
-    {
-        return testIgnored.get();
-    }
-
-    public int getTestFailed()
-    {
-        return testFailed.get();
-    }
-
-
-    public void testAssumptionFailure( ReportEntry report )
-    {
-        events.add( TEST_ASSUMPTION_FAIL );
-        data.add( report );
-        testIgnored.incrementAndGet();
-
-    }
-
-    public void writeTestOutput()
-    {
-        //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    public void info( String message )
-    {
-        events.add( CONSOLE_OUTPUT );
-        data.add( message );
-        //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    public void writeTestOutput( byte[] buf, int off, int len, boolean stdout )
-    {
-        events.add( stdout ? STDOUT : STDERR );
-        data.add( new String( buf, off, len ) );
-    }
-}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
index b5ff6dd..f95291b 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
@@ -38,11 +38,19 @@ import org.apache.maven.surefire.report.StackTraceWriter;
 import org.apache.maven.surefire.suite.RunResult;
 import org.apache.maven.surefire.testset.TestSetFailedException;
 
+import static java.lang.System.err;
+import static java.lang.System.out;
+import static java.lang.System.setErr;
+import static java.lang.System.setOut;
+import static java.lang.Thread.currentThread;
+import static org.apache.maven.surefire.booter.CommandReader.getReader;
 import static org.apache.maven.surefire.booter.Shutdown.EXIT;
 import static org.apache.maven.surefire.booter.Shutdown.KILL;
 import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_BYE;
 import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_ERROR;
 import static org.apache.maven.surefire.booter.ForkingRunListener.encode;
+import static org.apache.maven.surefire.booter.SurefireReflector.createForkingReporterFactoryInCurrentClassLoader;
+import static org.apache.maven.surefire.booter.SystemPropertyManager.setSystemProperties;
 import static org.apache.maven.surefire.util.ReflectionUtils.instantiateOneArg;
 import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThreadFactory;
 import static org.apache.maven.surefire.util.internal.StringUtils.encodeStringForForkCommunication;
@@ -75,12 +83,12 @@ public final class ForkedBooter
     {
         final CommandReader reader = startupMasterProcessReader();
         final ScheduledFuture<?> pingScheduler = listenToShutdownCommands( reader );
-        final PrintStream originalOut = System.out;
+        final PrintStream originalOut = out;
         try
         {
             if ( args.length > 1 )
             {
-                SystemPropertyManager.setSystemProperties( new File( args[1] ) );
+                setSystemProperties( new File( args[1] ) );
             }
 
             File surefirePropertiesFile = new File( args[0] );
@@ -98,7 +106,7 @@ public final class ForkedBooter
                 classpathConfiguration.trickClassPathWhenManifestOnlyClasspath();
             }
 
-            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+            ClassLoader classLoader = currentThread().getContextClassLoader();
             classLoader.setDefaultAssertionStatus( classpathConfiguration.isEnableAssertions() );
             startupConfiguration.writeSurefireTestClasspathProperty();
 
@@ -145,7 +153,7 @@ public final class ForkedBooter
         {
             // Just throwing does getMessage() and a local trace - we want to call printStackTrace for a full trace
             // noinspection UseOfSystemOutOrSystemErr
-            t.printStackTrace( System.err );
+            t.printStackTrace( err );
             // noinspection ProhibitedExceptionThrown,CallToSystemExit
             exit( 1, EXIT, reader, false );
         }
@@ -157,7 +165,7 @@ public final class ForkedBooter
 
     private static CommandReader startupMasterProcessReader()
     {
-        return CommandReader.getReader();
+        return getReader();
     }
 
     private static ScheduledFuture<?> listenToShutdownCommands( CommandReader reader )
@@ -240,14 +248,14 @@ public final class ForkedBooter
         final ReporterFactory factory = createForkingReporterFactory( providerConfiguration, originalSystemOut );
 
         return invokeProviderInSameClassLoader( testSet, factory, providerConfiguration, true, startupConfiguration,
-                                                false );
+                                                      false );
     }
 
     private static ReporterFactory createForkingReporterFactory( ProviderConfiguration providerConfiguration,
                                                                  PrintStream originalSystemOut )
     {
         final boolean trimStackTrace = providerConfiguration.getReporterConfiguration().isTrimStackTrace();
-        return SurefireReflector.createForkingReporterFactoryInCurrentClassLoader( trimStackTrace, originalSystemOut );
+        return createForkingReporterFactoryInCurrentClassLoader( trimStackTrace, originalSystemOut );
     }
 
     private static ScheduledExecutorService createJvmTerminator()
@@ -274,41 +282,41 @@ public final class ForkedBooter
     }
 
     private static RunResult invokeProviderInSameClassLoader( Object testSet, Object factory,
-                                                             ProviderConfiguration providerConfiguration,
-                                                             boolean insideFork,
-                                                             StartupConfiguration startupConfig,
-                                                             boolean restoreStreams )
+                                                              ProviderConfiguration providerConfig,
+                                                              boolean insideFork,
+                                                              StartupConfiguration startupConfig,
+                                                              boolean restoreStreams )
         throws TestSetFailedException, InvocationTargetException
     {
-        final PrintStream orgSystemOut = System.out;
-        final PrintStream orgSystemErr = System.err;
+        final PrintStream orgSystemOut = out;
+        final PrintStream orgSystemErr = err;
         // Note that System.out/System.err are also read in the "ReporterConfiguration" instatiation
         // in createProvider below. These are the same values as here.
 
         try
         {
-            return createProviderInCurrentClassloader( startupConfig, insideFork, providerConfiguration, factory )
-                .invoke( testSet );
+            return createProviderInCurrentClassloader( startupConfig, insideFork, providerConfig, factory )
+                           .invoke( testSet );
         }
         finally
         {
             if ( restoreStreams && System.getSecurityManager() == null )
             {
-                System.setOut( orgSystemOut );
-                System.setErr( orgSystemErr );
+                setOut( orgSystemOut );
+                setErr( orgSystemErr );
             }
         }
     }
 
-    private static SurefireProvider createProviderInCurrentClassloader( StartupConfiguration startupConfiguration1,
-                                                                       boolean isInsideFork,
+    private static SurefireProvider createProviderInCurrentClassloader( StartupConfiguration startupConfiguration,
+                                                                        boolean isInsideFork,
                                                                        ProviderConfiguration providerConfiguration,
-                                                                       Object reporterManagerFactory1 )
+                                                                       Object reporterManagerFactory )
     {
-        BaseProviderFactory bpf = new BaseProviderFactory( (ReporterFactory) reporterManagerFactory1, isInsideFork );
+        BaseProviderFactory bpf = new BaseProviderFactory( (ReporterFactory) reporterManagerFactory, isInsideFork );
         bpf.setTestRequest( providerConfiguration.getTestSuiteDefinition() );
         bpf.setReporterConfiguration( providerConfiguration.getReporterConfiguration() );
-        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+        ClassLoader classLoader = currentThread().getContextClassLoader();
         bpf.setClassLoaders( classLoader );
         bpf.setTestArtifactInfo( providerConfiguration.getTestArtifact() );
         bpf.setProviderProperties( providerConfiguration.getProviderProperties() );
@@ -317,7 +325,7 @@ public final class ForkedBooter
         bpf.setMainCliOptions( providerConfiguration.getMainCliOptions() );
         bpf.setSkipAfterFailureCount( providerConfiguration.getSkipAfterFailureCount() );
         bpf.setShutdown( providerConfiguration.getShutdown() );
-        String providerClass = startupConfiguration1.getActualClassName();
+        String providerClass = startupConfiguration.getActualClassName();
         return (SurefireProvider) instantiateOneArg( classLoader, providerClass, ProviderParameters.class, bpf );
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-integration-tests/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/pom.xml b/surefire-integration-tests/pom.xml
index 61e7434..b6fbd41 100644
--- a/surefire-integration-tests/pom.xml
+++ b/surefire-integration-tests/pom.xml
@@ -37,7 +37,6 @@
     <it.settings.showPasswords>false</it.settings.showPasswords>
     <testng.version>5.7</testng.version>
     <surefire.threadcount>5</surefire.threadcount>
-    <mavenHomeUsed>${maven.home}</mavenHomeUsed>
     <useInterpolatedSettings>false</useInterpolatedSettings>
   </properties>
 
@@ -103,7 +102,7 @@
           <systemPropertyVariables>
             <surefire.version>${project.version}</surefire.version>
             <testng.version>${testng.version}</testng.version>
-            <maven.home>${mavenHomeUsed}</maven.home>
+            <maven.home>${maven.home}</maven.home>
             <maven.settings.file>${project.basedir}/../surefire-setup-integration-tests/target/private/it-settings.xml
             </maven.settings.file>
             <maven.repo.local>${project.basedir}/../surefire-setup-integration-tests/target/it-repo</maven.repo.local>
@@ -203,50 +202,6 @@
       </properties>
     </profile>
     <profile>
-      <id>maven-2.2.1</id>
-      <properties>
-        <mavenHomeUsed>${project.build.directory}/maven-extract/apache-maven-2.2.1</mavenHomeUsed>
-      </properties>
-      <build>
-        <plugins>
-          <plugin>
-            <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-dependency-plugin</artifactId>
-            <version>2.4</version>
-            <executions>
-              <execution>
-                <id>unpack</id>
-                <phase>package</phase>
-                <goals>
-                  <goal>unpack</goal>
-                </goals>
-                <configuration>
-                  <artifactItems>
-                    <artifactItem>
-                      <groupId>org.apache.maven</groupId>
-                      <artifactId>apache-maven</artifactId>
-                      <version>2.2.1</version>
-                      <type>tar.gz</type>
-                      <classifier>bin</classifier>
-                      <overWrite>false</overWrite>
-                      <outputDirectory>${project.build.directory}/maven-extract</outputDirectory>
-                    </artifactItem>
-                  </artifactItems>
-                </configuration>
-              </execution>
-            </executions>
-          </plugin>
-          <plugin>
-            <artifactId>maven-failsafe-plugin</artifactId>
-            <version>2.12.4</version> <!-- ${shadedVersion}, but resolved due to http://jira.codehaus.org/browse/MRELEASE-799 -->
-            <configuration>
-              <excludedGroups>org.apache.maven.surefire.its.Not2xCompatible</excludedGroups>
-            </configuration>
-          </plugin>
-        </plugins>
-      </build>
-    </profile>
-    <profile>
       <id>jenkins</id>
       <build>
         <plugins>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Junit47concurrencyIT.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Junit47concurrencyIT.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Junit47concurrencyIT.java
index c129c4c..12c4419 100644
--- a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Junit47concurrencyIT.java
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Junit47concurrencyIT.java
@@ -40,14 +40,12 @@ public class Junit47concurrencyIT
         throws Exception
     {
         OutputValidator validator = unpack( "concurrentjunit47" )
-            .sysProp( "junitVersion", "4.7" )
-            .setJUnitVersion( "4.7" )
             .executeTest()
             .verifyErrorFree( 4 );
         String result = null;
         for ( String line : validator.loadLogLines() )
         {
-            if ( line.startsWith( "Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed:" ) )
+            if ( line.startsWith( "[INFO] Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed:" ) )
             {
                 result = line;
                 break;

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Not2xCompatible.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Not2xCompatible.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Not2xCompatible.java
deleted file mode 100644
index 4f1b5f2..0000000
--- a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Not2xCompatible.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.apache.maven.surefire.its;
-
-/*
- * 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.
- */
-
-/**
- * Marks an integration test as not compatible with 2.2.1
- */
-public interface Not2xCompatible
-{
-}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/HelperAssertions.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/HelperAssertions.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/HelperAssertions.java
index e202114..2e835da 100644
--- a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/HelperAssertions.java
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/HelperAssertions.java
@@ -23,6 +23,8 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.plugin.surefire.log.api.PrintStreamLogger;
 import org.apache.maven.plugins.surefire.report.ReportTestSuite;
 import org.apache.maven.plugins.surefire.report.SurefireReportParser;
 
@@ -129,7 +131,8 @@ public class HelperAssertions
             assertTrue( "Reports directory is missing: " + reportsDir.getAbsolutePath(), reportsDir.exists() );
             reportsDirs.add( reportsDir );
         }
-        SurefireReportParser parser = new SurefireReportParser( reportsDirs, Locale.getDefault() );
+        ConsoleLogger logger = new PrintStreamLogger( System.out );
+        SurefireReportParser parser = new SurefireReportParser( reportsDirs, Locale.getDefault(), logger );
         try
         {
             return parser.parseXMLReportFiles();
@@ -149,7 +152,8 @@ public class HelperAssertions
             assertTrue( "Reports directory is missing: " + reportsDir.getAbsolutePath(), reportsDir.exists() );
             reportsDirs.add( reportsDir );
         }
-        SurefireReportParser parser = new SurefireReportParser( reportsDirs, Locale.getDefault() );
+        ConsoleLogger logger = new PrintStreamLogger( System.out );
+        SurefireReportParser parser = new SurefireReportParser( reportsDirs, Locale.getDefault(), logger );
         try
         {
             return parser.parseXMLReportFiles();

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1122ParallelAndFlakyTestsIT.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1122ParallelAndFlakyTestsIT.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1122ParallelAndFlakyTestsIT.java
index e8fab4e..03e7639 100644
--- a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1122ParallelAndFlakyTestsIT.java
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1122ParallelAndFlakyTestsIT.java
@@ -19,9 +19,7 @@ package org.apache.maven.surefire.its.jiras;
  * under the License.
  */
 
-import org.apache.maven.it.VerificationException;
 import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
-import org.apache.maven.surefire.its.fixture.SurefireLauncher;
 import org.junit.Test;
 
 /**

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1136CwdPropagationInForkedModeIT.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1136CwdPropagationInForkedModeIT.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1136CwdPropagationInForkedModeIT.java
index cd6de87..8aaecea 100644
--- a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1136CwdPropagationInForkedModeIT.java
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1136CwdPropagationInForkedModeIT.java
@@ -19,11 +19,9 @@ package org.apache.maven.surefire.its.jiras;
  * under the License.
  */
 
-import org.apache.maven.surefire.its.Not2xCompatible;
 import org.apache.maven.surefire.its.fixture.OutputValidator;
 import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
 import org.junit.Test;
-import org.junit.experimental.categories.Category;
 
 /**
  * SUREFIRE-1136 Correct current working directory propagation in forked mode
@@ -33,7 +31,6 @@ import org.junit.experimental.categories.Category;
  *
  * @author Norbert Wnuk
  */
-@Category( Not2xCompatible.class )
 public class Surefire1136CwdPropagationInForkedModeIT
     extends SurefireJUnit4IntegrationTestCase
 {

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1158RemoveInfoLinesIT.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1158RemoveInfoLinesIT.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1158RemoveInfoLinesIT.java
index 6f8bed9..17064c0 100644
--- a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1158RemoveInfoLinesIT.java
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1158RemoveInfoLinesIT.java
@@ -18,11 +18,9 @@ package org.apache.maven.surefire.its.jiras;
  * under the License.
  */
 
-import org.apache.maven.surefire.its.Not2xCompatible;
 import org.apache.maven.surefire.its.fixture.OutputValidator;
 import org.apache.maven.surefire.its.fixture.SurefireVerifierException;
 import org.junit.Test;
-import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
@@ -39,7 +37,6 @@ import static org.junit.Assert.*;
  * @since 2.19
  */
 @RunWith( Parameterized.class )
-@Category( Not2xCompatible.class )
 public class Surefire1158RemoveInfoLinesIT
 {
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire735ForkFailWithRedirectConsoleOutputIT.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire735ForkFailWithRedirectConsoleOutputIT.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire735ForkFailWithRedirectConsoleOutputIT.java
index 1d1d2aa..cabb90e 100644
--- a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire735ForkFailWithRedirectConsoleOutputIT.java
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire735ForkFailWithRedirectConsoleOutputIT.java
@@ -19,17 +19,14 @@ package org.apache.maven.surefire.its.jiras;
  * under the License.
  */
 
-import org.apache.maven.surefire.its.Not2xCompatible;
 import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
 import org.apache.maven.surefire.its.fixture.SurefireLauncher;
 
 import org.junit.Test;
-import org.junit.experimental.categories.Category;
 
 /**
  * @author Kristian Rosenvold
  */
-@Category( Not2xCompatible.class )
 public class Surefire735ForkFailWithRedirectConsoleOutputIT
     extends SurefireJUnit4IntegrationTestCase
 {

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire806SpecifiedTestControlsIT.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire806SpecifiedTestControlsIT.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire806SpecifiedTestControlsIT.java
index 70e4d63..aedb82b 100644
--- a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire806SpecifiedTestControlsIT.java
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire806SpecifiedTestControlsIT.java
@@ -18,14 +18,11 @@ package org.apache.maven.surefire.its.jiras;
  * under the License.
  */
 
-import org.apache.maven.surefire.its.Not2xCompatible;
 import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
 
 import org.junit.Ignore;
 import org.junit.Test;
-import org.junit.experimental.categories.Category;
 
-@Category( Not2xCompatible.class )
 public class Surefire806SpecifiedTestControlsIT
     extends SurefireJUnit4IntegrationTestCase
 {

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-integration-tests/src/test/resources/concurrentjunit47/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/concurrentjunit47/pom.xml b/surefire-integration-tests/src/test/resources/concurrentjunit47/pom.xml
index ecb8860..d064175 100644
--- a/surefire-integration-tests/src/test/resources/concurrentjunit47/pom.xml
+++ b/surefire-integration-tests/src/test/resources/concurrentjunit47/pom.xml
@@ -36,16 +36,11 @@
   <version>1.0-SNAPSHOT</version>
   <name>Test for JUnit 4.7</name>
 
-
-  <properties>
-    <junitVersion>4.7</junitVersion>
-  </properties>
-
   <dependencies>
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
-      <version>${junitVersion}</version>
+      <version>4.7</version>
       <scope>test</scope>
     </dependency>
   </dependencies>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-integration-tests/src/test/resources/surefire-1080-parallel-fork-double-test/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/surefire-1080-parallel-fork-double-test/pom.xml b/surefire-integration-tests/src/test/resources/surefire-1080-parallel-fork-double-test/pom.xml
index fb553a8..5d3eb93 100644
--- a/surefire-integration-tests/src/test/resources/surefire-1080-parallel-fork-double-test/pom.xml
+++ b/surefire-integration-tests/src/test/resources/surefire-1080-parallel-fork-double-test/pom.xml
@@ -20,16 +20,13 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>org.apache.maven.surefire</groupId>
-    <artifactId>it-parent</artifactId>
-    <version>1.0</version>
-    <relativePath>../pom.xml</relativePath>
-  </parent>
+
   <groupId>org.apache.maven.plugins.surefire</groupId>
   <artifactId>jiras-surefire-1080</artifactId>
   <version>1.0</version>
+
   <url>http://maven.apache.org</url>
+
   <developers>
     <developer>
       <id>tibordigana</id>
@@ -46,6 +43,7 @@
       <name>Qingzhou Luo</name>
     </contributor>
   </contributors>
+
   <dependencies>
     <dependency>
       <groupId>junit</groupId>
@@ -54,10 +52,12 @@
       <scope>test</scope>
     </dependency>
   </dependencies>
+
   <build>
     <plugins>
       <plugin>
         <artifactId>maven-compiler-plugin</artifactId>
+        <version>2.3.2</version>
         <configuration>
           <source>1.5</source>
           <target>1.5</target>
@@ -65,6 +65,7 @@
       </plugin>
       <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
+        <version>${surefire.version}</version>
         <configuration>
           <parallel>classes</parallel>
           <forkCount>2</forkCount>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-integration-tests/src/test/resources/surefire-1082-parallel-junit-parameterized/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/surefire-1082-parallel-junit-parameterized/pom.xml b/surefire-integration-tests/src/test/resources/surefire-1082-parallel-junit-parameterized/pom.xml
index caba806..ef3b87d 100644
--- a/surefire-integration-tests/src/test/resources/surefire-1082-parallel-junit-parameterized/pom.xml
+++ b/surefire-integration-tests/src/test/resources/surefire-1082-parallel-junit-parameterized/pom.xml
@@ -20,16 +20,13 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>org.apache.maven.surefire</groupId>
-    <artifactId>it-parent</artifactId>
-    <version>1.0</version>
-    <relativePath>../pom.xml</relativePath>
-  </parent>
+
   <groupId>org.apache.maven.plugins.surefire</groupId>
   <artifactId>jiras-surefire-1082</artifactId>
   <version>1.0</version>
+
   <url>http://maven.apache.org</url>
+
   <developers>
     <developer>
       <id>tibordigana</id>
@@ -41,6 +38,7 @@
       <timezone>Europe/Bratislava</timezone>
     </developer>
   </developers>
+
   <dependencies>
     <dependency>
       <groupId>junit</groupId>
@@ -49,10 +47,12 @@
       <scope>test</scope>
     </dependency>
   </dependencies>
+
   <build>
     <plugins>
       <plugin>
         <artifactId>maven-compiler-plugin</artifactId>
+        <version>2.3.2</version>
         <configuration>
           <source>1.5</source>
           <target>1.5</target>
@@ -60,6 +60,7 @@
       </plugin>
       <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
+        <version>${surefire.version}</version>
       </plugin>
     </plugins>
   </build>


[4/5] maven-surefire git commit: [SUREFIRE-1254] add color messages

Posted by ti...@apache.org.
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/log/PluginConsoleLogger.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/log/PluginConsoleLogger.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/log/PluginConsoleLogger.java
new file mode 100644
index 0000000..7884270
--- /dev/null
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/log/PluginConsoleLogger.java
@@ -0,0 +1,126 @@
+package org.apache.maven.plugin.surefire.log;
+
+/*
+ * 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.apache.maven.plugin.logging.Log;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+
+/**
+ * Wrapper logger of miscellaneous (Maven 2.2.1 or 3.1) implementations of {@link Log}.
+ * Calling {@link Log#isInfoEnabled()} before {@link Log#info(CharSequence)} due to Maven 2.2.1.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19.2
+ * @see ConsoleLogger
+ */
+public final class PluginConsoleLogger
+    implements ConsoleLogger
+{
+    private final Log mojoLogger;
+
+    public PluginConsoleLogger( Log mojoLogger )
+    {
+        this.mojoLogger = mojoLogger;
+    }
+
+    public boolean isDebugEnabled()
+    {
+        return mojoLogger.isDebugEnabled();
+    }
+
+    public void debug( String message )
+    {
+        if ( mojoLogger.isDebugEnabled() )
+        {
+            mojoLogger.debug( message );
+        }
+    }
+
+    public void debug( CharSequence content, Throwable error )
+    {
+        if ( mojoLogger.isDebugEnabled() )
+        {
+            mojoLogger.debug( content, error );
+        }
+    }
+
+    public boolean isInfoEnabled()
+    {
+        return mojoLogger.isInfoEnabled();
+    }
+
+    public void info( String message )
+    {
+        if ( mojoLogger.isInfoEnabled() )
+        {
+            mojoLogger.info( message );
+        }
+    }
+
+    public boolean isWarnEnabled()
+    {
+        return mojoLogger.isWarnEnabled();
+    }
+
+    public void warning( String message )
+    {
+        if ( mojoLogger.isWarnEnabled() )
+        {
+            mojoLogger.warn( message );
+        }
+    }
+
+    public void warning( CharSequence content, Throwable error )
+    {
+        if ( mojoLogger.isWarnEnabled() )
+        {
+            mojoLogger.warn( content, error );
+        }
+    }
+
+    public boolean isErrorEnabled()
+    {
+        return mojoLogger.isErrorEnabled();
+    }
+
+    public void error( String message )
+    {
+        if ( mojoLogger.isErrorEnabled() )
+        {
+            mojoLogger.error( message );
+        }
+    }
+
+    public void error( String message, Throwable t )
+    {
+        if ( mojoLogger.isErrorEnabled() )
+        {
+            mojoLogger.error( message, t );
+        }
+    }
+
+    public void error( Throwable t )
+    {
+        if ( mojoLogger.isErrorEnabled() )
+        {
+            mojoLogger.error( t );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleReporter.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleReporter.java
index 1fcf4b0..36f311b 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleReporter.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleReporter.java
@@ -19,12 +19,16 @@ package org.apache.maven.plugin.surefire.report;
  * under the License.
  */
 
-import java.io.BufferedOutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintStream;
-import java.io.PrintWriter;
 import java.util.List;
+
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.shared.utils.logging.MessageBuilder;
 import org.apache.maven.surefire.report.ReportEntry;
+import org.apache.maven.plugin.surefire.log.api.Level;
+
+import static org.apache.maven.plugin.surefire.log.api.Level.resolveLevel;
+import static org.apache.maven.plugin.surefire.report.TestSetStats.concatenateWithTestGroup;
+import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
 
 /**
  * Base class for console reporters.
@@ -40,63 +44,56 @@ public class ConsoleReporter
 
     private static final String TEST_SET_STARTING_PREFIX = "Running ";
 
-    private static final int BUFFER_SIZE = 4096;
+    private final ConsoleLogger logger;
 
-    private final PrintWriter writer;
-
-    public ConsoleReporter( PrintStream originalSystemOut )
-    {
-        OutputStreamWriter out = new OutputStreamWriter( new BufferedOutputStream( originalSystemOut, BUFFER_SIZE ) );
-        writer = new PrintWriter( out );
-    }
-
-    public void testSetStarting( ReportEntry report )
+    public ConsoleReporter( ConsoleLogger logger )
     {
-        writeMessage( getTestSetStartingMessage( report ) );
+        this.logger = logger;
     }
 
-    public void writeMessage( String message )
+    public ConsoleLogger getConsoleLogger()
     {
-        writer.print( message );
-        writer.flush();
+        return logger;
     }
 
-    public void writeLnMessage( String message )
+    public void testSetStarting( ReportEntry report )
     {
-        writer.println( message );
-        writer.flush();
+        MessageBuilder builder = buffer();
+        logger.info( concatenateWithTestGroup( builder.a( TEST_SET_STARTING_PREFIX ), report ) );
     }
 
     public void testSetCompleted( WrappedReportEntry report, TestSetStats testSetStats, List<String> testResults )
     {
-        writeMessage( testSetStats.getTestSetSummary( report ) );
-
-        if ( testResults != null )
+        boolean success = testSetStats.getCompletedCount() > 0;
+        boolean failures = testSetStats.getFailures() > 0;
+        boolean errors = testSetStats.getErrors() > 0;
+        boolean skipped = testSetStats.getSkipped() > 0;
+        boolean flakes = testSetStats.getSkipped() > 0;
+        Level level = resolveLevel( success, failures, errors, skipped, flakes );
+
+        println( testSetStats.getColoredTestSetSummary( report ), level );
+        for ( String testResult : testResults )
         {
-            for ( String testResult : testResults )
-            {
-                writeLnMessage( testResult );
-            }
+            println( testResult, level );
         }
     }
 
-
     public void reset()
     {
-        writer.flush();
     }
 
-    /**
-     * Get the test set starting message for a report.
-     * eg. "Running org.foo.BarTest ( of group )"
-     *
-     * @param report report whose test set is starting
-     * @return the message
-     */
-    private static String getTestSetStartingMessage( ReportEntry report )
+    private void println( String message, Level level )
     {
-        return TEST_SET_STARTING_PREFIX + report.getNameWithGroup() + "\n";
+        switch ( level )
+        {
+            case FAILURE:
+                logger.error( message );
+                break;
+            case UNSTABLE:
+                logger.warning( message );
+                break;
+            default:
+                logger.info( message );
+        }
     }
-
-
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java
index e1ba809..0669763 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java
@@ -21,12 +21,14 @@ package org.apache.maven.plugin.surefire.report;
 
 import org.apache.maven.plugin.surefire.StartupReportConfiguration;
 import org.apache.maven.plugin.surefire.runorder.StatisticsReporter;
-import org.apache.maven.surefire.report.ConsoleLogger;
-import org.apache.maven.surefire.report.DefaultDirectConsoleReporter;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger;
+import org.apache.maven.shared.utils.logging.MessageBuilder;
 import org.apache.maven.surefire.report.ReporterFactory;
 import org.apache.maven.surefire.report.RunListener;
 import org.apache.maven.surefire.report.RunStatistics;
 import org.apache.maven.surefire.report.StackTraceWriter;
+import org.apache.maven.plugin.surefire.log.api.Level;
 import org.apache.maven.surefire.suite.RunResult;
 
 import java.util.ArrayList;
@@ -47,6 +49,8 @@ import static org.apache.maven.plugin.surefire.report.DefaultReporterFactory.Tes
 import static org.apache.maven.plugin.surefire.report.ReportEntryType.ERROR;
 import static org.apache.maven.plugin.surefire.report.ReportEntryType.FAILURE;
 import static org.apache.maven.plugin.surefire.report.ReportEntryType.SUCCESS;
+import static org.apache.maven.plugin.surefire.log.api.Level.resolveLevel;
+import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
 
 /**
  * Provides reporting modules on the plugin side.
@@ -58,13 +62,12 @@ import static org.apache.maven.plugin.surefire.report.ReportEntryType.SUCCESS;
 public class DefaultReporterFactory
     implements ReporterFactory
 {
-    private RunStatistics globalStats = new RunStatistics();
-
     private final StartupReportConfiguration reportConfiguration;
-
+    private final ConsoleLogger consoleLogger;
     private final StatisticsReporter statisticsReporter;
+    private final Collection<TestSetRunListener> listeners;
 
-    private final Collection<TestSetRunListener> listeners = new ConcurrentLinkedQueue<TestSetRunListener>();
+    private RunStatistics globalStats = new RunStatistics();
 
     // from "<testclass>.<testmethod>" -> statistics about all the runs for flaky tests
     private Map<String, List<TestMethodStats>> flakyTests;
@@ -75,16 +78,19 @@ public class DefaultReporterFactory
     // from "<testclass>.<testmethod>" -> statistics about all the runs for error tests
     private Map<String, List<TestMethodStats>> errorTests;
 
-    public DefaultReporterFactory( StartupReportConfiguration reportConfiguration )
+    public DefaultReporterFactory( StartupReportConfiguration reportConfiguration, ConsoleLogger consoleLogger )
     {
         this.reportConfiguration = reportConfiguration;
+        this.consoleLogger = consoleLogger;
         statisticsReporter = reportConfiguration.instantiateStatisticsReporter();
+        listeners = new ConcurrentLinkedQueue<TestSetRunListener>();
     }
 
     public RunListener createReporter()
     {
+        ConsoleReporter consoleReporter = shouldReportToConsole() ? new ConsoleReporter( consoleLogger ) : null;
         TestSetRunListener testSetRunListener =
-            new TestSetRunListener( reportConfiguration.instantiateConsoleReporter(),
+            new TestSetRunListener( consoleReporter,
                                     reportConfiguration.instantiateFileReporter(),
                                     reportConfiguration.instantiateStatelessXmlReporter(),
                                     reportConfiguration.instantiateConsoleOutputFileReporter(),
@@ -96,6 +102,13 @@ public class DefaultReporterFactory
         return testSetRunListener;
     }
 
+    private boolean shouldReportToConsole()
+    {
+        return reportConfiguration.isUseFile()
+                       ? reportConfiguration.isPrintSummary()
+                       : reportConfiguration.isRedirectTestOutputToFile() || reportConfiguration.isBriefOrPlainFormat();
+    }
+
     public void mergeFromOtherFactories( Collection<DefaultReporterFactory> factories )
     {
         for ( DefaultReporterFactory factory : factories )
@@ -123,38 +136,33 @@ public class DefaultReporterFactory
         return globalStats.getRunResult();
     }
 
-    private DefaultDirectConsoleReporter createConsoleLogger()
-    {
-        return new DefaultDirectConsoleReporter( reportConfiguration.getOriginalSystemOut() );
-    }
-
     public void runStarting()
     {
-        ConsoleLogger consoleReporter = createConsoleLogger();
-        consoleReporter.info( "" );
-        consoleReporter.info( "-------------------------------------------------------" );
-        consoleReporter.info( " T E S T S" );
-        consoleReporter.info( "-------------------------------------------------------" );
+        log( "" );
+        log( "-------------------------------------------------------" );
+        log( " T E S T S" );
+        log( "-------------------------------------------------------" );
     }
 
     private void runCompleted()
     {
-        final ConsoleLogger logger = createConsoleLogger();
         if ( reportConfiguration.isPrintSummary() )
         {
-            logger.info( "" );
-            logger.info( "Results:" );
-            logger.info( "" );
+            log( "" );
+            log( "Results:" );
+            log( "" );
         }
-        boolean printedFailures = printTestFailures( logger, failure );
-        printedFailures |= printTestFailures( logger, error );
-        printedFailures |= printTestFailures( logger, flake );
-        if ( printedFailures )
+        boolean printedFailures = printTestFailures( failure );
+        boolean printedErrors = printTestFailures( error );
+        boolean printedFlakes = printTestFailures( flake );
+        if ( printedFailures | printedErrors | printedFlakes )
         {
-            logger.info( "" );
+            log( "" );
         }
-        logger.info( globalStats.getSummary() );
-        logger.info( "" );
+        boolean hasSuccessful = globalStats.getCompletedCount() > 0;
+        boolean hasSkipped = globalStats.getSkipped() > 0;
+        log( globalStats.getSummary(), hasSuccessful, printedFailures, printedErrors, hasSkipped, printedFlakes );
+        log( "" );
     }
 
     public RunStatistics getGlobalRunStatistics()
@@ -168,7 +176,7 @@ public class DefaultReporterFactory
      */
     public static DefaultReporterFactory defaultNoXml()
     {
-        return new DefaultReporterFactory( StartupReportConfiguration.defaultNoXml() );
+        return new DefaultReporterFactory( StartupReportConfiguration.defaultNoXml(), new NullConsoleLogger() );
     }
 
     /**
@@ -318,24 +326,27 @@ public class DefaultReporterFactory
      * Print failed tests and flaked tests. A test is considered as a failed test if it failed/got an error with
      * all the runs. If a test passes in ever of the reruns, it will be count as a flaked test
      *
-     * @param logger the logger used to log information
      * @param type   the type of results to be printed, could be error, failure or flake
      * @return {@code true} if printed some lines
      */
     // Use default visibility for testing
-    boolean printTestFailures( ConsoleLogger logger, TestResultType type )
+    boolean printTestFailures( TestResultType type )
     {
         final Map<String, List<TestMethodStats>> testStats;
+        final Level level;
         switch ( type )
         {
             case failure:
                 testStats = failedTests;
+                level = Level.FAILURE;
                 break;
             case error:
                 testStats = errorTests;
+                level = Level.FAILURE;
                 break;
             case flake:
                 testStats = flakyTests;
+                level = Level.UNSTABLE;
                 break;
             default:
                 return false;
@@ -344,7 +355,7 @@ public class DefaultReporterFactory
         boolean printed = false;
         if ( !testStats.isEmpty() )
         {
-            logger.info( type.getLogPrefix() );
+            log( type.getLogPrefix(), level );
             printed = true;
         }
 
@@ -355,24 +366,24 @@ public class DefaultReporterFactory
             if ( testMethodStats.size() == 1 )
             {
                 // No rerun, follow the original output format
-                logger.info( "  " + testMethodStats.get( 0 ).getStackTraceWriter().smartTrimmedStackTrace() );
+                failure( "  " + testMethodStats.get( 0 ).getStackTraceWriter().smartTrimmedStackTrace() );
             }
             else
             {
-                logger.info( entry.getKey() );
+                log( entry.getKey(), level );
                 for ( int i = 0; i < testMethodStats.size(); i++ )
                 {
                     StackTraceWriter failureStackTrace = testMethodStats.get( i ).getStackTraceWriter();
                     if ( failureStackTrace == null )
                     {
-                        logger.info( "  Run " + ( i + 1 ) + ": PASS" );
+                        success( "  Run " + ( i + 1 ) + ": PASS" );
                     }
                     else
                     {
-                        logger.info( "  Run " + ( i + 1 ) + ": " + failureStackTrace.smartTrimmedStackTrace() );
+                        failure( "  Run " + ( i + 1 ) + ": " + failureStackTrace.smartTrimmedStackTrace() );
                     }
                 }
-                logger.info( "" );
+                log( "" );
             }
         }
         return printed;
@@ -401,4 +412,58 @@ public class DefaultReporterFactory
             return logPrefix;
         }
     }
+
+    private void log( String s, boolean success, boolean failures, boolean errors, boolean skipped, boolean flakes )
+    {
+        Level level = resolveLevel( success, failures, errors, skipped, flakes );
+        log( s, level );
+    }
+
+    private void log( String s, Level level )
+    {
+        MessageBuilder builder = buffer();
+        switch ( level )
+        {
+            case FAILURE:
+                consoleLogger.error( builder.failure( s ).toString() );
+                break;
+            case UNSTABLE:
+                consoleLogger.warning( builder.warning( s ).toString() );
+                break;
+            case SUCCESS:
+                consoleLogger.info( builder.info( s ).toString() );
+                break;
+            default:
+                consoleLogger.info( builder.a( s ).toString() );
+        }
+    }
+
+    private void log( String s )
+    {
+        consoleLogger.info( s );
+    }
+
+    private void info( String s )
+    {
+        MessageBuilder builder = buffer();
+        consoleLogger.info( builder.info( s ).toString() );
+    }
+
+    private void err( String s )
+    {
+        MessageBuilder builder = buffer();
+        consoleLogger.error( builder.error( s ).toString() );
+    }
+
+    private void success( String s )
+    {
+        MessageBuilder builder = buffer();
+        consoleLogger.info( builder.success( s ).toString() );
+    }
+
+    private void failure( String s )
+    {
+        MessageBuilder builder = buffer();
+        consoleLogger.error( builder.failure( s ).toString() );
+    }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DirectConsoleOutput.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DirectConsoleOutput.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DirectConsoleOutput.java
index bd5ba7c..25312aa 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DirectConsoleOutput.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DirectConsoleOutput.java
@@ -23,10 +23,11 @@ import java.io.PrintStream;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.CharacterCodingException;
-import java.nio.charset.Charset;
 
 import org.apache.maven.surefire.report.ReportEntry;
 
+import static java.nio.charset.Charset.defaultCharset;
+
 /**
  * Outputs test system out/system err directly to the console
  * <p/>
@@ -51,11 +52,10 @@ public class DirectConsoleOutput
 
     public void writeTestOutput( byte[] buf, int off, int len, boolean stdout )
     {
-        PrintStream stream = stdout ? sout : serr;
-
+        final PrintStream stream = stdout ? sout : serr;
         try
         {
-            CharBuffer decode = Charset.defaultCharset().newDecoder().decode( ByteBuffer.wrap( buf, off, len ) );
+            CharBuffer decode = defaultCharset().newDecoder().decode( ByteBuffer.wrap( buf, off, len ) );
             stream.append( decode );
         }
         catch ( CharacterCodingException e )
@@ -74,6 +74,5 @@ public class DirectConsoleOutput
 
     public void close()
     {
-        //To change body of implemented methods use File | Settings | File Templates.
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/FileReporter.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/FileReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/FileReporter.java
index 2e862cf..a4d8c8e 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/FileReporter.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/FileReporter.java
@@ -29,6 +29,7 @@ import java.io.PrintWriter;
 import java.util.List;
 
 import static org.apache.maven.plugin.surefire.report.FileReporterUtils.stripIllegalFilenameChars;
+import static org.apache.maven.surefire.util.internal.StringUtils.isNotBlank;
 
 /**
  * Base class for file reporters.
@@ -40,14 +41,11 @@ public class FileReporter
 {
     private final File reportsDirectory;
 
-    private final boolean deleteOnStarting;
-
     private final String reportNameSuffix;
 
     public FileReporter( File reportsDirectory, String reportNameSuffix )
     {
         this.reportsDirectory = reportsDirectory;
-        this.deleteOnStarting = false;
         this.reportNameSuffix = reportNameSuffix;
     }
 
@@ -60,12 +58,6 @@ public class FileReporter
         // noinspection ResultOfMethodCallIgnored
         reportDir.mkdirs();
 
-        if ( deleteOnStarting && reportFile.exists() )
-        {
-            // noinspection ResultOfMethodCallIgnored
-            reportFile.delete();
-        }
-
         try
         {
             PrintWriter writer = new PrintWriter( new FileWriter( reportFile ) );
@@ -87,19 +79,9 @@ public class FileReporter
     public static File getReportFile( File reportsDirectory, String reportEntryName, String reportNameSuffix,
                                       String fileExtension )
     {
-        File reportFile;
-
-        if ( reportNameSuffix != null && reportNameSuffix.length() > 0 )
-        {
-            reportFile =
-                new File( reportsDirectory, stripIllegalFilenameChars( reportEntryName + "-" + reportNameSuffix
-                    + fileExtension ) );
-        }
-        else
-        {
-            reportFile = new File( reportsDirectory, stripIllegalFilenameChars( reportEntryName + fileExtension ) );
-        }
-        return reportFile;
+        String fileName =
+                reportEntryName + ( isNotBlank( reportNameSuffix ) ? "-" + reportNameSuffix : "" ) + fileExtension;
+        return new File( reportsDirectory, stripIllegalFilenameChars( fileName ) );
     }
 
     public void testSetCompleted( WrappedReportEntry report, TestSetStats testSetStats, List<String> testResults )
@@ -107,16 +89,11 @@ public class FileReporter
         PrintWriter writer = testSetStarting( report );
         try
         {
-            writer.print( testSetStats.getTestSetSummary( report ) );
-
-            if ( testResults != null )
+            writer.println( testSetStats.getTestSetSummary( report ) );
+            for ( String testResult : testResults )
             {
-                for ( String testResult : testResults )
-                {
-                    writer.println( testResult );
-                }
+                writer.println( testResult );
             }
-
             writer.flush();
         }
         finally

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java
index 2bb187f..4b12884 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java
@@ -21,14 +21,20 @@ package org.apache.maven.plugin.surefire.report;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 import org.apache.maven.plugin.surefire.runorder.StatisticsReporter;
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.surefire.report.ConsoleOutputReceiver;
 import org.apache.maven.surefire.report.ReportEntry;
 import org.apache.maven.surefire.report.RunListener;
 
+import static org.apache.maven.plugin.surefire.report.ReportEntryType.ERROR;
+import static org.apache.maven.plugin.surefire.report.ReportEntryType.FAILURE;
+import static org.apache.maven.plugin.surefire.report.ReportEntryType.SKIPPED;
+import static org.apache.maven.plugin.surefire.report.ReportEntryType.SUCCESS;
+
 /**
  * Reports data for a single test set.
  * <p/>
@@ -76,15 +82,55 @@ public class TestSetRunListener
         this.simpleXMLReporter = simpleXMLReporter;
         this.consoleOutputReceiver = consoleOutputReceiver;
         this.briefOrPlainFormat = briefOrPlainFormat;
-        this.detailsForThis = new TestSetStats( trimStackTrace, isPlainFormat );
-        this.testMethodStats = new ArrayList<TestMethodStats>(  );
+        detailsForThis = new TestSetStats( trimStackTrace, isPlainFormat );
+        testMethodStats = new ArrayList<TestMethodStats>();
+    }
+
+    public void debug( String message )
+    {
+        if ( consoleReporter != null )
+        {
+            consoleReporter.getConsoleLogger().debug( trimTrailingNewLine( message ) );
+        }
     }
 
     public void info( String message )
     {
         if ( consoleReporter != null )
         {
-            consoleReporter.writeMessage( message );
+            consoleReporter.getConsoleLogger().info( trimTrailingNewLine( message ) );
+        }
+    }
+
+    public void warning( String message )
+    {
+        if ( consoleReporter != null )
+        {
+            consoleReporter.getConsoleLogger().warning( trimTrailingNewLine( message ) );
+        }
+    }
+
+    public void error( String message )
+    {
+        if ( consoleReporter != null )
+        {
+            consoleReporter.getConsoleLogger().error( trimTrailingNewLine( message ) );
+        }
+    }
+
+    public void error( String message, Throwable t )
+    {
+        if ( consoleReporter != null )
+        {
+            consoleReporter.getConsoleLogger().error( message, t );
+        }
+    }
+
+    public void error( Throwable t )
+    {
+        if ( consoleReporter != null )
+        {
+            consoleReporter.getConsoleLogger().error( t );
         }
     }
 
@@ -126,8 +172,9 @@ public class TestSetRunListener
 
     public void testSetCompleted( ReportEntry report )
     {
-        WrappedReportEntry wrap = wrapTestSet( report );
-        List<String> testResults = briefOrPlainFormat ? detailsForThis.getTestResults() : null;
+        final WrappedReportEntry wrap = wrapTestSet( report );
+        final List<String> testResults =
+                briefOrPlainFormat ? detailsForThis.getTestResults() : Collections.<String>emptyList();
         if ( fileReporter != null )
         {
             fileReporter.testSetCompleted( wrap, detailsForThis, testResults );
@@ -169,7 +216,7 @@ public class TestSetRunListener
 
     public void testSucceeded( ReportEntry reportEntry )
     {
-        WrappedReportEntry wrapped = wrap( reportEntry, ReportEntryType.SUCCESS );
+        WrappedReportEntry wrapped = wrap( reportEntry, SUCCESS );
         detailsForThis.testSucceeded( wrapped );
         if ( statisticsReporter != null )
         {
@@ -180,7 +227,7 @@ public class TestSetRunListener
 
     public void testError( ReportEntry reportEntry )
     {
-        WrappedReportEntry wrapped = wrap( reportEntry, ReportEntryType.ERROR );
+        WrappedReportEntry wrapped = wrap( reportEntry, ERROR );
         detailsForThis.testError( wrapped );
         if ( statisticsReporter != null )
         {
@@ -191,7 +238,7 @@ public class TestSetRunListener
 
     public void testFailed( ReportEntry reportEntry )
     {
-        WrappedReportEntry wrapped = wrap( reportEntry, ReportEntryType.FAILURE );
+        WrappedReportEntry wrapped = wrap( reportEntry, FAILURE );
         detailsForThis.testFailure( wrapped );
         if ( statisticsReporter != null )
         {
@@ -206,7 +253,7 @@ public class TestSetRunListener
 
     public void testSkipped( ReportEntry reportEntry )
     {
-        WrappedReportEntry wrapped = wrap( reportEntry, ReportEntryType.SKIPPED );
+        WrappedReportEntry wrapped = wrap( reportEntry, SKIPPED );
 
         detailsForThis.testSkipped( wrapped );
         if ( statisticsReporter != null )
@@ -228,7 +275,7 @@ public class TestSetRunListener
     private WrappedReportEntry wrap( ReportEntry other, ReportEntryType reportEntryType )
     {
         final int estimatedElapsed;
-        if ( reportEntryType != ReportEntryType.SKIPPED )
+        if ( reportEntryType != SKIPPED )
         {
             if ( other.getElapsed() != null )
             {
@@ -277,4 +324,15 @@ public class TestSetRunListener
     {
         return testMethodStats;
     }
+
+    public static String trimTrailingNewLine( final String message )
+    {
+        final int e = message == null ? 0 : lineBoundSymbolWidth( message );
+        return message != null && e != 0 ? message.substring( 0, message.length() - e ) : message;
+    }
+
+    private static int lineBoundSymbolWidth( String message )
+    {
+        return message.endsWith( "\n" ) || message.endsWith( "\r" ) ? 1 : ( message.endsWith( "\r\n" ) ? 2 : 0 );
+    }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetStats.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetStats.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetStats.java
index e5b47d2..9fcfafe 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetStats.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetStats.java
@@ -19,17 +19,32 @@ package org.apache.maven.plugin.surefire.report;
  * under the License.
  */
 
+import org.apache.maven.shared.utils.logging.MessageBuilder;
+import org.apache.maven.surefire.report.ReportEntry;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Queue;
 import java.util.concurrent.ConcurrentLinkedQueue;
 
+import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
+
 /**
  * Maintains per-thread test result state. Not thread safe.
  */
 public class TestSetStats
 {
+    private static final String TESTS = "Tests ";
+    private static final String RUN = "run: ";
+    private static final String TESTS_RUN = "Tests run: ";
+    private static final String FAILURES = "Failures: ";
+    private static final String ERRORS = "Errors: ";
+    private static final String SKIPPED = "Skipped: ";
+    private static final String FAILURE_MARKER = " <<< FAILURE!";
+    private static final String IN_MARKER = " - in ";
+    private static final String COMMA = ", ";
+
     private final Queue<WrappedReportEntry> reportEntries = new ConcurrentLinkedQueue<WrappedReportEntry>();
 
     private final boolean trimStackTrace;
@@ -164,21 +179,100 @@ public class TestSetStats
 
     public String getTestSetSummary( WrappedReportEntry reportEntry )
     {
-        String summary =
-                "Tests run: " + completedCount
-                        +  ", Failures: " + failures + ", Errors: " + errors + ", Skipped: " + skipped + ", "
-                        + reportEntry.getElapsedTimeVerbose();
+        String summary = TESTS_RUN + completedCount
+                                 + COMMA
+                                 + FAILURES + failures
+                                 + COMMA
+                                 + ERRORS + errors
+                                 + COMMA
+                                 + SKIPPED + skipped
+                                 + COMMA
+                                 + reportEntry.getElapsedTimeVerbose();
 
         if ( failures > 0 || errors > 0 )
         {
-            summary += " <<< FAILURE!";
+            summary += FAILURE_MARKER;
         }
 
-        summary += " - in " + reportEntry.getNameWithGroup() + "\n";
+        summary += IN_MARKER + reportEntry.getNameWithGroup();
 
         return summary;
     }
 
+    public String getColoredTestSetSummary( WrappedReportEntry reportEntry )
+    {
+        final boolean isSuccessful = failures == 0 && errors == 0 && skipped == 0;
+        final boolean isFailure = failures > 0;
+        final boolean isError = errors > 0;
+        final boolean isFailureOrError = isFailure | isError;
+        final boolean isSkipped = skipped > 0;
+        final  MessageBuilder builder = buffer();
+        if ( isSuccessful )
+        {
+            if ( completedCount == 0 )
+            {
+                builder.strong( TESTS_RUN ).strong( completedCount );
+            }
+            else
+            {
+                builder.success( TESTS_RUN ).success( completedCount );
+            }
+        }
+        else
+        {
+            if ( isFailureOrError )
+            {
+                builder.failure( TESTS ).strong( RUN ).strong( completedCount );
+            }
+            else
+            {
+                builder.warning( TESTS ).strong( RUN ).strong( completedCount );
+            }
+        }
+        builder.a( COMMA );
+        if ( isFailure )
+        {
+            builder.failure( FAILURES ).failure( failures );
+        }
+        else
+        {
+            builder.a( FAILURES ).a( failures );
+        }
+        builder.a( COMMA );
+        if ( isError )
+        {
+            builder.failure( ERRORS ).failure( errors );
+        }
+        else
+        {
+            builder.a( ERRORS ).a( errors );
+        }
+        builder.a( COMMA );
+        if ( isSkipped )
+        {
+            builder.failure( SKIPPED ).failure( skipped );
+        }
+        else
+        {
+            builder.a( SKIPPED ).a( skipped );
+        }
+        builder.a( COMMA )
+                .a( reportEntry.getElapsedTimeVerbose() );
+        if ( isFailureOrError )
+        {
+            if ( isFailure )
+            {
+                builder.failure( FAILURE_MARKER );
+            }
+            else
+            {
+                builder.warning( FAILURE_MARKER );
+            }
+        }
+        builder.a( IN_MARKER );
+        return concatenateWithTestGroup( builder, reportEntry );
+    }
+
     public List<String> getTestResults()
     {
         List<String> result = new ArrayList<String>();
@@ -204,4 +298,23 @@ public class TestSetStats
     {
         return reportEntries;
     }
+
+    /**
+     * Append the test set message for a report.
+     * e.g. "org.foo.BarTest ( of group )"
+     *
+     * @param builder    MessageBuilder with preceded text inside
+     * @param report     report whose test set is starting
+     * @return the message
+     */
+    public static String concatenateWithTestGroup( MessageBuilder builder, ReportEntry report )
+    {
+        final String testClass = report.getNameWithGroup();
+        int delimiter = testClass.lastIndexOf( '.' );
+        String pkg = testClass.substring( 0, 1 + delimiter );
+        String cls = testClass.substring( 1 + delimiter );
+        return builder.a( pkg )
+                       .strong( cls )
+                       .toString();
+    }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/RunStatistics.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/RunStatistics.java b/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/RunStatistics.java
index bcd5286..29aa8dc 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/RunStatistics.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/RunStatistics.java
@@ -37,10 +37,6 @@ public class RunStatistics
 
     private int flakes;
 
-    public RunStatistics()
-    {
-    }
-
     public synchronized boolean hadFailures()
     {
         return failures > 0;

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/surefire/spi/ServiceLoader.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/surefire/spi/ServiceLoader.java b/maven-surefire-common/src/main/java/org/apache/maven/surefire/spi/ServiceLoader.java
new file mode 100644
index 0000000..c23e5d6
--- /dev/null
+++ b/maven-surefire-common/src/main/java/org/apache/maven/surefire/spi/ServiceLoader.java
@@ -0,0 +1,171 @@
+package org.apache.maven.surefire.spi;
+
+/*
+ * 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 javax.annotation.Nonnull;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Set;
+
+import static java.lang.Character.isJavaIdentifierPart;
+import static java.lang.Character.isJavaIdentifierStart;
+import static java.util.Collections.emptySet;
+import static org.apache.maven.surefire.util.ReflectionUtils.getConstructor;
+
+/**
+ * SPI loader for Java 1.5.
+ *
+ * @since 2.19.2
+ */
+public class ServiceLoader
+{
+
+    @Nonnull
+    @SuppressWarnings( "unchecked" )
+    public <T> Set<T> load( Class<T> clazz, ClassLoader classLoader )
+    {
+        try
+        {
+            Set<T> implementations = new HashSet<T>();
+            for ( String fullyQualifiedClassName : lookup( clazz, classLoader ) )
+            {
+                Class<?> implClass = classLoader.loadClass( fullyQualifiedClassName );
+                implementations.add( (T) getConstructor( implClass ).newInstance() );
+            }
+            return implementations;
+        }
+        catch ( IOException e )
+        {
+            throw new IllegalStateException( e.getLocalizedMessage(), e );
+        }
+        catch ( ClassNotFoundException e )
+        {
+            throw new IllegalStateException( e.getLocalizedMessage(), e );
+        }
+        catch ( InvocationTargetException e )
+        {
+            throw new IllegalStateException( e.getLocalizedMessage(), e );
+        }
+        catch ( InstantiationException e )
+        {
+            throw new IllegalStateException( e.getLocalizedMessage(), e );
+        }
+        catch ( IllegalAccessException e )
+        {
+            throw new IllegalStateException( e.getLocalizedMessage(), e );
+        }
+    }
+
+    @Nonnull
+    public Set<String> lookup( Class<?> clazz, ClassLoader classLoader )
+            throws IOException
+    {
+        final String resourceName = "META-INF/services/" + clazz.getName();
+
+        if ( classLoader == null )
+        {
+            return emptySet();
+        }
+        final Enumeration<URL> urls = classLoader.getResources( resourceName );
+        return lookupSpiImplementations( urls );
+    }
+
+    /**
+     * Method loadServices loads the services of a class that are
+     * defined using the SPI mechanism.
+     *
+     * @param urlEnumeration The urls from the resource
+     * @return The set of service provider names
+     * @throws IOException When reading the streams fails
+     */
+    @Nonnull
+    @SuppressWarnings( "checkstyle:innerassignment" )
+    private static Set<String> lookupSpiImplementations( final Enumeration<URL> urlEnumeration )
+            throws IOException
+    {
+        final Set<String> names = new HashSet<String>();
+        nextUrl:
+        while ( urlEnumeration.hasMoreElements() )
+        {
+            final URL url = urlEnumeration.nextElement();
+            final BufferedReader reader = getReader( url );
+            try
+            {
+                for ( String line; ( line = reader.readLine() ) != null; )
+                {
+                    int ci = line.indexOf( '#' );
+                    if ( ci >= 0 )
+                    {
+                        line = line.substring( 0, ci );
+                    }
+                    line = line.trim();
+                    int n = line.length();
+                    if ( n == 0 )
+                    {
+                        continue; // next line
+                    }
+
+                    if ( line.indexOf( ' ' ) >= 0 || line.indexOf( '\t' ) >= 0 )
+                    {
+                        continue nextUrl; // next url
+                    }
+                    char cp = line.charAt( 0 ); // should use codePointAt but this was JDK1.3
+                    if ( !isJavaIdentifierStart( cp ) )
+                    {
+                        continue nextUrl; // next url
+                    }
+                    for ( int i = 1; i < n; i++ )
+                    {
+                        cp = line.charAt( i );  // should use codePointAt but this was JDK1.3
+                        if ( !isJavaIdentifierPart( cp ) && cp != '.' )
+                        {
+                            continue nextUrl; // next url
+                        }
+                    }
+                    if ( !names.contains( line ) )
+                    {
+                        names.add( line );
+                    }
+                }
+            }
+            finally
+            {
+                reader.close();
+            }
+        }
+
+        return names;
+    }
+
+    @Nonnull
+    private static BufferedReader getReader( @Nonnull URL url )
+            throws IOException
+    {
+        final InputStream inputStream = url.openStream();
+        final InputStreamReader inputStreamReader = new InputStreamReader( inputStream );
+        return new BufferedReader( inputStreamReader );
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireReflectorTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireReflectorTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireReflectorTest.java
new file mode 100644
index 0000000..cd31d34
--- /dev/null
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireReflectorTest.java
@@ -0,0 +1 @@
+package org.apache.maven.plugin.surefire;

/*
 * 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.apache.maven.plugin.surefire.log.api.ConsoleLogger;
import org.apache.maven.plugin.surefire.log.api.ConsoleLoggerDecorator;
import o
 rg.apache.maven.plugin.surefire.log.api.PrintStreamLogger;
import org.apache.maven.surefire.booter.IsolatedClassLoader;
import org.apache.maven.surefire.booter.SurefireReflector;
import org.junit.Before;
import org.junit.Test;

import static org.apache.maven.surefire.util.ReflectionUtils.getMethod;
import static org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

/**
 * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
 * @see ConsoleLogger
 * @see SurefireReflector
 * @since 2.19.2
 */
public class SurefireReflectorTest
{
     private ConsoleLogger logger;
    private SurefireReflector reflector;

    @Before
    public void prepareData()
    {
        logger = spy( new PrintStreamLogger( System.out ) );
        ClassLoader cl = new IsolatedClassLoader( Thread.currentThread().getContextClassLoader(), false, "role" );
        reflector = new SurefireReflector( cl );
    }

    @Test
    public void shouldProxyConsoleLogger()
    {
        Object mirror = reflector.createConsoleLogger( logger );
        assertThat( mirror, is( notNullValue() ) );
        assertThat( mirror.getClass().getInterfaces()[0].getName(), is( ConsoleLogger.class.getName() ) );
        assertThat( mirror, is( not( sameInstance( (Object) logger ) ) ) );
        assertThat( mirror, is( instanceOf( ConsoleLoggerDecorator.class ) ) );
        invokeMethodWithArray( mirror, getMethod( mirror, "info", String.class ), "Hi There!" );
        verify( logger, times( 1 ) ).info( "Hi There!" );
    }
}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java
index 63d3417..cccb14b 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java
@@ -30,7 +30,8 @@ import java.util.StringTokenizer;
 import org.apache.maven.plugin.surefire.booterclient.output.ForkClient;
 import org.apache.maven.surefire.booter.ForkingRunListener;
 import org.apache.maven.surefire.report.CategorizedReportEntry;
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger;
 import org.apache.maven.surefire.report.ConsoleOutputReceiver;
 import org.apache.maven.surefire.report.LegacyPojoStackTraceWriter;
 import org.apache.maven.surefire.report.ReportEntry;
@@ -220,8 +221,9 @@ public class ForkingRunListenerTest
 
         TestSetMockReporterFactory providerReporterFactory = new TestSetMockReporterFactory();
         final Properties testVmSystemProperties = new Properties();
+        NullConsoleLogger log = new NullConsoleLogger();
         ForkClient forkStreamClient = new ForkClient( providerReporterFactory, testVmSystemProperties,
-                                                      new MockNotifiableTestStream() );
+                                                      new MockNotifiableTestStream(), log );
 
         forkStreamClient.consumeMultiLineContent( content.toString( "utf-8" ) );
 
@@ -245,8 +247,9 @@ public class ForkingRunListenerTest
         forkingReporter.testSetCompleted( reportEntry );
 
         TestSetMockReporterFactory providerReporterFactory = new TestSetMockReporterFactory();
+        NullConsoleLogger log = new NullConsoleLogger();
         ForkClient forkStreamClient = new ForkClient( providerReporterFactory, new Properties(),
-                                                      new MockNotifiableTestStream() );
+                                                      new MockNotifiableTestStream(), log );
 
         forkStreamClient.consumeMultiLineContent( content.toString( "utf-8" ) );
 
@@ -269,8 +272,9 @@ public class ForkingRunListenerTest
         new ForkingRunListener( printStream, anotherChannel, false ).testSkipped( secondExpected );
 
         TestSetMockReporterFactory providerReporterFactory = new TestSetMockReporterFactory();
+        NullConsoleLogger log = new NullConsoleLogger();
         final ForkClient forkStreamClient = new ForkClient( providerReporterFactory, new Properties(),
-                                                            new MockNotifiableTestStream() );
+                                                            new MockNotifiableTestStream(), log );
         forkStreamClient.consumeMultiLineContent( content.toString( "utf-8" ) );
 
         MockReporter reporter = (MockReporter) forkStreamClient.getReporter( defaultChannel );
@@ -344,8 +348,9 @@ public class ForkingRunListenerTest
             throws ReporterException, IOException
         {
             TestSetMockReporterFactory providerReporterFactory = new TestSetMockReporterFactory();
+            NullConsoleLogger log = new NullConsoleLogger();
             final ForkClient forkStreamClient = new ForkClient( providerReporterFactory, new Properties(),
-                                                                new MockNotifiableTestStream() );
+                                                                new MockNotifiableTestStream(), log );
             forkStreamClient.consumeMultiLineContent( content.toString( ) );
             reporter = (MockReporter) forkStreamClient.getReporter( defaultChannel );
         }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java
index 3f2d221..b8c9ef0 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java
@@ -22,7 +22,7 @@ package org.apache.maven.plugin.surefire.booterclient;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.surefire.report.ConsoleOutputReceiver;
 import org.apache.maven.surefire.report.ReportEntry;
 import org.apache.maven.surefire.report.RunListener;
@@ -147,12 +147,38 @@ public class MockReporter
         testIgnored.incrementAndGet();
     }
 
+    public void debug( String message )
+    {
+        events.add( CONSOLE_OUTPUT );
+        data.add( message );
+    }
+
     public void info( String message )
     {
         events.add( CONSOLE_OUTPUT );
         data.add( message );
     }
 
+    public void warning( String message )
+    {
+        events.add( CONSOLE_OUTPUT );
+        data.add( message );
+    }
+
+    public void error( String message )
+    {
+        events.add( CONSOLE_OUTPUT );
+        data.add( message );
+    }
+
+    public void error( String message, Throwable t )
+    {
+    }
+
+    public void error( Throwable t )
+    {
+    }
+
     public void writeTestOutput( byte[] buf, int off, int len, boolean stdout )
     {
         events.add( stdout ? STDOUT : STDERR );

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
index 2e337e2..ada54a2 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
@@ -19,10 +19,12 @@ package org.apache.maven.plugin.surefire.booterclient;
  * under the License.
  */
 
-import org.apache.maven.plugin.surefire.StartupReportConfiguration;
 import org.apache.maven.plugin.surefire.report.DefaultReporterFactory;
+import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger;
 import org.apache.maven.surefire.report.RunListener;
 
+import static org.apache.maven.plugin.surefire.StartupReportConfiguration.defaultValue;
+
 /**
  * Internal tests use only.
  *
@@ -33,7 +35,7 @@ public class TestSetMockReporterFactory
 {
     public TestSetMockReporterFactory()
     {
-        super( StartupReportConfiguration.defaultValue() );
+        super( defaultValue(), new NullConsoleLogger() );
     }
 
     public RunListener createReporter()

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactoryTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactoryTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactoryTest.java
index 090a11b..0a0a9c8 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactoryTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactoryTest.java
@@ -21,30 +21,31 @@ package org.apache.maven.plugin.surefire.report;
 
 import java.io.File;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 import junit.framework.TestCase;
 
 import org.apache.maven.plugin.surefire.StartupReportConfiguration;
-import org.apache.maven.surefire.report.DefaultDirectConsoleReporter;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger;
 import org.apache.maven.surefire.report.RunStatistics;
 import org.apache.maven.surefire.report.SafeThrowable;
 import org.apache.maven.surefire.report.StackTraceWriter;
 
+import static java.util.Arrays.asList;
 import static org.apache.maven.plugin.surefire.report.DefaultReporterFactory.TestResultType.error;
 import static org.apache.maven.plugin.surefire.report.DefaultReporterFactory.TestResultType.failure;
 import static org.apache.maven.plugin.surefire.report.DefaultReporterFactory.TestResultType.flake;
 import static org.apache.maven.plugin.surefire.report.DefaultReporterFactory.TestResultType.skipped;
 import static org.apache.maven.plugin.surefire.report.DefaultReporterFactory.TestResultType.success;
 import static org.apache.maven.plugin.surefire.report.DefaultReporterFactory.TestResultType.unknown;
+import static org.apache.maven.plugin.surefire.report.DefaultReporterFactory.getTestResultType;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 public class DefaultReporterFactoryTest
     extends TestCase
 {
-
     private final static String TEST_ONE = "testOne";
 
     private final static String TEST_TWO = "testTwo";
@@ -61,10 +62,13 @@ public class DefaultReporterFactoryTest
 
     public void testMergeTestHistoryResult()
     {
-        StartupReportConfiguration reportConfig = new StartupReportConfiguration( true, true, "PLAIN", false, false, new File("target"), false, null, "TESTHASH",
-                                                                                                 false, 1, null );
+        StartupReportConfiguration reportConfig =
+                new StartupReportConfiguration( true, true, "PLAIN", false, false, new File("target"), false, null,
+                                                      "TESTHASH", false, 1, null );
+
+        DummyTestReporter reporter = new DummyTestReporter();
 
-        DefaultReporterFactory factory = new DefaultReporterFactory( reportConfig );
+        DefaultReporterFactory factory = new DefaultReporterFactory( reportConfig, reporter );
 
         // First run, four tests failed and one passed
         List<TestMethodStats> firstRunStats = new ArrayList<TestMethodStats>();
@@ -114,88 +118,108 @@ public class DefaultReporterFactoryTest
         assertEquals( 0, mergedStatistics.getSkipped() );
 
         // Now test the result will be printed out correctly
-        DummyTestReporter reporter = new DummyTestReporter();
-        factory.printTestFailures( reporter, DefaultReporterFactory.TestResultType.flake );
+        factory.printTestFailures( flake );
         String[] expectedFlakeOutput =
             { "Flaked tests: ", TEST_FOUR, "  Run 1: " + ASSERTION_FAIL, "  Run 2: PASS", "", TEST_ONE,
                 "  Run 1: " + ERROR, "  Run 2: " + ASSERTION_FAIL, "  Run 3: PASS", "", TEST_TWO, "  Run 1: " + ERROR,
                 "  Run 2: PASS", "" };
-        assertEquals( Arrays.asList( expectedFlakeOutput ), reporter.getMessages() );
+        assertEquals( asList( expectedFlakeOutput ), reporter.getMessages() );
 
-        reporter = new DummyTestReporter();
-        factory.printTestFailures( reporter, DefaultReporterFactory.TestResultType.error );
+        reporter.reset();
+        factory.printTestFailures( error );
         String[] expectedFailureOutput =
             { "Tests in error: ", TEST_THREE, "  Run 1: " + ASSERTION_FAIL, "  Run 2: " + ERROR, "  Run 3: " + ERROR, ""
             };
-        assertEquals( Arrays.asList( expectedFailureOutput ), reporter.getMessages() );
+        assertEquals( asList( expectedFailureOutput ), reporter.getMessages() );
 
-        reporter = new DummyTestReporter();
-        factory.printTestFailures( reporter, DefaultReporterFactory.TestResultType.failure );
+        reporter.reset();
+        factory.printTestFailures( failure );
         String[] expectedErrorOutput = { };
-        assertEquals( Arrays.asList( expectedErrorOutput ), reporter.getMessages() );
+        assertEquals( asList( expectedErrorOutput ), reporter.getMessages() );
     }
 
-    static class DummyTestReporter
-        extends DefaultDirectConsoleReporter
+    static final class DummyTestReporter implements ConsoleLogger
     {
-
         private final List<String> messages = new ArrayList<String>();
 
-        public DummyTestReporter()
+        public void debug( String message )
+        {
+            messages.add( message );
+        }
+
+        public void info( String message )
+        {
+            messages.add( message );
+        }
+
+        public void warning( String message )
+        {
+            messages.add( message );
+        }
+
+        public void error( String message )
+        {
+            messages.add( message );
+        }
+
+        public void error( String message, Throwable t )
         {
-            super( System.out );
+            messages.add( message );
         }
 
-        @Override
-        public void info( String msg )
+        public void error( Throwable t )
         {
-            messages.add( msg );
         }
 
-        public List<String> getMessages()
+        List<String> getMessages()
         {
             return messages;
         }
+
+        void reset()
+        {
+            messages.clear();
+        }
     }
 
     public void testGetTestResultType()
     {
         List<ReportEntryType> emptyList = new ArrayList<ReportEntryType>();
-        assertEquals( unknown, DefaultReporterFactory.getTestResultType( emptyList, 1 ) );
+        assertEquals( unknown, getTestResultType( emptyList, 1 ) );
 
         List<ReportEntryType> successList = new ArrayList<ReportEntryType>();
         successList.add( ReportEntryType.SUCCESS );
         successList.add( ReportEntryType.SUCCESS );
-        assertEquals( success, DefaultReporterFactory.getTestResultType( successList, 1 ) );
+        assertEquals( success, getTestResultType( successList, 1 ) );
 
         List<ReportEntryType> failureErrorList = new ArrayList<ReportEntryType>();
         failureErrorList.add( ReportEntryType.FAILURE );
         failureErrorList.add( ReportEntryType.ERROR );
-        assertEquals( error, DefaultReporterFactory.getTestResultType( failureErrorList, 1 ) );
+        assertEquals( error, getTestResultType( failureErrorList, 1 ) );
 
         List<ReportEntryType> errorFailureList = new ArrayList<ReportEntryType>();
         errorFailureList.add( ReportEntryType.ERROR );
         errorFailureList.add( ReportEntryType.FAILURE );
-        assertEquals( error, DefaultReporterFactory.getTestResultType( errorFailureList, 1 ) );
+        assertEquals( error, getTestResultType( errorFailureList, 1 ) );
 
         List<ReportEntryType> flakeList = new ArrayList<ReportEntryType>();
         flakeList.add( ReportEntryType.SUCCESS );
         flakeList.add( ReportEntryType.FAILURE );
-        assertEquals( flake, DefaultReporterFactory.getTestResultType( flakeList, 1 ) );
+        assertEquals( flake, getTestResultType( flakeList, 1 ) );
 
-        assertEquals( failure, DefaultReporterFactory.getTestResultType( flakeList, 0 ) );
+        assertEquals( failure, getTestResultType( flakeList, 0 ) );
 
         flakeList = new ArrayList<ReportEntryType>();
         flakeList.add( ReportEntryType.ERROR );
         flakeList.add( ReportEntryType.SUCCESS );
         flakeList.add( ReportEntryType.FAILURE );
-        assertEquals( flake, DefaultReporterFactory.getTestResultType( flakeList, 1 ) );
+        assertEquals( flake, getTestResultType( flakeList, 1 ) );
 
-        assertEquals( error, DefaultReporterFactory.getTestResultType( flakeList, 0 ) );
+        assertEquals( error, getTestResultType( flakeList, 0 ) );
 
         List<ReportEntryType> skippedList = new ArrayList<ReportEntryType>();
         skippedList.add( ReportEntryType.SKIPPED );
-        assertEquals( skipped, DefaultReporterFactory.getTestResultType( skippedList, 1 ) );
+        assertEquals( skipped, getTestResultType( skippedList, 1 ) );
     }
 
     static class DummyStackTraceWriter

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java
index 80cf5ff..d03f1b9 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java
@@ -21,6 +21,7 @@ package org.apache.maven.surefire;
 
 import junit.framework.JUnit4TestAdapter;
 import junit.framework.Test;
+import org.apache.maven.plugin.surefire.SurefireReflectorTest;
 import org.apache.maven.plugin.surefire.SurefirePropertiesTest;
 import org.apache.maven.plugin.surefire.booterclient.BooterDeserializerProviderConfigurationTest;
 import org.apache.maven.plugin.surefire.booterclient.BooterDeserializerStartupConfigurationTest;
@@ -38,6 +39,7 @@ import org.apache.maven.plugin.surefire.util.SpecificFileFilterTest;
 import org.apache.maven.surefire.report.ConsoleOutputFileReporterTest;
 import org.apache.maven.surefire.report.FileReporterTest;
 import org.apache.maven.surefire.report.RunStatisticsTest;
+import org.apache.maven.surefire.spi.SPITest;
 import org.apache.maven.surefire.util.RelocatorTest;
 import org.junit.runner.RunWith;
 import org.junit.runners.Suite;
@@ -66,7 +68,9 @@ import org.junit.runners.Suite;
     BooterDeserializerStartupConfigurationTest.class,
     BooterDeserializerProviderConfigurationTest.class,
     TestProvidingInputStreamTest.class,
-    TestLessInputStreamBuilderTest.class
+    TestLessInputStreamBuilderTest.class,
+    SPITest.class,
+    SurefireReflectorTest.class
 } )
 @RunWith( Suite.class )
 public class JUnit4SuiteTest

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/CustomizedImpl.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/CustomizedImpl.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/CustomizedImpl.java
new file mode 100644
index 0000000..70e2255
--- /dev/null
+++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/CustomizedImpl.java
@@ -0,0 +1,33 @@
+package org.apache.maven.surefire.spi;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19.2
+ */
+public class CustomizedImpl
+    implements IDefault
+{
+    public boolean isDefault()
+    {
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/DefaultImpl.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/DefaultImpl.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/DefaultImpl.java
new file mode 100644
index 0000000..e623f0b
--- /dev/null
+++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/DefaultImpl.java
@@ -0,0 +1,33 @@
+package org.apache.maven.surefire.spi;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19.2
+ */
+public class DefaultImpl
+    implements IDefault
+{
+    public boolean isDefault()
+    {
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/EmptyServiceInterface.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/EmptyServiceInterface.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/EmptyServiceInterface.java
new file mode 100644
index 0000000..38a186c
--- /dev/null
+++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/EmptyServiceInterface.java
@@ -0,0 +1,30 @@
+package org.apache.maven.surefire.spi;
+
+/*
+ * 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.
+ */
+
+
+/**
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19.2
+ */
+public interface EmptyServiceInterface
+{
+    String whoAmI();
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/ExistingServiceInterface.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/ExistingServiceInterface.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/ExistingServiceInterface.java
new file mode 100644
index 0000000..9d7fa25
--- /dev/null
+++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/ExistingServiceInterface.java
@@ -0,0 +1,30 @@
+package org.apache.maven.surefire.spi;
+
+/*
+ * 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.
+ */
+
+
+/**
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19.2
+ */
+public interface ExistingServiceInterface
+{
+    String whoAmI();
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/IDefault.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/IDefault.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/IDefault.java
new file mode 100644
index 0000000..53b7b38
--- /dev/null
+++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/IDefault.java
@@ -0,0 +1,33 @@
+package org.apache.maven.surefire.spi;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19.2
+ */
+public interface IDefault
+{
+    /**
+     * @return <tt>true</tt> if SPI implementation vendor is maven-surefire-plugin or maven-failsafe-plugin.
+     * <tt>false</tt> if customized by users.
+     */
+    boolean isDefault();
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/NoServiceInterface.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/NoServiceInterface.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/NoServiceInterface.java
new file mode 100644
index 0000000..af649b9
--- /dev/null
+++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/NoServiceInterface.java
@@ -0,0 +1,30 @@
+package org.apache.maven.surefire.spi;
+
+/*
+ * 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.
+ */
+
+
+/**
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19.2
+ */
+public interface NoServiceInterface
+{
+    void dummyService();
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/SPITest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/SPITest.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/SPITest.java
new file mode 100644
index 0000000..a8058f8
--- /dev/null
+++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/SPITest.java
@@ -0,0 +1,89 @@
+package org.apache.maven.surefire.spi;
+
+/*
+ * 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.apache.maven.plugin.surefire.booterclient.ProviderDetector;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static java.lang.Thread.currentThread;
+import static org.fest.assertions.Assertions.assertThat;
+
+/**
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19.2
+ */
+public class SPITest
+{
+    private final ServiceLoader spi = new ServiceLoader();
+    private final ProviderDetector providerDetector = new ProviderDetector();
+    private final ClassLoader ctx = currentThread().getContextClassLoader();
+
+    @Test
+    public void shouldNotLoadSpiDoesNotExist() throws IOException
+    {
+        assertThat( spi.lookup( NoServiceInterface.class, ctx ) )
+                .isEmpty();
+
+        assertThat( spi.load( NoServiceInterface.class, ctx ) )
+                .isEmpty();
+
+        assertThat( providerDetector.lookupServiceNames( NoServiceInterface.class, ctx ) )
+                .isEmpty();
+    }
+
+    @Test
+    public void shouldNotLoadEmptySpi() throws IOException
+    {
+        assertThat( spi.lookup( EmptyServiceInterface.class, ctx ) )
+                .isEmpty();
+
+        assertThat( spi.load( EmptyServiceInterface.class, ctx ) )
+                .isEmpty();
+
+        assertThat( providerDetector.lookupServiceNames( EmptyServiceInterface.class, ctx ) )
+                .isEmpty();
+    }
+
+    @Test
+    public void shouldLoad2SpiObjects() throws IOException
+    {
+        assertThat( spi.lookup( ExistingServiceInterface.class, ctx ) )
+                .hasSize( 2 );
+
+        assertThat( spi.lookup( ExistingServiceInterface.class, ctx ) )
+                .containsOnly( SPImpl1.class.getName(), SPImpl2.class.getName() );
+
+
+        assertThat( spi.load( ExistingServiceInterface.class, ctx ) )
+                .hasSize( 2 );
+
+        assertThat( spi.load( ExistingServiceInterface.class, ctx ) )
+                .contains( new SPImpl1(), new SPImpl2() );
+
+
+        assertThat( providerDetector.lookupServiceNames( ExistingServiceInterface.class, ctx ) )
+                .hasSize( 2 );
+
+        assertThat( providerDetector.lookupServiceNames( ExistingServiceInterface.class, ctx ) )
+                .containsOnly( SPImpl1.class.getName(), SPImpl2.class.getName() );
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/SPImpl1.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/SPImpl1.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/SPImpl1.java
new file mode 100644
index 0000000..e96cec7
--- /dev/null
+++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/SPImpl1.java
@@ -0,0 +1,44 @@
+package org.apache.maven.surefire.spi;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19.2
+ */
+public class SPImpl1 implements ExistingServiceInterface
+{
+    public String whoAmI()
+    {
+        return SPImpl1.class.getSimpleName();
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        return this == o || getClass() == o.getClass();
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return whoAmI().hashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/SPImpl2.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/SPImpl2.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/SPImpl2.java
new file mode 100644
index 0000000..75806b9
--- /dev/null
+++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/spi/SPImpl2.java
@@ -0,0 +1,44 @@
+package org.apache.maven.surefire.spi;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19.2
+ */
+public class SPImpl2 implements ExistingServiceInterface
+{
+    public String whoAmI()
+    {
+        return SPImpl2.class.getSimpleName();
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        return this == o || getClass() == o.getClass();
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return whoAmI().hashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/resources/META-INF/services/org.apache.maven.surefire.spi.EmptyServiceInterface
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/resources/META-INF/services/org.apache.maven.surefire.spi.EmptyServiceInterface b/maven-surefire-common/src/test/resources/META-INF/services/org.apache.maven.surefire.spi.EmptyServiceInterface
new file mode 100644
index 0000000..42d690d
--- /dev/null
+++ b/maven-surefire-common/src/test/resources/META-INF/services/org.apache.maven.surefire.spi.EmptyServiceInterface
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+# this is just a comment and should not be retrieved from SPI loader
+# here should not be any class specified!

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/test/resources/META-INF/services/org.apache.maven.surefire.spi.ExistingServiceInterface
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/resources/META-INF/services/org.apache.maven.surefire.spi.ExistingServiceInterface b/maven-surefire-common/src/test/resources/META-INF/services/org.apache.maven.surefire.spi.ExistingServiceInterface
new file mode 100644
index 0000000..9d34f7f
--- /dev/null
+++ b/maven-surefire-common/src/test/resources/META-INF/services/org.apache.maven.surefire.spi.ExistingServiceInterface
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+# this is just a comment and should not be retrieved from SPI loader
+org.apache.maven.surefire.spi.SPImpl1
+
+# another comment
+org.apache.maven.surefire.spi.SPImpl2


[2/5] maven-surefire git commit: [SUREFIRE-1254] add color messages

Posted by ti...@apache.org.
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-integration-tests/src/test/resources/surefire-1122-parallel-and-flakyTests/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/surefire-1122-parallel-and-flakyTests/pom.xml b/surefire-integration-tests/src/test/resources/surefire-1122-parallel-and-flakyTests/pom.xml
index 5fa0110..62ef251 100644
--- a/surefire-integration-tests/src/test/resources/surefire-1122-parallel-and-flakyTests/pom.xml
+++ b/surefire-integration-tests/src/test/resources/surefire-1122-parallel-and-flakyTests/pom.xml
@@ -20,15 +20,11 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>org.apache.maven.surefire</groupId>
-    <artifactId>it-parent</artifactId>
-    <version>1.0</version>
-    <relativePath>../pom.xml</relativePath>
-  </parent>
+
   <groupId>org.apache.maven.plugins.surefire</groupId>
   <artifactId>jiras-surefire-1122</artifactId>
   <version>1.0</version>
+
   <dependencies>
     <dependency>
       <groupId>junit</groupId>
@@ -37,10 +33,12 @@
       <scope>test</scope>
     </dependency>
   </dependencies>
+
   <build>
     <plugins>
       <plugin>
         <artifactId>maven-compiler-plugin</artifactId>
+        <version>2.3.2</version>
         <configuration>
           <source>1.5</source>
           <target>1.5</target>
@@ -48,6 +46,7 @@
       </plugin>
       <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
+        <version>${surefire.version}</version>
         <dependencies>
           <dependency>
             <groupId>org.apache.maven.surefire</groupId>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-logger-api/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-logger-api/pom.xml b/surefire-logger-api/pom.xml
new file mode 100644
index 0000000..1e64159
--- /dev/null
+++ b/surefire-logger-api/pom.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.maven.surefire</groupId>
+        <artifactId>surefire</artifactId>
+        <version>2.19.2-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>surefire-logger-api</artifactId>
+
+    <name>SureFire Logger API</name>
+    <description>
+        Interfaces and Utilities related only to internal SureFire Logger API. Free of dependencies.
+    </description>
+
+    <properties>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+    </properties>
+
+    <developers>
+        <developer>
+            <id>tibordigana</id>
+            <name>Tibor Diga\u0148a (tibor17)</name>
+            <email>tibordigana@apache.org</email>
+            <roles>
+                <role>PMC</role>
+            </roles>
+            <timezone>Europe/Bratislava</timezone>
+        </developer>
+    </developers>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLogger.java
----------------------------------------------------------------------
diff --git a/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLogger.java b/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLogger.java
new file mode 100644
index 0000000..6baa7e3
--- /dev/null
+++ b/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLogger.java
@@ -0,0 +1,64 @@
+package org.apache.maven.plugin.surefire.log.api;
+
+/*
+ * 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.
+ */
+
+/**
+ * Allows providers to write console messages on the running maven process.
+ * <p/>
+ * This output is associated with the entire test run and not a specific
+ * test, which means it just goes "straight" to the console "immediately".
+ * <p/>
+ * s* <p/>
+ * <p/>
+ * This interface is used in org.apache.maven.plugin.surefire.CommonReflector and reflected
+ * via IsolatedClassLoader which can see classes from JRE only. This interface MUST use
+ * JRE types in method signatures, e.g. {@link String} or {@link Throwable}, etc.
+ * <p/>
+ */
+public interface ConsoleLogger
+{
+    void debug( String message );
+
+    void info( String message );
+
+    void warning( String message );
+
+    /**
+     * @param message          message to log
+     */
+    void error( String message );
+
+    /**
+     * Simply delegates to {@link #error(String) error( toString( t, message ) )}.
+     *
+     * @param message          message to log
+     * @param t                exception, message and trace to log
+     */
+    void error( String message, Throwable t );
+
+    /**
+     * Simply delegates to method {@link #error(String, Throwable) error(null, Throwable)}.
+     *
+     * @param t                exception, message and trace to log
+     */
+    void error( Throwable t );
+
+
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerDecorator.java
----------------------------------------------------------------------
diff --git a/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerDecorator.java b/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerDecorator.java
new file mode 100644
index 0000000..d0761d8
--- /dev/null
+++ b/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerDecorator.java
@@ -0,0 +1 @@
+package org.apache.maven.plugin.surefire.log.api;

/*
 * 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.
 */

/**
 * Decorator around {@link ConsoleLogger}.
 * This class is loaded in the isolated ClassLoader and the child logger in the in-plugi
 n ClassLoader.
 *
 * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
 * @since 2.19.2
 */
public final class ConsoleLoggerDecorator
        implements ConsoleLogger
{
    private final Object logger;

    public ConsoleLoggerDecorator( Object logger )
    {
        if ( logger == null )
        {
            throw new NullPointerException( "logger argument is null in " + ConsoleLoggerDecorator.class );
        }
        this.logger = logger;
    }

    public void debug( String message )
    {
        try
        {
            logger.getClass()
                    .getMethod( "debug", String.class )
                    .invoke( logger, message );
        }
        catch ( Exception e )
        {
            throw new IllegalStateException( e.getLocalizedMessage(), e );
        }
    }

    public void info( String message )
    {
        try
        {
            logger.getClass()
                    .getMethod( "info", String.class )
                    .
 invoke( logger, message );
        }
        catch ( Exception e )
        {
            throw new IllegalStateException( e.getLocalizedMessage(), e );
        }
    }

    public void warning( String message )
    {
        try
        {
            logger.getClass()
                    .getMethod( "warning", String.class )
                    .invoke( logger, message );
        }
        catch ( Exception e )
        {
            throw new IllegalStateException( e.getLocalizedMessage(), e );
        }
    }

    public void error( String message )
    {
        try
        {
            logger.getClass()
                    .getMethod( "error", String.class )
                    .invoke( logger, message );
        }
        catch ( Exception e )
        {
            throw new IllegalStateException( e.getLocalizedMessage(), e );
        }
    }

    public void error( String message, Throwable t )
    {
        try
        {
            logger.getClass()
                    .getM
 ethod( "error", String.class, Throwable.class )
                    .invoke( logger, message, t );
        }
        catch ( Exception e )
        {
            throw new IllegalStateException( e.getLocalizedMessage(), e );
        }
    }

    public void error( Throwable t )
    {
        try
        {
            logger.getClass()
                    .getMethod( "error", Throwable.class )
                    .invoke( logger, t );
        }
        catch ( Exception e )
        {
            throw new IllegalStateException( e.getLocalizedMessage(), e );
        }
    }
}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerUtils.java
----------------------------------------------------------------------
diff --git a/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerUtils.java b/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerUtils.java
new file mode 100644
index 0000000..fe12ceb
--- /dev/null
+++ b/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerUtils.java
@@ -0,0 +1,55 @@
+package org.apache.maven.plugin.surefire.log.api;
+
+/*
+ * 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 java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19.2
+ */
+public final class ConsoleLoggerUtils
+{
+    private ConsoleLoggerUtils()
+    {
+        throw new IllegalStateException( "non instantiable constructor" );
+    }
+
+    public static String toString( String message, Throwable t )
+    {
+        StringWriter result = new StringWriter( 512 );
+        PrintWriter writer = new PrintWriter( result );
+        try
+        {
+            if ( message != null )
+            {
+                writer.println( message );
+            }
+            t.printStackTrace( writer );
+            writer.flush();
+            return result.toString();
+        }
+        finally
+        {
+            writer.close();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/Level.java
----------------------------------------------------------------------
diff --git a/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/Level.java b/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/Level.java
new file mode 100644
index 0000000..0e7164d
--- /dev/null
+++ b/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/Level.java
@@ -0,0 +1,66 @@
+package org.apache.maven.plugin.surefire.log.api;
+
+/*
+ * 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.
+ */
+
+/**
+ * Test result levels {@link #FAILURE}, {@link #UNSTABLE}, {@link #SUCCESS}.
+ * Writing to console without color via {@link #NO_COLOR}.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19.2
+ */
+public enum Level
+{
+    /**
+     * direct println
+     */
+    NO_COLOR,
+
+    /**
+     * defaults to bold, green
+     */
+    FAILURE,
+
+    /**
+     * defaults to bold, yellow
+     */
+    UNSTABLE,
+
+    /**
+     * defaults to bold, red
+     */
+    SUCCESS;
+
+    public static Level resolveLevel( boolean hasSuccessful, boolean hasFailure, boolean hasError,
+                                      boolean hasSkipped, boolean hasFlake )
+    {
+        boolean isRed = hasFailure | hasError;
+        if ( isRed )
+        {
+            return FAILURE;
+        }
+        boolean isYellow = hasSkipped | hasFlake;
+        if ( isYellow )
+        {
+            return UNSTABLE;
+        }
+        return hasSuccessful ? SUCCESS : NO_COLOR;
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/NullConsoleLogger.java
----------------------------------------------------------------------
diff --git a/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/NullConsoleLogger.java b/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/NullConsoleLogger.java
new file mode 100644
index 0000000..a78a615
--- /dev/null
+++ b/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/NullConsoleLogger.java
@@ -0,0 +1,53 @@
+package org.apache.maven.plugin.surefire.log.api;
+
+/*
+ * 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.
+ */
+
+/**
+ * Logger doing nothing rather than using null.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19.2
+ */
+public final class NullConsoleLogger implements ConsoleLogger
+{
+    public void debug( String message )
+    {
+    }
+
+    public void info( String message )
+    {
+    }
+
+    public void warning( String message )
+    {
+    }
+
+    public void error( String message )
+    {
+    }
+
+    public void error( String message, Throwable t )
+    {
+    }
+
+    public void error( Throwable t )
+    {
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/PrintStreamLogger.java
----------------------------------------------------------------------
diff --git a/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/PrintStreamLogger.java b/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/PrintStreamLogger.java
new file mode 100644
index 0000000..0eac176
--- /dev/null
+++ b/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/PrintStreamLogger.java
@@ -0,0 +1 @@
+package org.apache.maven.plugin.surefire.log.api;

/*
 * 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 java.io.PrintStream;

/**
 * For testing purposes.
 */
public class PrintStreamLogger
    implements ConsoleLogger
{
    private
  final PrintStream stream;

    public PrintStreamLogger( PrintStream stream )
    {
        this.stream = stream;
    }

    public void debug( String message )
    {
        stream.println( message );
    }

    public void info( String message )
    {
        stream.println( message );
    }

    public void warning( String message )
    {
        stream.println( message );
    }

    public void error( String message )
    {
        stream.println( message );
    }

    public void error( String message, Throwable t )
    {
        error( ConsoleLoggerUtils.toString( message, t ) );
    }

    public void error( Throwable t )
    {
        error( null, t );
    }
}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java b/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java
index 55f89be..a707fee 100644
--- a/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java
+++ b/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java
@@ -128,7 +128,6 @@ public class JUnit3Provider
     private void executeTestSet( SurefireTestSet testSet, RunListener reporter, ClassLoader classLoader )
         throws TestSetFailedException
     {
-
         ReportEntry report = new SimpleReportEntry( this.getClass().getName(), testSet.getName() );
 
         reporter.testSetStarting( report );

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4ProviderTest.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4ProviderTest.java b/surefire-providers/surefire-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4ProviderTest.java
index 586c55e..bf6cafc 100644
--- a/surefire-providers/surefire-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4ProviderTest.java
+++ b/surefire-providers/surefire-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4ProviderTest.java
@@ -24,9 +24,9 @@ import org.apache.maven.surefire.booter.BaseProviderFactory;
 import org.apache.maven.surefire.testset.TestRequest;
 import org.junit.runner.Description;
 
-import java.util.Arrays;
 import java.util.HashMap;
 
+import static java.util.Arrays.asList;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.*;
 import static org.junit.runner.Description.createSuiteDescription;
@@ -59,7 +59,7 @@ public class JUnit4ProviderTest
         class B {
         }
 
-        Description d = JUnit4Provider.createTestsDescription( Arrays.<Class<?>>asList( A.class, B.class ) );
+        Description d = JUnit4Provider.createTestsDescription( asList( A.class, B.class ) );
         assertThat( d, is( notNullValue() ) );
         assertThat( d.getDisplayName(), not( isEmptyOrNullString() ) );
         assertThat( d.getDisplayName(), is( "null" ) );

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ClassesParallelRunListener.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ClassesParallelRunListener.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ClassesParallelRunListener.java
index 542ffdb..e8ac786 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ClassesParallelRunListener.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ClassesParallelRunListener.java
@@ -20,7 +20,8 @@ package org.apache.maven.surefire.junitcore;
  */
 
 import java.util.Map;
-import org.apache.maven.surefire.report.ConsoleLogger;
+
+import org.apache.maven.surefire.report.ConsoleStream;
 import org.apache.maven.surefire.report.ReporterFactory;
 import org.apache.maven.surefire.testset.TestSetFailedException;
 
@@ -32,10 +33,10 @@ public class ClassesParallelRunListener
     extends ConcurrentRunListener
 {
     public ClassesParallelRunListener( Map<String, TestSet> classMethodCounts, ReporterFactory reporterFactory,
-                                       ConsoleLogger consoleLogger )
+                                       ConsoleStream consoleStream )
         throws TestSetFailedException
     {
-        super( reporterFactory, consoleLogger, false, classMethodCounts );
+        super( reporterFactory, consoleStream, false, classMethodCounts );
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentRunListener.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentRunListener.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentRunListener.java
index 5886317..89c6104 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentRunListener.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentRunListener.java
@@ -20,13 +20,16 @@ package org.apache.maven.surefire.junitcore;
  */
 
 import java.util.Map;
-import org.apache.maven.surefire.report.ConsoleLogger;
 import org.apache.maven.surefire.report.ConsoleOutputReceiver;
+import org.apache.maven.surefire.report.ConsoleStream;
 import org.apache.maven.surefire.report.ReportEntry;
 import org.apache.maven.surefire.report.ReporterFactory;
 import org.apache.maven.surefire.report.RunListener;
+import org.apache.maven.surefire.report.StackTraceWriter;
 import org.apache.maven.surefire.testset.TestSetFailedException;
 
+import static org.apache.maven.surefire.junitcore.TestMethod.getThreadTestMethod;
+
 /**
  * Handles responses from concurrent junit
  * <p/>
@@ -47,25 +50,21 @@ public abstract class ConcurrentRunListener
 
     private final boolean reportImmediately;
 
-    private final ReporterFactory reporterFactory;
-
-    private final ConsoleLogger consoleLogger;
+    private final ConsoleStream consoleStream;
 
-    ConcurrentRunListener( ReporterFactory reporterFactory, ConsoleLogger consoleLogger, boolean reportImmediately,
-                           Map<String, TestSet> classMethodCounts )
+    ConcurrentRunListener( final ReporterFactory reporterFactory, ConsoleStream consoleStream,
+                           boolean reportImmediately, Map<String, TestSet> classMethodCounts )
         throws TestSetFailedException
     {
         this.reportImmediately = reportImmediately;
-        this.reporterFactory = reporterFactory;
         this.classMethodCounts = classMethodCounts;
-        this.consoleLogger = consoleLogger;
-
-        this.reporterManagerThreadLocal = new ThreadLocal<RunListener>()
+        this.consoleStream = consoleStream;
+        reporterManagerThreadLocal = new ThreadLocal<RunListener>()
         {
             @Override
             protected RunListener initialValue()
             {
-                return ConcurrentRunListener.this.reporterFactory.createReporter();
+                return reporterFactory.createReporter();
             }
         };
     }
@@ -140,8 +139,8 @@ public abstract class ConcurrentRunListener
 
     public void testSucceeded( ReportEntry report )
     {
-        TestMethod testMethod = getTestMethod();
-        if ( null != testMethod )
+        TestMethod testMethod = getThreadTestMethod();
+        if ( testMethod != null )
         {
             testMethod.testFinished();
             testMethod.getTestSet().incrementFinishedTests( getRunListener(), reportImmediately );
@@ -151,7 +150,7 @@ public abstract class ConcurrentRunListener
 
     private TestMethod getOrCreateThreadAttachedTestMethod( ReportEntry description )
     {
-        TestMethod threadTestMethod = TestMethod.getThreadTestMethod();
+        TestMethod threadTestMethod = getThreadTestMethod();
         if ( threadTestMethod != null )
         {
             return threadTestMethod;
@@ -159,8 +158,12 @@ public abstract class ConcurrentRunListener
         TestSet testSet = getTestSet( description );
         if ( testSet == null )
         {
-            consoleLogger.info( description.getName() );
-            consoleLogger.info( description.getStackTraceWriter().writeTraceToString() );
+            consoleStream.println( description.getName() );
+            StackTraceWriter writer = description.getStackTraceWriter();
+            if ( writer != null )
+            {
+                consoleStream.println( writer.writeTraceToString() );
+            }
             return null;
         }
         else
@@ -171,11 +174,6 @@ public abstract class ConcurrentRunListener
 
     protected abstract void checkIfTestSetCanBeReported( TestSet testSetForTest );
 
-    TestMethod getTestMethod()
-    {
-        return TestMethod.getThreadTestMethod();
-    }
-
     TestSet getTestSet( ReportEntry description )
     {
         return classMethodCounts.get( description.getSourceName() );
@@ -189,27 +187,27 @@ public abstract class ConcurrentRunListener
     public static ConcurrentRunListener createInstance( Map<String, TestSet> classMethodCounts,
                                                             ReporterFactory reporterFactory,
                                                             boolean parallelClasses, boolean parallelBoth,
-                                                            ConsoleLogger consoleLogger )
+                                                            ConsoleStream consoleStream )
         throws TestSetFailedException
     {
         return parallelClasses
-            ? new ClassesParallelRunListener( classMethodCounts, reporterFactory, consoleLogger )
-            : new MethodsParallelRunListener( classMethodCounts, reporterFactory, !parallelBoth, consoleLogger );
+            ? new ClassesParallelRunListener( classMethodCounts, reporterFactory, consoleStream )
+            : new MethodsParallelRunListener( classMethodCounts, reporterFactory, !parallelBoth, consoleStream );
     }
 
 
     public void writeTestOutput( byte[] buf, int off, int len, boolean stdout )
     {
-        TestMethod threadTestMethod = TestMethod.getThreadTestMethod();
+        TestMethod threadTestMethod = getThreadTestMethod();
         if ( threadTestMethod != null )
         {
-            final LogicalStream logicalStream = threadTestMethod.getLogicalStream();
+            LogicalStream logicalStream = threadTestMethod.getLogicalStream();
             logicalStream.write( stdout, buf, off, len );
         }
         else
         {
-            // Not able to assocaite output with any thread. Just dump to console
-            consoleLogger.info( new String( buf, off, len ) );
+            // Not able to associate output with any thread. Just dump to console
+            consoleStream.println( buf, off, len );
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
index 473da2a..0f41b6f 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
@@ -30,7 +30,7 @@ import org.apache.maven.surefire.common.junit48.JUnit48Reflector;
 import org.apache.maven.surefire.common.junit48.JUnit48TestChecker;
 import org.apache.maven.surefire.providerapi.AbstractProvider;
 import org.apache.maven.surefire.providerapi.ProviderParameters;
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.surefire.report.ConsoleStream;
 import org.apache.maven.surefire.report.ReporterFactory;
 import org.apache.maven.surefire.suite.RunResult;
 import org.apache.maven.surefire.testset.TestListResolver;
@@ -119,14 +119,12 @@ public class JUnitCoreProvider
     {
         final ReporterFactory reporterFactory = providerParameters.getReporterFactory();
 
-        final RunResult runResult;
-
-        final ConsoleLogger consoleLogger = providerParameters.getConsoleLogger();
+        final ConsoleStream consoleStream = providerParameters.getConsoleLogger();
 
         Filter filter = jUnit48Reflector.isJUnit48Available() ? createJUnit48Filter() : null;
 
         Notifier notifier =
-            new Notifier( createRunListener( reporterFactory, consoleLogger ), getSkipAfterFailureCount() );
+            new Notifier( createRunListener( reporterFactory, consoleStream ), getSkipAfterFailureCount() );
         // startCapture() called in createRunListener() in prior to setTestsToRun()
 
         if ( testsToRun == null )
@@ -143,9 +141,11 @@ public class JUnitCoreProvider
             registerPleaseStopJUnitListener( notifier );
         }
 
+        final RunResult runResult;
+
         try
         {
-            JUnitCoreWrapper core = new JUnitCoreWrapper( notifier, jUnitCoreParameters, consoleLogger );
+            JUnitCoreWrapper core = new JUnitCoreWrapper( notifier, jUnitCoreParameters, consoleStream );
 
             if ( commandsReader != null )
             {
@@ -162,7 +162,7 @@ public class JUnitCoreProvider
             {
                 Notifier rerunNotifier = pureNotifier();
                 notifier.copyListenersTo( rerunNotifier );
-                JUnitCoreWrapper rerunCore = new JUnitCoreWrapper( rerunNotifier, jUnitCoreParameters, consoleLogger );
+                JUnitCoreWrapper rerunCore = new JUnitCoreWrapper( rerunNotifier, jUnitCoreParameters, consoleStream );
                 for ( int i = 0; i < rerunFailingTestsCount && !testFailureListener.getAllFailures().isEmpty(); i++ )
                 {
                     List<Failure> failures = testFailureListener.getAllFailures();
@@ -237,7 +237,7 @@ public class JUnitCoreProvider
         } );
     }
 
-    private JUnit4RunListener createRunListener( ReporterFactory reporterFactory, ConsoleLogger consoleLogger )
+    private JUnit4RunListener createRunListener( ReporterFactory reporterFactory, ConsoleStream consoleStream )
         throws TestSetFailedException
     {
         if ( isSingleThreaded() )
@@ -251,7 +251,7 @@ public class JUnitCoreProvider
             final Map<String, TestSet> testSetMap = new ConcurrentHashMap<String, TestSet>();
 
             ConcurrentRunListener listener = createInstance( testSetMap, reporterFactory, isParallelTypes(),
-                                                             isParallelMethodsAndTypes(), consoleLogger );
+                                                             isParallelMethodsAndTypes(), consoleStream );
             startCapture( listener );
 
             return new JUnitCoreRunListener( listener, testSetMap );

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
index 21858fe..2abfa58 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
@@ -22,7 +22,7 @@ package org.apache.maven.surefire.junitcore;
 import org.apache.maven.surefire.common.junit4.Notifier;
 import org.apache.maven.surefire.junitcore.pc.ParallelComputer;
 import org.apache.maven.surefire.junitcore.pc.ParallelComputerBuilder;
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.surefire.report.ConsoleStream;
 import org.apache.maven.surefire.testset.TestSetFailedException;
 import org.apache.maven.surefire.util.TestsToRun;
 import org.junit.Ignore;
@@ -54,13 +54,13 @@ final class JUnitCoreWrapper
 {
     private final Notifier notifier;
     private final JUnitCoreParameters jUnitCoreParameters;
-    private final ConsoleLogger logger;
+    private final ConsoleStream consoleStream;
 
-    JUnitCoreWrapper( Notifier notifier, JUnitCoreParameters jUnitCoreParameters, ConsoleLogger logger )
+    JUnitCoreWrapper( Notifier notifier, JUnitCoreParameters jUnitCoreParameters, ConsoleStream consoleStream )
     {
         this.notifier = notifier;
         this.jUnitCoreParameters = jUnitCoreParameters;
-        this.logger = logger;
+        this.consoleStream = consoleStream;
     }
 
     void execute( TestsToRun testsToRun, Filter filter )
@@ -151,7 +151,7 @@ final class JUnitCoreWrapper
     {
         return jUnitCoreParameters.isNoThreading()
             ? serial()
-            : new ParallelComputerBuilder( logger, jUnitCoreParameters ).buildComputer();
+            : new ParallelComputerBuilder( consoleStream, jUnitCoreParameters ).buildComputer();
     }
 
     private final class JUnitCore

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/MethodsParallelRunListener.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/MethodsParallelRunListener.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/MethodsParallelRunListener.java
index 4edc365..0e487b0 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/MethodsParallelRunListener.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/MethodsParallelRunListener.java
@@ -20,7 +20,8 @@ package org.apache.maven.surefire.junitcore;
  */
 
 import java.util.Map;
-import org.apache.maven.surefire.report.ConsoleLogger;
+
+import org.apache.maven.surefire.report.ConsoleStream;
 import org.apache.maven.surefire.report.ReporterFactory;
 import org.apache.maven.surefire.testset.TestSetFailedException;
 
@@ -36,10 +37,10 @@ public class MethodsParallelRunListener
     private final Object lock = new Object();
 
     public MethodsParallelRunListener( Map<String, TestSet> classMethodCounts, ReporterFactory reporterFactory,
-                                       boolean reportImmediately, ConsoleLogger consoleLogger )
+                                       boolean reportImmediately, ConsoleStream consoleStream )
         throws TestSetFailedException
     {
-        super( reporterFactory, consoleLogger, reportImmediately, classMethodCounts );
+        super( reporterFactory, consoleStream, reportImmediately, classMethodCounts );
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/AbstractThreadPoolStrategy.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/AbstractThreadPoolStrategy.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/AbstractThreadPoolStrategy.java
index 17db2ba..5eb7715 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/AbstractThreadPoolStrategy.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/AbstractThreadPoolStrategy.java
@@ -19,7 +19,7 @@ package org.apache.maven.surefire.junitcore.pc;
  * under the License.
  */
 
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.surefire.report.ConsoleStream;
 
 import java.util.Collection;
 import java.util.concurrent.ExecutorService;
@@ -47,12 +47,12 @@ abstract class AbstractThreadPoolStrategy
 
     private volatile boolean isDestroyed;
 
-    AbstractThreadPoolStrategy( ConsoleLogger logger, ExecutorService threadPool )
+    AbstractThreadPoolStrategy( ConsoleStream logger, ExecutorService threadPool )
     {
         this( logger, threadPool, null );
     }
 
-    AbstractThreadPoolStrategy( ConsoleLogger logger, ExecutorService threadPool, Collection<Future<?>> futureResults )
+    AbstractThreadPoolStrategy( ConsoleStream logger, ExecutorService threadPool, Collection<Future<?>> futureResults )
     {
         super( logger );
         this.threadPool = threadPool;

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/InvokerStrategy.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/InvokerStrategy.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/InvokerStrategy.java
index 3f95915..cc1a040 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/InvokerStrategy.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/InvokerStrategy.java
@@ -19,7 +19,7 @@ package org.apache.maven.surefire.junitcore.pc;
  * under the License.
  */
 
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.surefire.report.ConsoleStream;
 
 import java.util.Queue;
 import java.util.concurrent.ConcurrentLinkedQueue;
@@ -37,7 +37,7 @@ final class InvokerStrategy
 
     private final Queue<Thread> activeThreads = new ConcurrentLinkedQueue<Thread>();
 
-    protected InvokerStrategy( ConsoleLogger logger )
+    protected InvokerStrategy( ConsoleStream logger )
     {
         super( logger );
     }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/NonSharedThreadPoolStrategy.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/NonSharedThreadPoolStrategy.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/NonSharedThreadPoolStrategy.java
index 88b13d0..535011b 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/NonSharedThreadPoolStrategy.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/NonSharedThreadPoolStrategy.java
@@ -19,7 +19,7 @@ package org.apache.maven.surefire.junitcore.pc;
  * under the License.
  */
 
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.surefire.report.ConsoleStream;
 
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -34,7 +34,7 @@ import java.util.concurrent.TimeUnit;
 final class NonSharedThreadPoolStrategy
     extends AbstractThreadPoolStrategy
 {
-    NonSharedThreadPoolStrategy( ConsoleLogger logger, ExecutorService threadPool )
+    NonSharedThreadPoolStrategy( ConsoleStream logger, ExecutorService threadPool )
     {
         super( logger, threadPool );
     }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilder.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilder.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilder.java
index d407baa..0b35765 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilder.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilder.java
@@ -35,7 +35,7 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;
 
 import org.apache.maven.surefire.junitcore.JUnitCoreParameters;
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.surefire.report.ConsoleStream;
 import org.apache.maven.surefire.testset.TestSetFailedException;
 import org.apache.maven.surefire.util.internal.DaemonThreadFactory;
 import org.junit.internal.runners.ErrorReportingRunner;
@@ -92,7 +92,7 @@ public final class ParallelComputerBuilder
 
     private final Map<Type, Integer> parallelGroups = new EnumMap<Type, Integer>( Type.class );
 
-    private final ConsoleLogger logger;
+    private final ConsoleStream logger;
 
     private boolean useSeparatePools;
 
@@ -109,7 +109,7 @@ public final class ParallelComputerBuilder
      * Can be used only in unit tests.
      * Do NOT call this constructor in production.
      */
-    ParallelComputerBuilder( ConsoleLogger logger )
+    ParallelComputerBuilder( ConsoleStream logger )
     {
         this.logger = logger;
         runningInTests = true;
@@ -119,7 +119,7 @@ public final class ParallelComputerBuilder
         parallelGroups.put( METHODS, 0 );
     }
 
-    public ParallelComputerBuilder( ConsoleLogger logger, JUnitCoreParameters parameters )
+    public ParallelComputerBuilder( ConsoleStream logger, JUnitCoreParameters parameters )
     {
         this( logger );
         runningInTests = false;

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/Scheduler.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/Scheduler.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/Scheduler.java
index a957340..2c87fdd 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/Scheduler.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/Scheduler.java
@@ -19,7 +19,7 @@ package org.apache.maven.surefire.junitcore.pc;
  * under the License.
  */
 
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.surefire.report.ConsoleStream;
 import org.junit.runner.Description;
 import org.junit.runners.model.RunnerScheduler;
 
@@ -56,7 +56,7 @@ public class Scheduler
 
     private final Description description;
 
-    private final ConsoleLogger logger;
+    private final ConsoleStream logger;
 
     private volatile boolean shutdown = false;
 
@@ -72,7 +72,7 @@ public class Scheduler
      * You can use it with one infinite thread pool shared in strategies across all
      * suites, class runners, etc.
      */
-    public Scheduler( ConsoleLogger logger, Description description, SchedulingStrategy strategy )
+    public Scheduler( ConsoleStream logger, Description description, SchedulingStrategy strategy )
     {
         this( logger, description, strategy, -1 );
     }
@@ -81,8 +81,8 @@ public class Scheduler
      * Should be used if schedulers in parallel children and parent use one instance of bounded thread pool.
      * <p/>
      * Set this scheduler in a e.g. one suite of classes, then every individual class runner should reference
-     * {@link Scheduler(ConsoleLogger, org.junit.runner.Description, Scheduler, SchedulingStrategy)}
-     * or {@link Scheduler(ConsoleLogger, org.junit.runner.Description, Scheduler, SchedulingStrategy, int)}.
+     * {@link Scheduler(ConsoleStream, org.junit.runner.Description, Scheduler, SchedulingStrategy)}
+     * or {@link Scheduler(ConsoleStream, org.junit.runner.Description, Scheduler, SchedulingStrategy, int)}.
      *
      * @param logger current logger implementation
      * @param description description of current runner
@@ -90,7 +90,7 @@ public class Scheduler
      * @param concurrency determines maximum concurrent children scheduled a time via {@link #schedule(Runnable)}
      * @throws NullPointerException if null <tt>strategy</tt>
      */
-    public Scheduler( ConsoleLogger logger, Description description, SchedulingStrategy strategy, int concurrency )
+    public Scheduler( ConsoleStream logger, Description description, SchedulingStrategy strategy, int concurrency )
     {
         this( logger, description, strategy, BalancerFactory.createBalancer( concurrency ) );
     }
@@ -99,7 +99,7 @@ public class Scheduler
      * New instances should be used by schedulers with limited concurrency by <tt>balancer</tt>
      * against other groups of schedulers. The schedulers share one pool.
      * <p/>
-     * Unlike in {@link Scheduler(ConsoleLogger, org.junit.runner.Description, SchedulingStrategy, int)} which was
+     * Unlike in {@link Scheduler(ConsoleStream, org.junit.runner.Description, SchedulingStrategy, int)} which was
      * limiting the <tt>concurrency</tt> of children of a runner where this scheduler was set, <em>this</em>
      * <tt>balancer</tt> is limiting the concurrency of all children in runners having schedulers created by this
      * constructor.
@@ -110,7 +110,7 @@ public class Scheduler
      * @param balancer    determines maximum concurrent children scheduled a time via {@link #schedule(Runnable)}
      * @throws NullPointerException if null <tt>strategy</tt> or <tt>balancer</tt>
      */
-    public Scheduler( ConsoleLogger logger, Description description, SchedulingStrategy strategy, Balancer balancer )
+    public Scheduler( ConsoleStream logger, Description description, SchedulingStrategy strategy, Balancer balancer )
     {
         strategy.setDefaultShutdownHandler( newShutdownHandler() );
         this.logger = logger;
@@ -131,7 +131,7 @@ public class Scheduler
      * @param balancer        determines maximum concurrent children scheduled a time via {@link #schedule(Runnable)}
      * @throws NullPointerException if null <tt>masterScheduler</tt>, <tt>strategy</tt> or <tt>balancer</tt>
      */
-    public Scheduler( ConsoleLogger logger, Description description, Scheduler masterScheduler,
+    public Scheduler( ConsoleStream logger, Description description, Scheduler masterScheduler,
                       SchedulingStrategy strategy, Balancer balancer )
     {
         this( logger, description, strategy, balancer );
@@ -141,12 +141,12 @@ public class Scheduler
 
     /**
      * @param masterScheduler a reference to
-     * {@link Scheduler(ConsoleLogger, org.junit.runner.Description, SchedulingStrategy, int)}
-     *                        or {@link Scheduler(ConsoleLogger, org.junit.runner.Description, SchedulingStrategy)}
-     * @see Scheduler(ConsoleLogger, org.junit.runner.Description, SchedulingStrategy)
-     * @see Scheduler(ConsoleLogger, org.junit.runner.Description, SchedulingStrategy, int)
+     * {@link Scheduler(ConsoleStream, org.junit.runner.Description, SchedulingStrategy, int)}
+     *                        or {@link Scheduler(ConsoleStream, org.junit.runner.Description, SchedulingStrategy)}
+     * @see Scheduler(ConsoleStream, org.junit.runner.Description, SchedulingStrategy)
+     * @see Scheduler(ConsoleStream, org.junit.runner.Description, SchedulingStrategy, int)
      */
-    public Scheduler( ConsoleLogger logger, Description description, Scheduler masterScheduler,
+    public Scheduler( ConsoleStream logger, Description description, Scheduler masterScheduler,
                       SchedulingStrategy strategy, int concurrency )
     {
         this( logger, description, strategy, concurrency );
@@ -160,7 +160,7 @@ public class Scheduler
      * <p/>
      * Cached thread pool is infinite and can be always shared.
      */
-    public Scheduler( ConsoleLogger logger, Description description, Scheduler masterScheduler,
+    public Scheduler( ConsoleStream logger, Description description, Scheduler masterScheduler,
                       SchedulingStrategy strategy )
     {
         this( logger, description, masterScheduler, strategy, 0 );
@@ -215,12 +215,12 @@ public class Scheduler
         {
             stream.close();
         }
-        logger.info( out.toString() );
+        logger.println( out.toString() );
     }
 
     protected void logQuietly( String msg )
     {
-        logger.info( msg );
+        logger.println( msg );
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategies.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategies.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategies.java
index 6706951..520c312 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategies.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategies.java
@@ -19,7 +19,7 @@ package org.apache.maven.surefire.junitcore.pc;
  * under the License.
  */
 
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.surefire.report.ConsoleStream;
 import org.apache.maven.surefire.util.internal.DaemonThreadFactory;
 
 import java.util.concurrent.ExecutorService;
@@ -40,7 +40,7 @@ public class SchedulingStrategies
      * @param logger current error logger
      * @return sequentially executing strategy
      */
-    public static SchedulingStrategy createInvokerStrategy( ConsoleLogger logger )
+    public static SchedulingStrategy createInvokerStrategy( ConsoleStream logger )
     {
         return new InvokerStrategy( logger );
     }
@@ -50,7 +50,7 @@ public class SchedulingStrategies
      * @param nThreads fixed pool capacity
      * @return parallel scheduling strategy
      */
-    public static SchedulingStrategy createParallelStrategy( ConsoleLogger logger, int nThreads )
+    public static SchedulingStrategy createParallelStrategy( ConsoleStream logger, int nThreads )
     {
         return new NonSharedThreadPoolStrategy( logger,
                                                 Executors.newFixedThreadPool( nThreads, DAEMON_THREAD_FACTORY ) );
@@ -60,7 +60,7 @@ public class SchedulingStrategies
      * @param logger current error logger
      * @return parallel scheduling strategy with unbounded capacity
      */
-    public static SchedulingStrategy createParallelStrategyUnbounded( ConsoleLogger logger )
+    public static SchedulingStrategy createParallelStrategyUnbounded( ConsoleStream logger )
     {
         return new NonSharedThreadPoolStrategy( logger, Executors.newCachedThreadPool( DAEMON_THREAD_FACTORY ) );
     }
@@ -78,7 +78,7 @@ public class SchedulingStrategies
      * @return parallel strategy with shared thread pool
      * @throws NullPointerException if <tt>threadPool</tt> is null
      */
-    public static SchedulingStrategy createParallelSharedStrategy( ConsoleLogger logger, ExecutorService threadPool )
+    public static SchedulingStrategy createParallelSharedStrategy( ConsoleStream logger, ExecutorService threadPool )
     {
         if ( threadPool == null )
         {

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategy.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategy.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategy.java
index b1e1fd0..ce337bc 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategy.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategy.java
@@ -19,7 +19,7 @@ package org.apache.maven.surefire.junitcore.pc;
  * under the License.
  */
 
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.surefire.report.ConsoleStream;
 
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
@@ -43,9 +43,9 @@ public abstract class SchedulingStrategy
 
     private final AtomicBoolean canSchedule = new AtomicBoolean( true );
 
-    private final ConsoleLogger logger;
+    private final ConsoleStream logger;
 
-    protected SchedulingStrategy( ConsoleLogger logger )
+    protected SchedulingStrategy( ConsoleStream logger )
     {
         this.logger = logger;
     }
@@ -145,6 +145,6 @@ public abstract class SchedulingStrategy
         {
             stream.close();
         }
-        logger.info( out.toString() );
+        logger.println( out.toString() );
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SharedThreadPoolStrategy.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SharedThreadPoolStrategy.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SharedThreadPoolStrategy.java
index ff72d64..a577fdb 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SharedThreadPoolStrategy.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SharedThreadPoolStrategy.java
@@ -19,7 +19,7 @@ package org.apache.maven.surefire.junitcore.pc;
  * under the License.
  */
 
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.surefire.report.ConsoleStream;
 
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ConcurrentLinkedQueue;
@@ -37,7 +37,7 @@ import java.util.concurrent.Future;
 final class SharedThreadPoolStrategy
     extends AbstractThreadPoolStrategy
 {
-    SharedThreadPoolStrategy( ConsoleLogger logger, ExecutorService threadPool )
+    SharedThreadPoolStrategy( ConsoleStream logger, ExecutorService threadPool )
     {
         super( logger, threadPool, new ConcurrentLinkedQueue<Future<?>>() );
     }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SingleThreadScheduler.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SingleThreadScheduler.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SingleThreadScheduler.java
index 88ae625..a0f5c2d 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SingleThreadScheduler.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/SingleThreadScheduler.java
@@ -19,7 +19,7 @@ package org.apache.maven.surefire.junitcore.pc;
  * under the License.
  */
 
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.surefire.report.ConsoleStream;
 import org.apache.maven.surefire.util.internal.DaemonThreadFactory;
 import org.junit.runner.Description;
 import org.junit.runners.model.RunnerScheduler;
@@ -42,7 +42,7 @@ import java.util.concurrent.TimeUnit;
  */
 final class SingleThreadScheduler
 {
-    private final ConsoleLogger logger;
+    private final ConsoleStream logger;
 
     private final ExecutorService pool = newPool();
 
@@ -54,7 +54,7 @@ final class SingleThreadScheduler
         return new ThreadPoolExecutor( 1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), tf );
     }
 
-    SingleThreadScheduler( ConsoleLogger logger )
+    SingleThreadScheduler( ConsoleStream logger )
     {
         this.logger = logger;
         SchedulingStrategy strategy = SchedulingStrategies.createParallelSharedStrategy( logger, pool );

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConcurrentRunListenerTest.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConcurrentRunListenerTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConcurrentRunListenerTest.java
index 24fb2da..dc504b6 100644
--- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConcurrentRunListenerTest.java
+++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConcurrentRunListenerTest.java
@@ -24,7 +24,8 @@ import java.io.PrintStream;
 import java.util.HashMap;
 import java.util.Map;
 import org.apache.maven.plugin.surefire.report.DefaultReporterFactory;
-import org.apache.maven.surefire.report.DefaultConsoleReporter;
+import org.apache.maven.surefire.report.ConsoleStream;
+import org.apache.maven.surefire.report.DefaultDirectConsoleReporter;
 import org.apache.maven.surefire.report.ReporterFactory;
 import org.apache.maven.surefire.report.RunListener;
 import org.apache.maven.surefire.report.RunStatistics;
@@ -147,7 +148,7 @@ public class ConcurrentRunListenerTest
     {
         DefaultReporterFactory reporterFactory = createReporterFactory();
         HashMap<String, TestSet> classMethodCounts = new HashMap<String, TestSet>();
-        final DefaultConsoleReporter defaultConsoleReporter = new DefaultConsoleReporter( System.out );
+        final ConsoleStream defaultConsoleReporter = new DefaultDirectConsoleReporter( System.out );
         RunListener reporter =
             new ClassesParallelRunListener( classMethodCounts, reporterFactory, defaultConsoleReporter );
         JUnitCoreRunListener runListener = new JUnitCoreRunListener( reporter, classMethodCounts );
@@ -200,8 +201,8 @@ public class ConcurrentRunListenerTest
         throws TestSetFailedException
     {
         return new JUnitCoreRunListener(
-            new ClassesParallelRunListener( testSetMap, reporterFactory, new DefaultConsoleReporter( System.out ) ),
-            testSetMap );
+            new ClassesParallelRunListener( testSetMap, reporterFactory,
+                                                  new DefaultDirectConsoleReporter( System.out ) ), testSetMap );
     }
 
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/DefaultConsoleReporter.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/DefaultConsoleReporter.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/DefaultConsoleReporter.java
new file mode 100644
index 0000000..0c8e856
--- /dev/null
+++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/DefaultConsoleReporter.java
@@ -0,0 +1,68 @@
+package org.apache.maven.surefire.junitcore;
+
+/*
+ * 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.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+
+import java.io.PrintStream;
+
+/**
+ * @author <a href="mailto:kristian@zenior.no">Kristian Rosenvold</a>
+ */
+public class DefaultConsoleReporter
+    implements ConsoleLogger
+{
+    private final PrintStream systemOut;
+
+    public DefaultConsoleReporter( PrintStream systemOut )
+    {
+        this.systemOut = systemOut;
+    }
+
+    public void debug( String message )
+    {
+
+    }
+
+    public void info( String message )
+    {
+        systemOut.println( message );
+    }
+
+    public void warning( String message )
+    {
+
+    }
+
+    public void error( String message )
+    {
+
+    }
+
+    public void error( String message, Throwable t )
+    {
+
+    }
+
+    public void error( Throwable t )
+    {
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreTester.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreTester.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreTester.java
index e021647..41ae610 100644
--- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreTester.java
+++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreTester.java
@@ -20,9 +20,8 @@ package org.apache.maven.surefire.junitcore;
  */
 
 import org.apache.maven.plugin.surefire.report.DefaultReporterFactory;
-import org.apache.maven.surefire.report.ConsoleOutputCapture;
 import org.apache.maven.surefire.report.ConsoleOutputReceiver;
-import org.apache.maven.surefire.report.DefaultConsoleReporter;
+import org.apache.maven.surefire.report.DefaultDirectConsoleReporter;
 import org.apache.maven.surefire.report.ReporterFactory;
 import org.apache.maven.surefire.report.RunListener;
 import org.apache.maven.surefire.testset.TestSetFailedException;
@@ -33,6 +32,9 @@ import org.junit.runner.Result;
 import java.util.HashMap;
 import java.util.concurrent.ExecutionException;
 
+import static org.apache.maven.surefire.junitcore.ConcurrentRunListener.createInstance;
+import static org.apache.maven.surefire.report.ConsoleOutputCapture.startCapture;
+
 /**
  * @author Kristian Rosenvold
  */
@@ -58,12 +60,10 @@ public class JUnitCoreTester
 
         try
         {
-
             final HashMap<String, TestSet> classMethodCounts = new HashMap<String, TestSet>();
-            RunListener reporter =
-                ConcurrentRunListener.createInstance( classMethodCounts, reporterManagerFactory, parallelClasses, false,
-                                                      new DefaultConsoleReporter( System.out ) );
-            ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) reporter );
+            RunListener reporter = createInstance( classMethodCounts, reporterManagerFactory, parallelClasses, false,
+                                                         new DefaultDirectConsoleReporter( System.out ) );
+            startCapture( (ConsoleOutputReceiver) reporter );
 
             JUnitCoreRunListener runListener = new JUnitCoreRunListener( reporter, classMethodCounts );
             JUnitCore junitCore = new JUnitCore();

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Logger.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Logger.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Logger.java
deleted file mode 100644
index 4fff4b0..0000000
--- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Logger.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.apache.maven.surefire.junitcore;
-
-/*
- * 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.apache.maven.surefire.report.ConsoleLogger;
-
-public final class Logger implements ConsoleLogger
-{
-    public void info( String message )
-    {
-        System.out.println( message );
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java
index 0ee4269..3e9ca93 100644
--- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java
+++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java
@@ -20,14 +20,14 @@ package org.apache.maven.surefire.junitcore;
 import java.io.File;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
+
 import org.apache.maven.plugin.surefire.report.DefaultReporterFactory;
 import org.apache.maven.surefire.booter.BaseProviderFactory;
 import org.apache.maven.surefire.booter.ProviderParameterNames;
 import org.apache.maven.surefire.common.junit4.JUnit4RunListener;
 import org.apache.maven.surefire.common.junit4.Notifier;
 import org.apache.maven.surefire.junit4.MockReporter;
-import org.apache.maven.surefire.report.ConsoleLogger;
-import org.apache.maven.surefire.report.DefaultConsoleReporter;
+import org.apache.maven.surefire.report.DefaultDirectConsoleReporter;
 import org.apache.maven.surefire.report.ReporterConfiguration;
 import org.apache.maven.surefire.report.ReporterFactory;
 import org.apache.maven.surefire.report.RunListener;
@@ -89,7 +89,6 @@ public class Surefire746Test
     {
         ReporterFactory reporterFactory = DefaultReporterFactory.defaultNoXml();
         BaseProviderFactory providerParameters = new BaseProviderFactory( reporterFactory, true );
-        ConsoleLogger consoleLogger = new DefaultConsoleReporter( System.out );
 
         providerParameters.setReporterConfiguration( new ReporterConfiguration( new File( "" ), false ) );
         Map<String, String> junitProps = new HashMap<String, String>();
@@ -100,7 +99,8 @@ public class Surefire746Test
         final Map<String, TestSet> testSetMap = new ConcurrentHashMap<String, TestSet>();
 
         RunListener listener =
-            ConcurrentRunListener.createInstance( testSetMap, reporterFactory, false, false, consoleLogger );
+            ConcurrentRunListener.createInstance( testSetMap, reporterFactory, false, false,
+                                                        new DefaultDirectConsoleReporter( System.out ) );
 
         TestsToRun testsToRun = new TestsToRun( Collections.<Class<?>>singleton( TestClassTest.class ) );
 
@@ -116,7 +116,8 @@ public class Surefire746Test
             // and rethrows a failure which happened in listener
             exception.expect( TestSetFailedException.class );
             JUnit4RunListener dummy = new JUnit4RunListener( new MockReporter() );
-            new JUnitCoreWrapper( new Notifier( dummy, 0 ), jUnitCoreParameters, new Logger() )
+            new JUnitCoreWrapper( new Notifier( dummy, 0 ), jUnitCoreParameters,
+                                        new DefaultDirectConsoleReporter( System.out ) )
                 .execute( testsToRun, customRunListeners, null );
         }
         finally

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilderTest.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilderTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilderTest.java
index aca5d68..5184cdd 100644
--- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilderTest.java
+++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilderTest.java
@@ -20,7 +20,8 @@ package org.apache.maven.surefire.junitcore.pc;
  */
 
 import net.jcip.annotations.NotThreadSafe;
-import org.apache.maven.surefire.junitcore.Logger;
+import org.apache.maven.surefire.report.ConsoleStream;
+import org.apache.maven.surefire.report.DefaultDirectConsoleReporter;
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;
@@ -63,6 +64,8 @@ public class ParallelComputerBuilderTest
 
     private static volatile Runnable shutdownTask;
 
+    private static final ConsoleStream logger = new DefaultDirectConsoleReporter( System.out );
+
     @Rule
     public final Stopwatch stopwatch = new Stopwatch() {};
 
@@ -103,7 +106,7 @@ public class ParallelComputerBuilderTest
     @Test
     public void parallelMethodsReuseOneOrTwoThreads()
     {
-        ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( new Logger() );
+        ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger );
         parallelComputerBuilder.useOnePool( 4 );
 
         // One thread because one suite: TestSuite, however the capacity is 5.
@@ -146,7 +149,7 @@ public class ParallelComputerBuilderTest
     @Test
     public void suiteAndClassInOnePool()
     {
-        ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( new Logger() );
+        ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger );
         parallelComputerBuilder.useOnePool( 5 );
         parallelComputerBuilder.parallelSuites( 5 );
         parallelComputerBuilder.parallelClasses( 5 );
@@ -172,7 +175,7 @@ public class ParallelComputerBuilderTest
     public void onePoolWithUnlimitedParallelMethods()
     {
         // see ParallelComputerBuilder Javadoc
-        ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( new Logger() );
+        ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger );
         parallelComputerBuilder.useOnePool( 8 );
         parallelComputerBuilder.parallelSuites( 2 );
         parallelComputerBuilder.parallelClasses( 4 );
@@ -197,7 +200,7 @@ public class ParallelComputerBuilderTest
     @Test
     public void underflowParallelism()
     {
-        ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( new Logger() );
+        ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger );
         parallelComputerBuilder.useOnePool( 3 );
 
         // One thread because one suite: TestSuite.
@@ -229,7 +232,7 @@ public class ParallelComputerBuilderTest
     @Test
     public void separatePoolsWithSuite()
     {
-        ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( new Logger() );
+        ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger );
         parallelComputerBuilder.parallelSuites( 5 );
         parallelComputerBuilder.parallelClasses( 5 );
         parallelComputerBuilder.parallelMethods( 3 );
@@ -253,7 +256,7 @@ public class ParallelComputerBuilderTest
     @Test
     public void separatePoolsWithSuiteAndClass()
     {
-        ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( new Logger() );
+        ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger );
         parallelComputerBuilder.parallelSuites( 5 );
         parallelComputerBuilder.parallelClasses( 5 );
         parallelComputerBuilder.parallelMethods( 3 );
@@ -280,7 +283,7 @@ public class ParallelComputerBuilderTest
     @Test
     public void separatePoolsWithSuiteAndSequentialClasses()
     {
-        ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( new Logger() );
+        ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger );
         parallelComputerBuilder.parallelSuites( 5 );
         parallelComputerBuilder.parallelClasses( 1 );
         parallelComputerBuilder.parallelMethods( 3 );
@@ -324,7 +327,7 @@ public class ParallelComputerBuilderTest
     public void nothingParallel()
     {
         JUnitCore core = new JUnitCore();
-        ParallelComputerBuilder builder = new ParallelComputerBuilder( new Logger() );
+        ParallelComputerBuilder builder = new ParallelComputerBuilder( logger );
         assertFalse( builder.isOptimized() );
 
         Result result = core.run( builder.buildComputer(), NothingDoingTest1.class, NothingDoingTest2.class );
@@ -377,7 +380,7 @@ public class ParallelComputerBuilderTest
     @Test
     public void keepBeforeAfterOneClass()
     {
-        ParallelComputerBuilder builder = new ParallelComputerBuilder( new Logger() );
+        ParallelComputerBuilder builder = new ParallelComputerBuilder( logger );
         builder.parallelMethods();
         assertFalse( builder.isOptimized() );
         testKeepBeforeAfter( builder, NothingDoingTest1.class );
@@ -386,7 +389,7 @@ public class ParallelComputerBuilderTest
     @Test
     public void keepBeforeAfterTwoClasses()
     {
-        ParallelComputerBuilder builder = new ParallelComputerBuilder( new Logger() );
+        ParallelComputerBuilder builder = new ParallelComputerBuilder( logger );
         builder.useOnePool( 5 ).parallelClasses( 1 ).parallelMethods( 2 );
         assertFalse( builder.isOptimized() );
         testKeepBeforeAfter( builder, NothingDoingTest1.class, NothingDoingTest2.class );
@@ -395,7 +398,7 @@ public class ParallelComputerBuilderTest
     @Test
     public void keepBeforeAfterTwoParallelClasses()
     {
-        ParallelComputerBuilder builder = new ParallelComputerBuilder( new Logger() );
+        ParallelComputerBuilder builder = new ParallelComputerBuilder( logger );
         builder.useOnePool( 8 ).parallelClasses( 2 ).parallelMethods( 2 );
         assertFalse( builder.isOptimized() );
         JUnitCore core = new JUnitCore();
@@ -411,7 +414,7 @@ public class ParallelComputerBuilderTest
     @Test
     public void notThreadSafeTest()
     {
-        ParallelComputerBuilder builder = new ParallelComputerBuilder( new Logger() )
+        ParallelComputerBuilder builder = new ParallelComputerBuilder( logger )
             .useOnePool( 6 ).optimize( true ).parallelClasses( 3 ).parallelMethods( 3 );
         ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) builder.buildComputer();
         Result result = new JUnitCore().run( computer, NotThreadSafeTest1.class, NotThreadSafeTest2.class );
@@ -432,7 +435,7 @@ public class ParallelComputerBuilderTest
     @Test
     public void mixedThreadSafety()
     {
-        ParallelComputerBuilder builder = new ParallelComputerBuilder( new Logger() )
+        ParallelComputerBuilder builder = new ParallelComputerBuilder( logger )
             .useOnePool( 6 ).optimize( true ).parallelClasses( 3 ).parallelMethods( 3 );
         ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) builder.buildComputer();
         Result result = new JUnitCore().run( computer, NotThreadSafeTest1.class, NormalTest1.class );
@@ -454,7 +457,7 @@ public class ParallelComputerBuilderTest
     @Test
     public void notThreadSafeTestsInSuite()
     {
-        ParallelComputerBuilder builder = new ParallelComputerBuilder( new Logger() )
+        ParallelComputerBuilder builder = new ParallelComputerBuilder( logger )
             .useOnePool( 5 ).parallelMethods( 3 );
         assertFalse( builder.isOptimized() );
         ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) builder.buildComputer();
@@ -477,7 +480,7 @@ public class ParallelComputerBuilderTest
     @Test
     public void mixedThreadSafetyInSuite()
     {
-        ParallelComputerBuilder builder = new ParallelComputerBuilder( new Logger() )
+        ParallelComputerBuilder builder = new ParallelComputerBuilder( logger )
             .useOnePool( 10 ).optimize( true ).parallelSuites( 2 ).parallelClasses( 3 ).parallelMethods( 3 );
         ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) builder.buildComputer();
         Result result = new JUnitCore().run( computer, MixedSuite.class );
@@ -499,7 +502,7 @@ public class ParallelComputerBuilderTest
     @Test
     public void inheritanceWithNotThreadSafe()
     {
-        ParallelComputerBuilder builder = new ParallelComputerBuilder( new Logger() )
+        ParallelComputerBuilder builder = new ParallelComputerBuilder( logger )
             .useOnePool( 10 ).optimize( true ).parallelSuites( 2 ).parallelClasses( 3 ).parallelMethods( 3 );
         ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) builder.buildComputer();
         Result result = new JUnitCore().run( computer, OverMixedSuite.class );
@@ -529,7 +532,7 @@ public class ParallelComputerBuilderTest
             TimeUnit.MILLISECONDS.sleep( 500 );
         }
         Collection<Thread> expectedThreads = jvmThreads();
-        ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( new Logger() );
+        ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger );
         parallelComputerBuilder.parallelMethods( 3 );
         ParallelComputer computer = parallelComputerBuilder.buildComputer();
         Result result = new JUnitCore().run( computer, TestWithBeforeAfter.class );
@@ -564,7 +567,7 @@ public class ParallelComputerBuilderTest
     {
         Result run( final boolean useInterrupt )
         {
-            ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( new Logger() )
+            ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger )
                 .useOnePool( 8 )
                 .parallelSuites( 2 )
                 .parallelClasses( 3 )

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerUtilTest.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerUtilTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerUtilTest.java
index a19c8c8..15daac9 100644
--- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerUtilTest.java
+++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerUtilTest.java
@@ -20,7 +20,8 @@ package org.apache.maven.surefire.junitcore.pc;
  */
 
 import org.apache.maven.surefire.junitcore.JUnitCoreParameters;
-import org.apache.maven.surefire.junitcore.Logger;
+import org.apache.maven.surefire.report.ConsoleStream;
+import org.apache.maven.surefire.report.DefaultDirectConsoleReporter;
 import org.apache.maven.surefire.testset.TestSetFailedException;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
@@ -58,6 +59,8 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
 @RunWith( Theories.class )
 public final class ParallelComputerUtilTest
 {
+    private final ConsoleStream logger = new DefaultDirectConsoleReporter( System.out );
+
     @DataPoint
     public static final int CPU_1 = 1;
 
@@ -968,7 +971,7 @@ public final class ParallelComputerUtilTest
         properties.put(PARALLEL_KEY, "methods");
         properties.put(THREADCOUNTMETHODS_KEY, "2");
         JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( new Logger(), params );
+        ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( logger, params );
         ParallelComputer pc = pcBuilder.buildComputer();
         Result result = new JUnitCore().run( pc, TestClass.class );
         long timeSpent = stopwatch.runtime( MILLISECONDS );
@@ -992,7 +995,7 @@ public final class ParallelComputerUtilTest
         properties.put(THREADCOUNTMETHODS_KEY, "2");
         properties.put(PARALLEL_TIMEOUT_KEY, Double.toString(2.5d));
         JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( new Logger(), params );
+        ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( logger, params );
         ParallelComputer pc = pcBuilder.buildComputer();
         new JUnitCore().run( pc, TestClass.class );
         long timeSpent = stopwatch.runtime( MILLISECONDS );
@@ -1015,7 +1018,7 @@ public final class ParallelComputerUtilTest
         properties.put(THREADCOUNTMETHODS_KEY, "2");
         properties.put(PARALLEL_TIMEOUTFORCED_KEY, Double.toString(2.5d));
         JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( new Logger(), params );
+        ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( logger, params );
         ParallelComputer pc = pcBuilder.buildComputer();
         new JUnitCore().run( pc, TestClass.class );
         long timeSpent = stopwatch.runtime( MILLISECONDS );
@@ -1041,7 +1044,7 @@ public final class ParallelComputerUtilTest
         properties.put(PARALLEL_TIMEOUT_KEY, Double.toString(2.5d));
         properties.put(PARALLEL_TIMEOUTFORCED_KEY, Double.toString(3.5d));
         JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( new Logger(), params );
+        ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( logger, params );
         ParallelComputer pc = pcBuilder.buildComputer();
         new JUnitCore().run( pc, TestClass.class );
         long timeSpent = stopwatch.runtime( MILLISECONDS );
@@ -1065,7 +1068,7 @@ public final class ParallelComputerUtilTest
         properties.put(PARALLEL_TIMEOUTFORCED_KEY, Double.toString(3.5d));
         properties.put(PARALLEL_TIMEOUT_KEY, Double.toString(4.0d));
         JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( new Logger(), params );
+        ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( logger, params );
         ParallelComputer pc = pcBuilder.buildComputer();
         new JUnitCore().run( pc, TestClass.class );
         long timeSpent = stopwatch.runtime( MILLISECONDS );


[5/5] maven-surefire git commit: [SUREFIRE-1254] add color messages

Posted by ti...@apache.org.
[SUREFIRE-1254] add color messages


Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/6a79127a
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/6a79127a
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/6a79127a

Branch: refs/heads/master
Commit: 6a79127ab63273f0f1f5268c65e4806761871a46
Parents: 2c9edf0
Author: Tibor17 <ti...@lycos.com>
Authored: Fri Sep 16 22:56:10 2016 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Sat Sep 17 00:53:49 2016 +0200

----------------------------------------------------------------------
 README.md                                       |   4 +-
 maven-failsafe-plugin/pom.xml                   |   1 -
 .../plugin/failsafe/IntegrationTestMojo.java    |  12 +-
 .../maven/plugin/failsafe/VerifyMojo.java       |  64 +++++--
 maven-surefire-common/pom.xml                   |  46 +++++
 .../plugin/surefire/AbstractSurefireMojo.java   | 149 +++++++++------
 .../maven/plugin/surefire/CommonReflector.java  |  34 ++--
 .../surefire/InPluginVMSurefireStarter.java     |  41 +++--
 .../surefire/StartupReportConfiguration.java    |  18 +-
 .../surefire/SurefireDependencyResolver.java    |   7 +-
 .../maven/plugin/surefire/SurefireHelper.java   |   9 +-
 .../surefire/booterclient/ForkStarter.java      |  39 ++--
 .../surefire/booterclient/ProviderDetector.java | 101 +---------
 .../booterclient/output/ForkClient.java         |  77 +++++---
 .../output/NativeStdErrStreamConsumer.java      |  38 ++++
 .../surefire/log/PluginConsoleLogger.java       | 126 +++++++++++++
 .../plugin/surefire/report/ConsoleReporter.java |  79 ++++----
 .../surefire/report/DefaultReporterFactory.java | 141 ++++++++++----
 .../surefire/report/DirectConsoleOutput.java    |   9 +-
 .../plugin/surefire/report/FileReporter.java    |  37 +---
 .../surefire/report/TestSetRunListener.java     |  80 ++++++--
 .../plugin/surefire/report/TestSetStats.java    | 125 ++++++++++++-
 .../maven/surefire/report/RunStatistics.java    |   4 -
 .../maven/surefire/spi/ServiceLoader.java       | 171 +++++++++++++++++
 .../plugin/surefire/SurefireReflectorTest.java  |   1 +
 .../booterclient/ForkingRunListenerTest.java    |  15 +-
 .../surefire/booterclient/MockReporter.java     |  28 ++-
 .../TestSetMockReporterFactory.java             |   6 +-
 .../report/DefaultReporterFactoryTest.java      |  90 +++++----
 .../apache/maven/surefire/JUnit4SuiteTest.java  |   6 +-
 .../maven/surefire/spi/CustomizedImpl.java      |  33 ++++
 .../apache/maven/surefire/spi/DefaultImpl.java  |  33 ++++
 .../surefire/spi/EmptyServiceInterface.java     |  30 +++
 .../surefire/spi/ExistingServiceInterface.java  |  30 +++
 .../org/apache/maven/surefire/spi/IDefault.java |  33 ++++
 .../maven/surefire/spi/NoServiceInterface.java  |  30 +++
 .../org/apache/maven/surefire/spi/SPITest.java  |  89 +++++++++
 .../org/apache/maven/surefire/spi/SPImpl1.java  |  44 +++++
 .../org/apache/maven/surefire/spi/SPImpl2.java  |  44 +++++
 ...che.maven.surefire.spi.EmptyServiceInterface |  21 +++
 ....maven.surefire.spi.ExistingServiceInterface |  24 +++
 .../org.apache.maven.surefire.spi.IDefault      |  22 +++
 maven-surefire-plugin/pom.xml                   |  26 +++
 .../maven/plugin/surefire/SurefirePlugin.java   |   4 +-
 maven-surefire-plugin/src/site/apt/index.apt.vm |   4 +
 maven-surefire-report-plugin/pom.xml            |  55 ++++++
 .../report/AbstractSurefireReportMojo.java      |  84 +++++----
 .../surefire/report/FailsafeReportMojo.java     |   2 +-
 .../surefire/report/PluginConsoleLogger.java    | 140 ++++++++++++++
 .../report/SurefireReportGenerator.java         |  23 +--
 .../surefire/report/Surefire597Test.java        |   5 +-
 pom.xml                                         |   6 +
 surefire-api/pom.xml                            |   4 +
 .../surefire/booter/BaseProviderFactory.java    |   8 +-
 .../maven/surefire/booter/CommandReader.java    |  24 ++-
 .../surefire/booter/ForkingRunListener.java     |  96 ++++++++--
 .../surefire/booter/SurefireReflector.java      |  23 ++-
 .../providerapi/ProviderParameters.java         |   6 +-
 .../maven/surefire/report/ConsoleLogger.java    |  33 ----
 .../surefire/report/ConsoleOutputCapture.java   |  13 +-
 .../maven/surefire/report/ConsoleStream.java    |   1 +
 .../surefire/report/DefaultConsoleReporter.java |  41 -----
 .../report/DefaultDirectConsoleReporter.java    |  11 +-
 .../maven/surefire/report/MockReporter.java     | 183 -------------------
 .../maven/surefire/booter/ForkedBooter.java     |  54 +++---
 surefire-integration-tests/pom.xml              |  47 +----
 .../surefire/its/Junit47concurrencyIT.java      |   4 +-
 .../maven/surefire/its/Not2xCompatible.java     |  27 ---
 .../surefire/its/fixture/HelperAssertions.java  |   8 +-
 .../Surefire1122ParallelAndFlakyTestsIT.java    |   2 -
 ...urefire1136CwdPropagationInForkedModeIT.java |   3 -
 .../jiras/Surefire1158RemoveInfoLinesIT.java    |   3 -
 ...e735ForkFailWithRedirectConsoleOutputIT.java |   3 -
 .../Surefire806SpecifiedTestControlsIT.java     |   3 -
 .../test/resources/concurrentjunit47/pom.xml    |   7 +-
 .../pom.xml                                     |  13 +-
 .../pom.xml                                     |  13 +-
 .../pom.xml                                     |  11 +-
 surefire-logger-api/pom.xml                     |  54 ++++++
 .../plugin/surefire/log/api/ConsoleLogger.java  |  64 +++++++
 .../log/api/ConsoleLoggerDecorator.java         |   1 +
 .../surefire/log/api/ConsoleLoggerUtils.java    |  55 ++++++
 .../maven/plugin/surefire/log/api/Level.java    |  66 +++++++
 .../surefire/log/api/NullConsoleLogger.java     |  53 ++++++
 .../surefire/log/api/PrintStreamLogger.java     |   1 +
 .../maven/surefire/junit/JUnit3Provider.java    |   1 -
 .../surefire/junit4/JUnit4ProviderTest.java     |   4 +-
 .../junitcore/ClassesParallelRunListener.java   |   7 +-
 .../junitcore/ConcurrentRunListener.java        |  54 +++---
 .../surefire/junitcore/JUnitCoreProvider.java   |  18 +-
 .../surefire/junitcore/JUnitCoreWrapper.java    |  10 +-
 .../junitcore/MethodsParallelRunListener.java   |   7 +-
 .../pc/AbstractThreadPoolStrategy.java          |   6 +-
 .../surefire/junitcore/pc/InvokerStrategy.java  |   4 +-
 .../pc/NonSharedThreadPoolStrategy.java         |   4 +-
 .../junitcore/pc/ParallelComputerBuilder.java   |   8 +-
 .../maven/surefire/junitcore/pc/Scheduler.java  |  34 ++--
 .../junitcore/pc/SchedulingStrategies.java      |  10 +-
 .../junitcore/pc/SchedulingStrategy.java        |   8 +-
 .../junitcore/pc/SharedThreadPoolStrategy.java  |   4 +-
 .../junitcore/pc/SingleThreadScheduler.java     |   6 +-
 .../junitcore/ConcurrentRunListenerTest.java    |   9 +-
 .../junitcore/DefaultConsoleReporter.java       |  68 +++++++
 .../surefire/junitcore/JUnitCoreTester.java     |  14 +-
 .../apache/maven/surefire/junitcore/Logger.java |  30 ---
 .../surefire/junitcore/Surefire746Test.java     |  11 +-
 .../pc/ParallelComputerBuilderTest.java         |  41 +++--
 .../junitcore/pc/ParallelComputerUtilTest.java  |  15 +-
 .../junitcore/pc/SchedulingStrategiesTest.java  |  20 +-
 surefire-report-parser/pom.xml                  |   4 +
 .../surefire/report/SurefireReportParser.java   |  15 +-
 .../surefire/report/TestSuiteXmlParser.java     |  15 +-
 .../report/SurefireReportParserTest.java        |   7 +-
 .../surefire/report/TestSuiteXmlParserTest.java |  69 ++++++-
 .../surefire/its/StagedLocalRepoHelper.java     |   2 +
 115 files changed, 2637 insertions(+), 1143 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index f5e147d..e7b4b07 100644
--- a/README.md
+++ b/README.md
@@ -24,10 +24,8 @@ Usage of [maven-surefire-plugin], [maven-failsafe-plugin], [maven-surefire-repor
 
 # Development Information
 
-Surefire needs Maven 3.0.5 and JDK 1.6+ to be built.
+Surefire needs to use Maven 3.1.0+ and JDK 1.6+ to be built.
 But in order to run IT tests, you can do:
-* -DmavenHomeUsed= path to a Maven 2.x home or -Pmaven-2.2.1, this profile will download Maven 2.2.1 distribution.
-  Use it to run integration tests.
 * In order to run tests for a release check during the vote the following memory requirements are needed:
   $ export MAVEN_OPTS="-Xmx768m -XX:MaxPermSize=1g -XX:SoftRefLRUPolicyMSPerMB=50 -Djava.awt.headless=true"
 * $ mvn install site site:stage -P reporting,run-its

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-failsafe-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/pom.xml b/maven-failsafe-plugin/pom.xml
index 5ca813a..fb1c0b6 100644
--- a/maven-failsafe-plugin/pom.xml
+++ b/maven-failsafe-plugin/pom.xml
@@ -203,7 +203,6 @@
           </execution>
         </executions>
       </plugin>
-
     </plugins>
   </build>
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
index bf50fec..78a3cd7 100644
--- a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
+++ b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
@@ -34,10 +34,11 @@ import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.plugins.annotations.ResolutionScope;
-import org.apache.maven.shared.utils.ReaderFactory;
 import org.apache.maven.shared.utils.StringUtils;
 import org.apache.maven.surefire.suite.RunResult;
 
+import static org.apache.maven.shared.utils.ReaderFactory.FILE_ENCODING;
+
 /**
  * Run integration tests using Surefire.
  *
@@ -363,10 +364,11 @@ public class IntegrationTestMojo
     {
         if ( StringUtils.isEmpty( encoding ) )
         {
-            getLog().warn( "File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
-                           + ", i.e. build is platform dependent! The file encoding for reports output files "
-                               + "should be provided by the POM property ${project.reporting.outputEncoding}." );
-            return ReaderFactory.FILE_ENCODING;
+            getConsoleLogger().warning( "File encoding has not been set, using platform encoding "
+                + FILE_ENCODING
+                + ", i.e. build is platform dependent! The file encoding for reports output files "
+                + "should be provided by the POM property ${project.reporting.outputEncoding}." );
+            return FILE_ENCODING;
         }
         else
         {

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/VerifyMojo.java
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/VerifyMojo.java b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/VerifyMojo.java
index 95f522e..37199a3 100644
--- a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/VerifyMojo.java
+++ b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/VerifyMojo.java
@@ -33,16 +33,21 @@ import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugin.surefire.SurefireHelper;
 import org.apache.maven.plugin.surefire.SurefireReportParameters;
+import org.apache.maven.plugin.surefire.log.PluginConsoleLogger;
 import org.apache.maven.plugins.annotations.Component;
 import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
-import org.apache.maven.shared.utils.ReaderFactory;
-import org.apache.maven.shared.utils.StringUtils;
-import org.apache.maven.shared.utils.io.IOUtil;
 import org.apache.maven.surefire.cli.CommandLineOption;
 import org.apache.maven.surefire.suite.RunResult;
 
+import static org.apache.maven.plugin.surefire.SurefireHelper.reportExecution;
+import static org.apache.maven.shared.utils.ReaderFactory.FILE_ENCODING;
+import static org.apache.maven.shared.utils.StringUtils.capitalizeFirstLetter;
+import static org.apache.maven.shared.utils.StringUtils.isEmpty;
+import static org.apache.maven.shared.utils.io.IOUtil.close;
+import static org.apache.maven.surefire.suite.RunResult.noTestsRun;
+
 /**
  * Verify integration tests ran using Surefire.
  *
@@ -159,6 +164,8 @@ public class VerifyMojo
 
     private Collection<CommandLineOption> cli;
 
+    private volatile PluginConsoleLogger consoleLogger;
+
     public void execute()
         throws MojoExecutionException, MojoFailureException
     {
@@ -166,26 +173,28 @@ public class VerifyMojo
         if ( verifyParameters() )
         {
             logDebugOrCliShowErrors(
-                StringUtils.capitalizeFirstLetter( getPluginName() ) + " report directory: " + getReportsDirectory() );
+                capitalizeFirstLetter( getPluginName() ) + " report directory: " + getReportsDirectory() );
 
             RunResult summary;
             try
             {
                 final String encoding;
-                if ( StringUtils.isEmpty( this.encoding ) )
+                if ( isEmpty( this.encoding ) )
                 {
-                    getLog().warn( "File encoding has not been set, using platform encoding "
-                            + ReaderFactory.FILE_ENCODING
-                            + ", i.e. build is platform dependent! The file encoding for reports output files "
-                            + "should be provided by the POM property ${project.reporting.outputEncoding}." );
-                    encoding = ReaderFactory.FILE_ENCODING;
+                    getConsoleLogger()
+                            .warning( "File encoding has not been set, using platform encoding "
+                                              + FILE_ENCODING
+                                              + ", i.e. build is platform dependent! The file encoding for "
+                                              + "reports output files should be provided by the POM property "
+                                              + "${project.reporting.outputEncoding}." );
+                    encoding = FILE_ENCODING;
                 }
                 else
                 {
                     encoding = this.encoding;
                 }
 
-                summary = existsSummaryFile() ? readSummary( encoding, summaryFile ) : RunResult.noTestsRun();
+                summary = existsSummaryFile() ? readSummary( encoding, summaryFile ) : noTestsRun();
 
                 if ( existsSummaryFiles() )
                 {
@@ -200,8 +209,23 @@ public class VerifyMojo
                 throw new MojoExecutionException( e.getMessage(), e );
             }
 
-            SurefireHelper.reportExecution( this, summary, getLog() );
+            reportExecution( this, summary, getConsoleLogger() );
+        }
+    }
+
+    private PluginConsoleLogger getConsoleLogger()
+    {
+        if ( consoleLogger == null )
+        {
+            synchronized ( this )
+            {
+                if ( consoleLogger == null )
+                {
+                    consoleLogger = new PluginConsoleLogger( getLog() );
+                }
+            }
         }
+        return consoleLogger;
     }
 
     private RunResult readSummary( String encoding, File summaryFile )
@@ -219,9 +243,9 @@ public class VerifyMojo
         }
         finally
         {
-            IOUtil.close( reader );
-            IOUtil.close( bufferedInputStream );
-            IOUtil.close( fileInputStream );
+            close( reader );
+            close( bufferedInputStream );
+            close( fileInputStream );
         }
     }
 
@@ -230,7 +254,7 @@ public class VerifyMojo
     {
         if ( isSkip() || isSkipTests() || isSkipITs() || isSkipExec() )
         {
-            getLog().info( "Tests are skipped." );
+            getConsoleLogger().info( "Tests are skipped." );
             return false;
         }
 
@@ -244,7 +268,7 @@ public class VerifyMojo
 
         if ( !existsSummary() )
         {
-            getLog().info( "No tests to run." );
+            getConsoleLogger().info( "No tests to run." );
             return false;
         }
 
@@ -370,12 +394,12 @@ public class VerifyMojo
 
     private Collection<CommandLineOption> commandLineOptions()
     {
-        return SurefireHelper.commandLineOptions( session, getLog() );
+        return SurefireHelper.commandLineOptions( session, getConsoleLogger() );
     }
 
-    private void logDebugOrCliShowErrors( CharSequence s )
+    private void logDebugOrCliShowErrors( String s )
     {
-        SurefireHelper.logDebugOrCliShowErrors( s, getLog(), cli );
+        SurefireHelper.logDebugOrCliShowErrors( s, getConsoleLogger(), cli );
     }
 
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/pom.xml
----------------------------------------------------------------------
diff --git a/maven-surefire-common/pom.xml b/maven-surefire-common/pom.xml
index aef1950..5336982 100644
--- a/maven-surefire-common/pom.xml
+++ b/maven-surefire-common/pom.xml
@@ -106,6 +106,12 @@
       </exclusions>
     </dependency>
     <dependency>
+      <groupId>org.fusesource.jansi</groupId>
+      <artifactId>jansi</artifactId>
+      <version>1.13</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
       <groupId>org.mockito</groupId>
       <artifactId>mockito-all</artifactId>
       <version>1.8.4</version>
@@ -116,12 +122,52 @@
   <build>
     <plugins>
       <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <version>1.12</version>
+        <executions>
+          <execution>
+            <id>add-source</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${project.build.directory}/generated-sources</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>shared-logging-generated-sources</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>unpack</goal>
+            </goals>
+            <configuration>
+              <outputDirectory>${project.build.directory}/generated-sources</outputDirectory>
+              <overWriteIfNewer>false</overWriteIfNewer>
+              <artifact>org.apache.maven.shared:maven-shared-utils:3.1.0:jar:sources</artifact>
+              <includes>org/apache/maven/shared/utils/logging/*.java</includes>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
           <redirectTestOutputToFile>true</redirectTestOutputToFile>
           <includes>
             <include>**/JUnit4SuiteTest.java</include>
           </includes>
+          <classpathDependencyExcludes>
+            <classpathDependencyExclude>org.fusesource.jansi:jansi</classpathDependencyExclude>
+          </classpathDependencyExcludes>
         </configuration>
         <dependencies>
           <dependency>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
index eaa01a8..cd27edf 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
@@ -57,11 +57,11 @@ import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugin.descriptor.PluginDescriptor;
-import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.plugin.surefire.booterclient.ChecksumCalculator;
 import org.apache.maven.plugin.surefire.booterclient.ForkConfiguration;
 import org.apache.maven.plugin.surefire.booterclient.ForkStarter;
 import org.apache.maven.plugin.surefire.booterclient.ProviderDetector;
+import org.apache.maven.plugin.surefire.log.PluginConsoleLogger;
 import org.apache.maven.plugin.surefire.util.DependencyScanner;
 import org.apache.maven.plugin.surefire.util.DirectoryScanner;
 import org.apache.maven.plugins.annotations.Component;
@@ -82,6 +82,7 @@ import org.apache.maven.surefire.booter.SurefireBooterForkException;
 import org.apache.maven.surefire.booter.SurefireExecutionException;
 import org.apache.maven.surefire.cli.CommandLineOption;
 import org.apache.maven.surefire.providerapi.SurefireProvider;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.surefire.report.ReporterConfiguration;
 import org.apache.maven.surefire.suite.RunResult;
 import org.apache.maven.surefire.testset.DirectoryScannerParameters;
@@ -97,6 +98,10 @@ import org.apache.maven.toolchain.ToolchainManager;
 
 import javax.annotation.Nonnull;
 
+import static java.lang.Thread.currentThread;
+import static org.apache.maven.shared.utils.StringUtils.capitalizeFirstLetter;
+import static org.apache.maven.shared.utils.StringUtils.isNotBlank;
+
 /**
  * Abstract base class for running tests using Surefire.
  *
@@ -107,8 +112,7 @@ public abstract class AbstractSurefireMojo
     extends AbstractMojo
     implements SurefireExecutionParameters
 {
-
-    // common mojo parameters
+    private final ProviderDetector providerDetector = new ProviderDetector();
 
     /**
      * Information about this plugin, mainly used to lookup this plugin's configuration from the currently executing
@@ -735,6 +739,8 @@ public abstract class AbstractSurefireMojo
 
     private List<CommandLineOption> cli;
 
+    private volatile PluginConsoleLogger consoleLogger;
+
     public void execute()
         throws MojoExecutionException, MojoFailureException
     {
@@ -760,6 +766,21 @@ public abstract class AbstractSurefireMojo
         }
     }
 
+    protected final PluginConsoleLogger getConsoleLogger()
+    {
+        if ( consoleLogger == null )
+        {
+            synchronized ( this )
+            {
+                if ( consoleLogger == null )
+                {
+                    consoleLogger = new PluginConsoleLogger( getLog() );
+                }
+            }
+        }
+        return consoleLogger;
+    }
+
     private void setupStuff()
     {
         createDependencyResolver();
@@ -812,17 +833,17 @@ public abstract class AbstractSurefireMojo
         setProperties( new SurefireProperties( getProperties() ) );
         if ( isSkipExecution() )
         {
-            getLog().info( "Tests are skipped." );
+            getConsoleLogger().info( "Tests are skipped." );
             return false;
         }
 
         String jvmToUse = getJvm();
         if ( toolchain != null )
         {
-            getLog().info( "Toolchain in maven-" + getPluginName() + "-plugin: " + toolchain );
+            getConsoleLogger().info( "Toolchain in maven-" + getPluginName() + "-plugin: " + toolchain );
             if ( jvmToUse != null )
             {
-                getLog().warn( "Toolchains are ignored, 'executable' parameter is set to " + jvmToUse );
+                getConsoleLogger().warning( "Toolchains are ignored, 'executable' parameter is set to " + jvmToUse );
             }
         }
 
@@ -833,7 +854,7 @@ public abstract class AbstractSurefireMojo
             {
                 throw new MojoFailureException( "No tests to run!" );
             }
-            getLog().info( "No tests to run." );
+            getConsoleLogger().info( "No tests to run." );
         }
         else
         {
@@ -898,9 +919,10 @@ public abstract class AbstractSurefireMojo
 
     private void createDependencyResolver()
     {
-        dependencyResolver =
-            new SurefireDependencyResolver( getArtifactResolver(), getArtifactFactory(), getLog(), getLocalRepository(),
-                                            getRemoteRepositories(), getMetadataSource(), getPluginName() );
+        dependencyResolver = new SurefireDependencyResolver( getArtifactResolver(), getArtifactFactory(),
+                                                                   getConsoleLogger(), getLocalRepository(),
+                                                                   getRemoteRepositories(), getMetadataSource(),
+                                                                   getPluginName() );
     }
 
     protected List<ProviderInfo> createProviders()
@@ -925,13 +947,13 @@ public abstract class AbstractSurefireMojo
         catch ( IOException e )
         {
             String msg = "The system property file '" + systemPropertiesFile.getAbsolutePath() + "' can't be read.";
-            if ( getLog().isDebugEnabled() )
+            if ( getConsoleLogger().isDebugEnabled() )
             {
-                getLog().warn( msg, e );
+                getConsoleLogger().debug( msg, e );
             }
             else
             {
-                getLog().warn( msg );
+                getConsoleLogger().warning( msg );
             }
         }
 
@@ -948,20 +970,25 @@ public abstract class AbstractSurefireMojo
             {
                 if ( getArgLine() == null || !getArgLine().contains( "-D" + o + "=" ) )
                 {
-                    getLog().warn( o + " cannot be set as system property, use <argLine>-D"
-                                       + o + "=...</argLine> instead" );
+                    getConsoleLogger().warning( o + " cannot be set as system property, use <argLine>-D"
+                                                        + o + "=...</argLine> instead"
+                    );
                 }
             }
             for ( Object systemPropertyMatchingArgLine : systemPropertiesMatchingArgLine( result ) )
             {
-                getLog().warn( "The system property " + systemPropertyMatchingArgLine + " is configured twice! "
-                                   + "The property appears in <argLine/> and any of <systemPropertyVariables/>, "
-                                   + "<systemProperties/> or user property." );
+                getConsoleLogger()
+                        .warning( "The system property "
+                                          + systemPropertyMatchingArgLine
+                                          + " is configured twice! "
+                                          + "The property appears in <argLine/> and any of <systemPropertyVariables/>, "
+                                          + "<systemProperties/> or user property."
+                        );
             }
         }
-        if ( getLog().isDebugEnabled() )
+        if ( getConsoleLogger().isDebugEnabled() )
         {
-            showToLog( result, getLog(), "system property" );
+            showToLog( result, getConsoleLogger(), "system property" );
         }
         return result;
     }
@@ -969,7 +996,7 @@ public abstract class AbstractSurefireMojo
     private Set<Object> systemPropertiesMatchingArgLine( SurefireProperties result )
     {
         Set<Object> intersection = new HashSet<Object>();
-        if ( StringUtils.isNotBlank( getArgLine() ) )
+        if ( isNotBlank( getArgLine() ) )
         {
             for ( Object systemProperty : result.getStringKeySet() )
             {
@@ -985,7 +1012,7 @@ public abstract class AbstractSurefireMojo
         return intersection;
     }
 
-    public void showToLog( SurefireProperties props, org.apache.maven.plugin.logging.Log log, String setting )
+    private void showToLog( SurefireProperties props, ConsoleLogger log, String setting )
     {
         for ( Object key : props.getStringKeySet() )
         {
@@ -994,7 +1021,6 @@ public abstract class AbstractSurefireMojo
         }
     }
 
-
     private RunResult executeProvider( ProviderInfo provider, DefaultScanResult scanResult )
         throws MojoExecutionException, MojoFailureException, SurefireExecutionException, SurefireBooterForkException,
         TestSetFailedException
@@ -1016,7 +1042,7 @@ public abstract class AbstractSurefireMojo
         else
         {
             ForkConfiguration forkConfiguration = getForkConfiguration();
-            if ( getLog().isDebugEnabled() )
+            if ( getConsoleLogger().isDebugEnabled() )
             {
                 showMap( getEnvironmentVariables(), "environment variable" );
             }
@@ -1026,7 +1052,7 @@ public abstract class AbstractSurefireMojo
             {
                 ForkStarter forkStarter =
                     createForkStarter( provider, forkConfiguration, classLoaderConfiguration, runOrderParameters,
-                                       getLog() );
+                                       getConsoleLogger() );
                 return forkStarter.run( effectiveProperties, scanResult );
             }
             finally
@@ -1058,16 +1084,17 @@ public abstract class AbstractSurefireMojo
 
     protected void cleanupForkConfiguration( ForkConfiguration forkConfiguration )
     {
-        if ( !getLog().isDebugEnabled() && forkConfiguration != null )
+        if ( !getConsoleLogger().isDebugEnabled() && forkConfiguration != null )
         {
             File tempDirectory = forkConfiguration.getTempDirectory();
             try
             {
                 FileUtils.deleteDirectory( tempDirectory );
             }
-            catch ( IOException ioe )
+            catch ( IOException e )
             {
-                getLog().warn( "Could not delete temp directory " + tempDirectory + " because " + ioe.getMessage() );
+                getConsoleLogger()
+                        .warning( "Could not delete temp directory " + tempDirectory + " because " + e.getMessage() );
             }
         }
     }
@@ -1075,7 +1102,7 @@ public abstract class AbstractSurefireMojo
     protected void logReportsDirectory()
     {
         logDebugOrCliShowErrors(
-            StringUtils.capitalizeFirstLetter( getPluginName() ) + " report directory: " + getReportsDirectory() );
+            capitalizeFirstLetter( getPluginName() ) + " report directory: " + getReportsDirectory() );
     }
 
     final Toolchain getToolchain()
@@ -1121,11 +1148,13 @@ public abstract class AbstractSurefireMojo
         {
             DefaultArtifactVersion defaultArtifactVersion = new DefaultArtifactVersion( testNgArtifact.getVersion() );
             getProperties().setProperty( "testng.configurator", getConfiguratorName( defaultArtifactVersion,
-                                                                                     getLog() ) );
+                                                                                           getConsoleLogger()
+                    )
+            );
         }
     }
 
-    private static String getConfiguratorName( ArtifactVersion version, Log log )
+    private static String getConfiguratorName( ArtifactVersion version, PluginConsoleLogger log )
         throws MojoExecutionException
     {
         try
@@ -1158,7 +1187,7 @@ public abstract class AbstractSurefireMojo
             range = VersionRange.createFromVersionSpec( "[5.14.1,5.14.3)" );
             if ( range.containsVersion( version ) )
             {
-                log.warn( "The 'reporter' or 'listener' may not work properly in TestNG 5.14.1 and 5.14.2." );
+                log.warning( "The 'reporter' or 'listener' may not work properly in TestNG 5.14.1 and 5.14.2." );
                 return "org.apache.maven.surefire.testng.conf.TestNG5141Configurator";
             }
             range = VersionRange.createFromVersionSpec( "[5.14.3,6.0)" );
@@ -1559,11 +1588,11 @@ public abstract class AbstractSurefireMojo
 
             final Classpath testClasspath = generateTestClasspath();
 
-            getLog().debug( testClasspath.getLogMessage( "test" ) );
-            getLog().debug( providerClasspath.getLogMessage( "provider" ) );
+            getConsoleLogger().debug( testClasspath.getLogMessage( "test" ) );
+            getConsoleLogger().debug( providerClasspath.getLogMessage( "provider" ) );
 
-            getLog().debug( testClasspath.getCompactLogMessage( "test(compact)" ) );
-            getLog().debug( providerClasspath.getCompactLogMessage( "provider(compact)" ) );
+            getConsoleLogger().debug( testClasspath.getCompactLogMessage( "test(compact)" ) );
+            getConsoleLogger().debug( providerClasspath.getCompactLogMessage( "provider(compact)" ) );
 
             final ClasspathConfiguration classpathConfiguration =
                 new ClasspathConfiguration( testClasspath, providerClasspath, inprocClassPath,
@@ -1607,12 +1636,12 @@ public abstract class AbstractSurefireMojo
 
     private boolean isSpecificTestSpecified()
     {
-        return StringUtils.isNotBlank( getTest() );
+        return isNotBlank( getTest() );
     }
 
     @Nonnull private List<String> readListFromFile( @Nonnull final File file )
     {
-        getLog().debug( "Reading list from: " + file );
+        getConsoleLogger().debug( "Reading list from: " + file );
 
         if ( !file.exists() )
         {
@@ -1623,12 +1652,12 @@ public abstract class AbstractSurefireMojo
         {
             List<String> list = FileUtils.loadFile( file );
 
-            if ( getLog().isDebugEnabled() )
+            if ( getConsoleLogger().isDebugEnabled() )
             {
-                getLog().debug( "List contents:" );
+                getConsoleLogger().debug( "List contents:" );
                 for ( String entry : list )
                 {
-                    getLog().debug( "  " + entry );
+                    getConsoleLogger().debug( "  " + entry );
                 }
             }
             return list;
@@ -1830,7 +1859,7 @@ public abstract class AbstractSurefireMojo
 
     private ForkStarter createForkStarter( ProviderInfo provider, ForkConfiguration forkConfiguration,
                                              ClassLoaderConfiguration classLoaderConfiguration,
-                                             RunOrderParameters runOrderParameters, Log log )
+                                             RunOrderParameters runOrderParameters, ConsoleLogger log )
         throws MojoExecutionException, MojoFailureException
     {
         StartupConfiguration startupConfiguration = createStartupConfiguration( provider, classLoaderConfiguration );
@@ -1850,7 +1879,8 @@ public abstract class AbstractSurefireMojo
         String configChecksum = getConfigChecksum();
         StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum );
         ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters );
-        return new InPluginVMSurefireStarter( startupConfiguration, providerConfiguration, startupReportConfiguration );
+        return new InPluginVMSurefireStarter( startupConfiguration, providerConfiguration,
+                                                    startupReportConfiguration, consoleLogger );
 
     }
 
@@ -1869,7 +1899,7 @@ public abstract class AbstractSurefireMojo
                                       getEffectiveJvm(),
                                       getWorkingDirectory() != null ? getWorkingDirectory() : getBasedir(),
                                       getProject().getModel().getProperties(),
-                                      getArgLine(), getEnvironmentVariables(), getLog().isDebugEnabled(),
+                                      getArgLine(), getEnvironmentVariables(), getConsoleLogger().isDebugEnabled(),
                                       getEffectiveForkCount(), reuseForks );
     }
 
@@ -1893,8 +1923,8 @@ public abstract class AbstractSurefireMojo
 
         if ( !ForkConfiguration.FORK_ONCE.equals( getForkMode() ) )
         {
-            getLog().warn(
-                "The parameter forkMode is deprecated since version 2.14. Use forkCount and reuseForks instead." );
+            getConsoleLogger().warning( "The parameter forkMode is deprecated since version 2.14. "
+                                                + "Use forkCount and reuseForks instead." );
         }
     }
 
@@ -1958,7 +1988,7 @@ public abstract class AbstractSurefireMojo
         {
             // use the same JVM as the one used to run Maven (the "java.home" one)
             jvmToUse = System.getProperty( "java.home" ) + File.separator + "bin" + File.separator + "java";
-            getLog().debug( "Using JVM: " + jvmToUse );
+            getConsoleLogger().debug( "Using JVM: " + jvmToUse );
         }
 
         return jvmToUse;
@@ -2073,7 +2103,8 @@ public abstract class AbstractSurefireMojo
         @SuppressWarnings( "unchecked" ) Map<String, String> pluginContext = getPluginContext();
         if ( pluginContext.containsKey( configChecksum ) )
         {
-            getLog().info( "Skipping execution of surefire because it has already been run for this configuration" );
+            getConsoleLogger()
+                    .info( "Skipping execution of surefire because it has already been run for this configuration" );
             return true;
         }
         pluginContext.put( configChecksum, configChecksum );
@@ -2208,7 +2239,7 @@ public abstract class AbstractSurefireMojo
         {
             String key = (String) o;
             String value = (String) map.get( key );
-            getLog().debug( "Setting " + setting + " [" + key + "]=[" + value + "]" );
+            getConsoleLogger().debug( "Setting " + setting + " [" + key + "]=[" + value + "]" );
         }
     }
 
@@ -2252,7 +2283,7 @@ public abstract class AbstractSurefireMojo
             {
                 Artifact artifact = (Artifact) o;
 
-                getLog().debug(
+                getConsoleLogger().debug(
                     "Adding to " + getPluginName() + " booter test classpath: " + artifact.getFile().getAbsolutePath()
                     + " Scope: " + artifact.getScope() );
 
@@ -2277,13 +2308,13 @@ public abstract class AbstractSurefireMojo
         {
             String msg = "Build uses Maven 2.0.x, cannot propagate system properties"
                 + " from command line to tests (cf. SUREFIRE-121)";
-            if ( getLog().isDebugEnabled() )
+            if ( getConsoleLogger().isDebugEnabled() )
             {
-                getLog().warn( msg, e );
+                getConsoleLogger().debug( msg, e );
             }
             else
             {
-                getLog().warn( msg );
+                getConsoleLogger().warning( msg );
             }
         }
         if ( props == null )
@@ -2346,7 +2377,7 @@ public abstract class AbstractSurefireMojo
     {
         if ( isUseSystemClassLoader() && isNotForking() )
         {
-            getLog().warn( "useSystemClassloader setting has no effect when not forking" );
+            getConsoleLogger().warning( "useSystemClassloader setting has no effect when not forking" );
         }
     }
 
@@ -2357,7 +2388,7 @@ public abstract class AbstractSurefireMojo
 
     private List<CommandLineOption> commandLineOptions()
     {
-        return SurefireHelper.commandLineOptions( getSession(), getLog() );
+        return SurefireHelper.commandLineOptions( getSession(), getConsoleLogger() );
     }
 
     private void warnIfDefunctGroupsCombinations()
@@ -2695,8 +2726,8 @@ public abstract class AbstractSurefireMojo
         {
             try
             {
-                return ProviderDetector.getServiceNames( SurefireProvider.class,
-                                                         Thread.currentThread().getContextClassLoader() );
+                ClassLoader cl = currentThread().getContextClassLoader();
+                return providerDetector.lookupServiceNames( SurefireProvider.class, cl );
             }
             catch ( IOException e )
             {
@@ -3236,8 +3267,8 @@ public abstract class AbstractSurefireMojo
         this.classpathDependencyScopeExclude = classpathDependencyScopeExclude;
     }
 
-    protected void logDebugOrCliShowErrors( CharSequence s )
+    protected void logDebugOrCliShowErrors( String s )
     {
-        SurefireHelper.logDebugOrCliShowErrors( s, getLog(), cli );
+        SurefireHelper.logDebugOrCliShowErrors( s, getConsoleLogger(), cli );
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java
index 06ec9a5..4ae589f 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java
@@ -21,19 +21,25 @@ package org.apache.maven.plugin.surefire;
 
 import java.io.File;
 import java.lang.reflect.Constructor;
+
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.plugin.surefire.report.DefaultReporterFactory;
-import org.apache.maven.surefire.util.ReflectionUtils;
+import org.apache.maven.surefire.booter.SurefireReflector;
 import org.apache.maven.surefire.util.SurefireReflectionException;
 
 import javax.annotation.Nonnull;
 
+import static org.apache.maven.surefire.util.ReflectionUtils.getConstructor;
+import static org.apache.maven.surefire.util.ReflectionUtils.instantiateObject;
+import static org.apache.maven.surefire.util.ReflectionUtils.newInstance;
+
 /**
  * @author Kristian Rosenvold
  */
 public class CommonReflector
 {
     private final Class<?> startupReportConfiguration;
-
+    private final Class<?> consoleLogger;
     private final ClassLoader surefireClassLoader;
 
     public CommonReflector( @Nonnull ClassLoader surefireClassLoader )
@@ -43,6 +49,7 @@ public class CommonReflector
         try
         {
             startupReportConfiguration = surefireClassLoader.loadClass( StartupReportConfiguration.class.getName() );
+            consoleLogger = surefireClassLoader.loadClass( ConsoleLogger.class.getName() );
         }
         catch ( ClassNotFoundException e )
         {
@@ -50,23 +57,22 @@ public class CommonReflector
         }
     }
 
-    public Object createReportingReporterFactory( @Nonnull StartupReportConfiguration startupReportConfiguration )
+    public Object createReportingReporterFactory( @Nonnull StartupReportConfiguration startupReportConfiguration,
+                                                  @Nonnull ConsoleLogger consoleLogger )
     {
-        Class<?>[] args = new Class[]{ this.startupReportConfiguration };
+        Class<?>[] args = { this.startupReportConfiguration, this.consoleLogger };
         Object src = createStartupReportConfiguration( startupReportConfiguration );
-        Object[] params = new Object[]{ src };
-        return ReflectionUtils.instantiateObject( DefaultReporterFactory.class.getName(), args, params,
-                                                  surefireClassLoader );
+        Object logger = SurefireReflector.createConsoleLogger( consoleLogger, surefireClassLoader );
+        Object[] params = { src, logger };
+        return instantiateObject( DefaultReporterFactory.class.getName(), args, params, surefireClassLoader );
     }
 
     private Object createStartupReportConfiguration( @Nonnull StartupReportConfiguration reporterConfiguration )
     {
-        Constructor<?> constructor = ReflectionUtils.getConstructor( startupReportConfiguration,
-                                                                     boolean.class, boolean.class,
-                                                                     String.class, boolean.class, boolean.class,
-                                                                     File.class, boolean.class, String.class,
-                                                                     String.class, boolean.class, int.class,
-                                                                     String.class );
+        Constructor<?> constructor = getConstructor( startupReportConfiguration, boolean.class, boolean.class,
+                                                           String.class, boolean.class, boolean.class, File.class,
+                                                           boolean.class, String.class, String.class, boolean.class,
+                                                           int.class, String.class );
         //noinspection BooleanConstructorCall
         Object[] params = { reporterConfiguration.isUseFile(), reporterConfiguration.isPrintSummary(),
             reporterConfiguration.getReportFormat(), reporterConfiguration.isRedirectTestOutputToFile(),
@@ -74,7 +80,7 @@ public class CommonReflector
             reporterConfiguration.isTrimStackTrace(), reporterConfiguration.getReportNameSuffix(),
             reporterConfiguration.getConfigurationHash(), reporterConfiguration.isRequiresRunHistory(),
             reporterConfiguration.getRerunFailingTestsCount(), reporterConfiguration.getXsdSchemaLocation() };
-        return ReflectionUtils.newInstance( constructor, params );
+        return newInstance( constructor, params );
     }
 
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/InPluginVMSurefireStarter.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/InPluginVMSurefireStarter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/InPluginVMSurefireStarter.java
index 5ab361d..f0d299e 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/InPluginVMSurefireStarter.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/InPluginVMSurefireStarter.java
@@ -19,8 +19,8 @@ package org.apache.maven.plugin.surefire;
  * under the License.
  */
 
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.surefire.booter.ProviderConfiguration;
-import org.apache.maven.surefire.booter.ProviderFactory;
 import org.apache.maven.surefire.booter.StartupConfiguration;
 import org.apache.maven.surefire.booter.SurefireExecutionException;
 import org.apache.maven.surefire.suite.RunResult;
@@ -31,6 +31,8 @@ import javax.annotation.Nonnull;
 import java.lang.reflect.InvocationTargetException;
 import java.util.Map;
 
+import static org.apache.maven.surefire.booter.ProviderFactory.invokeProvider;
+
 /**
  * Starts the provider in the same VM as the surefire plugin.
  * <p/>
@@ -45,20 +47,20 @@ import java.util.Map;
  */
 public class InPluginVMSurefireStarter
 {
+    private final StartupConfiguration startupConfig;
+    private final StartupReportConfiguration startupReportConfig;
+    private final ProviderConfiguration providerConfig;
+    private final ConsoleLogger consoleLogger;
 
-    private final StartupConfiguration startupConfiguration;
-
-    private final StartupReportConfiguration startupReportConfiguration;
-
-    private final ProviderConfiguration providerConfiguration;
-
-    public InPluginVMSurefireStarter( @Nonnull StartupConfiguration startupConfiguration,
-                                      @Nonnull ProviderConfiguration providerConfiguration,
-                                      @Nonnull StartupReportConfiguration startupReportConfiguration )
+    public InPluginVMSurefireStarter( @Nonnull StartupConfiguration startupConfig,
+                                      @Nonnull ProviderConfiguration providerConfig,
+                                      @Nonnull StartupReportConfiguration startupReportConfig,
+                                      @Nonnull ConsoleLogger consoleLogger )
     {
-        this.startupConfiguration = startupConfiguration;
-        this.startupReportConfiguration = startupReportConfiguration;
-        this.providerConfiguration = providerConfiguration;
+        this.startupConfig = startupConfig;
+        this.startupReportConfig = startupReportConfig;
+        this.providerConfig = providerConfig;
+        this.consoleLogger = consoleLogger;
     }
 
     public RunResult runSuitesInProcess( @Nonnull DefaultScanResult scanResult )
@@ -67,20 +69,19 @@ public class InPluginVMSurefireStarter
         // The test classloader must be constructed first to avoid issues with commons-logging until we properly
         // separate the TestNG classloader
 
-        Map<String, String> providerProperties = providerConfiguration.getProviderProperties();
+        Map<String, String> providerProperties = providerConfig.getProviderProperties();
         scanResult.writeTo( providerProperties );
 
-        startupConfiguration.writeSurefireTestClasspathProperty();
-        ClassLoader testsClassLoader = startupConfiguration.getClasspathConfiguration().createMergedClassLoader();
+        startupConfig.writeSurefireTestClasspathProperty();
+        ClassLoader testClassLoader = startupConfig.getClasspathConfiguration().createMergedClassLoader();
 
-        CommonReflector surefireReflector = new CommonReflector( testsClassLoader );
+        CommonReflector surefireReflector = new CommonReflector( testClassLoader );
 
-        final Object factory = surefireReflector.createReportingReporterFactory( startupReportConfiguration );
+        Object factory = surefireReflector.createReportingReporterFactory( startupReportConfig, consoleLogger );
 
         try
         {
-            return ProviderFactory.invokeProvider( null, testsClassLoader, factory,
-                                                   providerConfiguration, false, startupConfiguration, true );
+            return invokeProvider( null, testClassLoader, factory, providerConfig, false, startupConfig, true );
         }
         catch ( InvocationTargetException e )
         {

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java
index f45b303..30156f9 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java
@@ -27,7 +27,6 @@ import java.util.Properties;
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.maven.plugin.surefire.report.ConsoleOutputFileReporter;
-import org.apache.maven.plugin.surefire.report.ConsoleReporter;
 import org.apache.maven.plugin.surefire.report.DirectConsoleOutput;
 import org.apache.maven.plugin.surefire.report.FileReporter;
 import org.apache.maven.plugin.surefire.report.StatelessXmlReporter;
@@ -37,6 +36,9 @@ import org.apache.maven.plugin.surefire.runorder.StatisticsReporter;
 
 import javax.annotation.Nonnull;
 
+import static org.apache.maven.plugin.surefire.report.ConsoleReporter.BRIEF;
+import static org.apache.maven.plugin.surefire.report.ConsoleReporter.PLAIN;
+
 /**
  * All the parameters used to construct reporters
  * <p/>
@@ -45,9 +47,9 @@ import javax.annotation.Nonnull;
  */
 public class StartupReportConfiguration
 {
-    public static final String BRIEF_REPORT_FORMAT = ConsoleReporter.BRIEF;
+    public static final String BRIEF_REPORT_FORMAT = BRIEF;
 
-    public static final String PLAIN_REPORT_FORMAT = ConsoleReporter.PLAIN;
+    public static final String PLAIN_REPORT_FORMAT = PLAIN;
 
     private final PrintStream originalSystemOut;
 
@@ -186,16 +188,6 @@ public class StartupReportConfiguration
         return BRIEF_REPORT_FORMAT.equals( fmt ) || PLAIN_REPORT_FORMAT.equals( fmt );
     }
 
-    public ConsoleReporter instantiateConsoleReporter()
-    {
-        return shouldReportToConsole() ? new ConsoleReporter( originalSystemOut ) : null;
-    }
-
-    private boolean shouldReportToConsole()
-    {
-        return isUseFile() ? isPrintSummary() : isRedirectTestOutputToFile() || isBriefOrPlainFormat();
-    }
-
     public TestcycleConsoleOutputReceiver instantiateConsoleOutputFileReporter()
     {
         return isRedirectTestOutputToFile()

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java
index 41b6171..12a1239 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java
@@ -37,8 +37,8 @@ import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
 import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
 import org.apache.maven.artifact.versioning.VersionRange;
-import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.surefire.booter.Classpath;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -56,7 +56,7 @@ public class SurefireDependencyResolver
 
     private final ArtifactFactory artifactFactory;
 
-    private final org.apache.maven.plugin.logging.Log log;
+    private final ConsoleLogger log;
 
     private final ArtifactRepository localRepository;
 
@@ -66,7 +66,8 @@ public class SurefireDependencyResolver
 
     private final String pluginName;
 
-    protected SurefireDependencyResolver( ArtifactResolver artifactResolver, ArtifactFactory artifactFactory, Log log,
+    protected SurefireDependencyResolver( ArtifactResolver artifactResolver, ArtifactFactory artifactFactory,
+                                          ConsoleLogger log,
                                           ArtifactRepository localRepository,
                                           List<ArtifactRepository> remoteRepositories,
                                           ArtifactMetadataSource artifactMetadataSource, String pluginName )

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireHelper.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireHelper.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireHelper.java
index 8952787..3f87c3c 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireHelper.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireHelper.java
@@ -23,7 +23,7 @@ import org.apache.maven.execution.MavenExecutionRequest;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
-import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.plugin.surefire.log.PluginConsoleLogger;
 import org.apache.maven.surefire.cli.CommandLineOption;
 import org.apache.maven.surefire.suite.RunResult;
 
@@ -54,7 +54,8 @@ public final class SurefireHelper
         throw new IllegalAccessError( "Utility class" );
     }
 
-    public static void reportExecution( SurefireReportParameters reportParameters, RunResult result, Log log )
+    public static void reportExecution( SurefireReportParameters reportParameters, RunResult result,
+                                        PluginConsoleLogger log )
         throws MojoFailureException, MojoExecutionException
     {
         boolean timeoutOrOtherFailure = result.isFailureOrTimeout();
@@ -99,7 +100,7 @@ public final class SurefireHelper
         }
     }
 
-    public static List<CommandLineOption> commandLineOptions( MavenSession session, Log log )
+    public static List<CommandLineOption> commandLineOptions( MavenSession session, PluginConsoleLogger log )
     {
         List<CommandLineOption> cli = new ArrayList<CommandLineOption>();
         if ( log.isErrorEnabled() )
@@ -146,7 +147,7 @@ public final class SurefireHelper
         return unmodifiableList( cli );
     }
 
-    public static void logDebugOrCliShowErrors( CharSequence s, Log log, Collection<CommandLineOption> cli )
+    public static void logDebugOrCliShowErrors( String s, PluginConsoleLogger log, Collection<CommandLineOption> cli )
     {
         if ( cli.contains( LOGGING_LEVEL_DEBUG ) )
         {

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
index 2a70927..4f9c813 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
@@ -19,7 +19,6 @@ package org.apache.maven.plugin.surefire.booterclient;
  * under the License.
  */
 
-import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.plugin.surefire.CommonReflector;
 import org.apache.maven.plugin.surefire.StartupReportConfiguration;
 import org.apache.maven.plugin.surefire.SurefireProperties;
@@ -29,6 +28,7 @@ import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.OutputStre
 import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestLessInputStream;
 import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestProvidingInputStream;
 import org.apache.maven.plugin.surefire.booterclient.output.ForkClient;
+import org.apache.maven.plugin.surefire.booterclient.output.NativeStdErrStreamConsumer;
 import org.apache.maven.plugin.surefire.booterclient.output.ThreadedStreamConsumer;
 import org.apache.maven.plugin.surefire.report.DefaultReporterFactory;
 import org.apache.maven.shared.utils.cli.CommandLineCallable;
@@ -44,6 +44,7 @@ import org.apache.maven.surefire.booter.StartupConfiguration;
 import org.apache.maven.surefire.booter.SurefireBooterForkException;
 import org.apache.maven.surefire.booter.SurefireExecutionException;
 import org.apache.maven.surefire.providerapi.SurefireProvider;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.surefire.report.StackTraceWriter;
 import org.apache.maven.surefire.suite.RunResult;
 import org.apache.maven.surefire.testset.TestRequest;
@@ -141,7 +142,7 @@ public class ForkStarter
 
     private final StartupReportConfiguration startupReportConfiguration;
 
-    private final Log log;
+    private final ConsoleLogger log;
 
     private final DefaultReporterFactory defaultReporterFactory;
 
@@ -200,7 +201,7 @@ public class ForkStarter
 
     public ForkStarter( ProviderConfiguration providerConfiguration, StartupConfiguration startupConfiguration,
                         ForkConfiguration forkConfiguration, int forkedProcessTimeoutInSeconds,
-                        StartupReportConfiguration startupReportConfiguration, Log log )
+                        StartupReportConfiguration startupReportConfiguration, ConsoleLogger log )
     {
         this.forkConfiguration = forkConfiguration;
         this.providerConfiguration = providerConfiguration;
@@ -208,7 +209,7 @@ public class ForkStarter
         this.startupConfiguration = startupConfiguration;
         this.startupReportConfiguration = startupReportConfiguration;
         this.log = log;
-        defaultReporterFactory = new DefaultReporterFactory( startupReportConfiguration );
+        defaultReporterFactory = new DefaultReporterFactory( startupReportConfiguration, log );
         defaultReporterFactory.runStarting();
         defaultReporterFactories = new ConcurrentLinkedQueue<DefaultReporterFactory>();
         currentForkClients = new ConcurrentLinkedQueue<ForkClient>();
@@ -239,13 +240,13 @@ public class ForkStarter
     private RunResult run( SurefireProperties effectiveSystemProperties, Map<String, String> providerProperties )
             throws SurefireBooterForkException
     {
-        DefaultReporterFactory forkedReporterFactory = new DefaultReporterFactory( startupReportConfiguration );
+        DefaultReporterFactory forkedReporterFactory = new DefaultReporterFactory( startupReportConfiguration, log );
         defaultReporterFactories.add( forkedReporterFactory );
         TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
         PropertiesWrapper props = new PropertiesWrapper( providerProperties );
         TestLessInputStream stream = builder.build();
-        ForkClient forkClient =
-            new ForkClient( forkedReporterFactory, startupReportConfiguration.getTestVmSystemProperties(), stream );
+        Properties sysProps = startupReportConfiguration.getTestVmSystemProperties();
+        ForkClient forkClient = new ForkClient( forkedReporterFactory, sysProps, stream, log );
         Thread shutdown = createImmediateShutdownHookThread( builder, providerConfiguration.getShutdown() );
         ScheduledFuture<?> ping = triggerPingTimerForShutdown( builder );
         try
@@ -318,12 +319,12 @@ public class ForkStarter
                     public RunResult call()
                         throws Exception
                     {
-                        DefaultReporterFactory reporter = new DefaultReporterFactory( startupReportConfiguration );
+                        DefaultReporterFactory reporter = new DefaultReporterFactory( startupReportConfiguration, log );
                         defaultReporterFactories.add( reporter );
 
                         Properties vmProps = startupReportConfiguration.getTestVmSystemProperties();
 
-                        ForkClient forkClient = new ForkClient( reporter, vmProps, testProvidingInputStream )
+                        ForkClient forkClient = new ForkClient( reporter, vmProps, testProvidingInputStream, log )
                         {
                             @Override
                             protected void stopOnNextTest()
@@ -383,11 +384,11 @@ public class ForkStarter
                         throws Exception
                     {
                         DefaultReporterFactory forkedReporterFactory =
-                            new DefaultReporterFactory( startupReportConfiguration );
+                            new DefaultReporterFactory( startupReportConfiguration, log );
                         defaultReporterFactories.add( forkedReporterFactory );
                         Properties vmProps = startupReportConfiguration.getTestVmSystemProperties();
                         ForkClient forkClient = new ForkClient( forkedReporterFactory, vmProps,
-                                                                builder.getImmediateCommands() )
+                                                                      builder.getImmediateCommands(), log )
                         {
                             @Override
                             protected void stopOnNextTest()
@@ -533,11 +534,8 @@ public class ForkStarter
             join( bootClasspathConfiguration, startupConfiguration.getClasspathConfiguration().getTestClasspath() ),
             startupConfiguration.getClasspathConfiguration().getProviderClasspath() );
 
-        if ( log.isDebugEnabled() )
-        {
-            log.debug( bootClasspath.getLogMessage( "boot" ) );
-            log.debug( bootClasspath.getCompactLogMessage( "boot(compact)" ) );
-        }
+        log.debug( bootClasspath.getLogMessage( "boot" ) );
+        log.debug( bootClasspath.getCompactLogMessage( "boot(compact)" ) );
 
         OutputStreamFlushableCommandline cli =
             forkConfiguration.createCommandLine( bootClasspath.getClassPath(), startupConfiguration, forkNumber );
@@ -558,10 +556,7 @@ public class ForkStarter
         final CloseableCloser closer =
                 new CloseableCloser( threadedStreamConsumer, requireNonNull( testProvidingInputStream, "null param" ) );
 
-        if ( forkConfiguration.isDebug() )
-        {
-            System.out.println( "Forking command line: " + cli );
-        }
+        log.debug( "Forking command line: " + cli );
 
         RunResult runResult = null;
 
@@ -569,7 +564,7 @@ public class ForkStarter
         {
             CommandLineCallable future =
                 executeCommandLineAsCallable( cli, testProvidingInputStream, threadedStreamConsumer,
-                                              threadedStreamConsumer, 0, closer,
+                                              new NativeStdErrStreamConsumer(), 0, closer,
                                               Charset.forName( FORK_STREAM_CHARSET_NAME ) );
 
             currentForkClients.add( forkClient );
@@ -630,7 +625,7 @@ public class ForkStarter
             ClassLoader unifiedClassLoader = classpathConfiguration.createMergedClassLoader();
 
             CommonReflector commonReflector = new CommonReflector( unifiedClassLoader );
-            Object reporterFactory = commonReflector.createReportingReporterFactory( startupReportConfiguration );
+            Object reporterFactory = commonReflector.createReportingReporterFactory( startupReportConfiguration, log );
 
             ProviderFactory providerFactory =
                 new ProviderFactory( startupConfiguration, providerConfiguration, unifiedClassLoader, reporterFactory );

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ProviderDetector.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ProviderDetector.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ProviderDetector.java
index 7af0103..3b93eff 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ProviderDetector.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ProviderDetector.java
@@ -19,20 +19,12 @@ package org.apache.maven.plugin.surefire.booterclient;
  * under the License.
  */
 
+import org.apache.maven.surefire.spi.ServiceLoader;
+
 import javax.annotation.Nonnull;
-import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.Enumeration;
-import java.util.HashSet;
 import java.util.Set;
 
-import static java.lang.Character.isJavaIdentifierPart;
-import static java.lang.Character.isJavaIdentifierStart;
-import static java.util.Collections.emptySet;
-
 /**
  * @author Stephen Conolly
  * @author Kristian Rosenvold
@@ -40,93 +32,12 @@ import static java.util.Collections.emptySet;
  */
 public final class ProviderDetector
 {
+    private final ServiceLoader spi = new ServiceLoader();
 
-    @Nonnull public static Set<String> getServiceNames( Class<?> clazz, ClassLoader classLoader )
-        throws IOException
-    {
-        final String resourceName = "META-INF/services/" + clazz.getName();
-
-        if ( classLoader == null )
-        {
-            return emptySet();
-        }
-        final Enumeration<URL> urlEnumeration = classLoader.getResources( resourceName );
-        return getNames( urlEnumeration );
-    }
-
-
-    /**
-     * Method loadServices loads the services of a class that are
-     * defined using the SPI mechanism.
-     *
-     * @param urlEnumeration The urls from the resource
-     * @return The set of service provider names
-     * @throws IOException When reading the streams fails
-     */
     @Nonnull
-    @SuppressWarnings( "checkstyle:innerassignment" )
-    private static Set<String> getNames( final Enumeration<URL> urlEnumeration )
-        throws IOException
-    {
-        final Set<String> names = new HashSet<String>();
-        nextUrl:
-        while ( urlEnumeration.hasMoreElements() )
-        {
-            final URL url = urlEnumeration.nextElement();
-            final BufferedReader reader = getReader( url );
-            try
-            {
-                for ( String line; ( line = reader.readLine() ) != null; )
-                {
-                    int ci = line.indexOf( '#' );
-                    if ( ci >= 0 )
-                    {
-                        line = line.substring( 0, ci );
-                    }
-                    line = line.trim();
-                    int n = line.length();
-                    if ( n == 0 )
-                    {
-                        continue; // next line
-                    }
-
-                    if ( line.indexOf( ' ' ) >= 0 || line.indexOf( '\t' ) >= 0 )
-                    {
-                        continue nextUrl; // next url
-                    }
-                    char cp = line.charAt( 0 ); // should use codePointAt but this was JDK1.3
-                    if ( !isJavaIdentifierStart( cp ) )
-                    {
-                        continue nextUrl; // next url
-                    }
-                    for ( int i = 1; i < n; i++ )
-                    {
-                        cp = line.charAt( i );  // should use codePointAt but this was JDK1.3
-                        if ( !isJavaIdentifierPart( cp ) && cp != '.' )
-                        {
-                            continue nextUrl; // next url
-                        }
-                    }
-                    if ( !names.contains( line ) )
-                    {
-                        names.add( line );
-                    }
-                }
-            }
-            finally
-            {
-                reader.close();
-            }
-        }
-
-        return names;
-    }
-
-    @Nonnull private static BufferedReader getReader( @Nonnull URL url )
-        throws IOException
+    public Set<String> lookupServiceNames( Class<?> clazz, ClassLoader classLoader )
+            throws IOException
     {
-        final InputStream inputStream = url.openStream();
-        final InputStreamReader inputStreamReader = new InputStreamReader( inputStream );
-        return new BufferedReader( inputStreamReader );
+        return spi.lookup( clazz, classLoader );
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
index 767962a..be3b09f 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
@@ -23,27 +23,29 @@ import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.StringReader;
 import java.nio.ByteBuffer;
-import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Properties;
 import java.util.StringTokenizer;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.NotifiableTestStream;
 import org.apache.maven.plugin.surefire.report.DefaultReporterFactory;
 import org.apache.maven.shared.utils.cli.StreamConsumer;
-import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.surefire.report.ConsoleOutputReceiver;
 import org.apache.maven.surefire.report.ReportEntry;
 import org.apache.maven.surefire.report.ReporterException;
 import org.apache.maven.surefire.report.RunListener;
 import org.apache.maven.surefire.report.StackTraceWriter;
 
+import static java.lang.Integer.decode;
 import static java.lang.Integer.parseInt;
 import static java.lang.System.currentTimeMillis;
 import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_BYE;
 import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_CONSOLE;
+import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_DEBUG;
 import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_ERROR;
 import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_NEXT_TEST;
 import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_STDERR;
@@ -58,6 +60,7 @@ import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_TES
 import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_TEST_SUCCEEDED;
 import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_TESTSET_COMPLETED;
 import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_TESTSET_STARTING;
+import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_WARNING;
 import static org.apache.maven.surefire.booter.Shutdown.KILL;
 import static org.apache.maven.surefire.report.CategorizedReportEntry.reportEntry;
 import static org.apache.maven.surefire.util.internal.StringUtils.isNotBlank;
@@ -75,30 +78,34 @@ public class ForkClient
     private static final long START_TIME_ZERO = 0L;
     private static final long START_TIME_NEGATIVE_TIMEOUT = -1L;
 
-    private final DefaultReporterFactory defaultReporterFactory;
-
-    private final NotifiableTestStream notifiableTestStream;
+    private final ConcurrentMap<Integer, RunListener> testSetReporters;
 
-    private final Map<Integer, RunListener> testSetReporters = new ConcurrentHashMap<Integer, RunListener>();
+    private final DefaultReporterFactory defaultReporterFactory;
 
     private final Properties testVmSystemProperties;
 
+    private final NotifiableTestStream notifiableTestStream;
+
     /**
      * <t>testSetStartedAt</t> is set to non-zero after received
      * {@link org.apache.maven.surefire.booter.ForkingRunListener#BOOTERCODE_TESTSET_STARTING test-set}.
      */
     private final AtomicLong testSetStartedAt = new AtomicLong( START_TIME_ZERO );
 
+    private final ConsoleLogger log;
+
     private volatile boolean saidGoodBye;
 
     private volatile StackTraceWriter errorInFork;
 
     public ForkClient( DefaultReporterFactory defaultReporterFactory, Properties testVmSystemProperties,
-                       NotifiableTestStream notifiableTestStream )
+                       NotifiableTestStream notifiableTestStream, ConsoleLogger log )
     {
+        testSetReporters = new ConcurrentHashMap<Integer, RunListener>();
         this.defaultReporterFactory = defaultReporterFactory;
         this.testVmSystemProperties = testVmSystemProperties;
         this.notifiableTestStream = notifiableTestStream;
+        this.log = log;
     }
 
     protected void stopOnNextTest()
@@ -158,7 +165,7 @@ public class ForkClient
             int comma = s.indexOf( ",", 3 );
             if ( comma < 0 )
             {
-                System.out.println( s );
+                log.warning( s );
                 return;
             }
             final int channelNumber = parseInt( s.substring( 2, comma ), 16 );
@@ -168,29 +175,37 @@ public class ForkClient
             switch ( operationId )
             {
                 case BOOTERCODE_TESTSET_STARTING:
-                    getOrCreateReporter( channelNumber ).testSetStarting( createReportEntry( remaining ) );
+                    getOrCreateReporter( channelNumber )
+                            .testSetStarting( createReportEntry( remaining ) );
                     setCurrentStartTime();
                     break;
                 case BOOTERCODE_TESTSET_COMPLETED:
-                    getOrCreateReporter( channelNumber ).testSetCompleted( createReportEntry( remaining ) );
+                    getOrCreateReporter( channelNumber )
+                            .testSetCompleted( createReportEntry( remaining ) );
                     break;
                 case BOOTERCODE_TEST_STARTING:
-                    getOrCreateReporter( channelNumber ).testStarting( createReportEntry( remaining ) );
+                    getOrCreateReporter( channelNumber )
+                            .testStarting( createReportEntry( remaining ) );
                     break;
                 case BOOTERCODE_TEST_SUCCEEDED:
-                    getOrCreateReporter( channelNumber ).testSucceeded( createReportEntry( remaining ) );
+                    getOrCreateReporter( channelNumber )
+                            .testSucceeded( createReportEntry( remaining ) );
                     break;
                 case BOOTERCODE_TEST_FAILED:
-                    getOrCreateReporter( channelNumber ).testFailed( createReportEntry( remaining ) );
+                    getOrCreateReporter( channelNumber )
+                            .testFailed( createReportEntry( remaining ) );
                     break;
                 case BOOTERCODE_TEST_SKIPPED:
-                    getOrCreateReporter( channelNumber ).testSkipped( createReportEntry( remaining ) );
+                    getOrCreateReporter( channelNumber )
+                            .testSkipped( createReportEntry( remaining ) );
                     break;
                 case BOOTERCODE_TEST_ERROR:
-                    getOrCreateReporter( channelNumber ).testError( createReportEntry( remaining ) );
+                    getOrCreateReporter( channelNumber )
+                            .testError( createReportEntry( remaining ) );
                     break;
                 case BOOTERCODE_TEST_ASSUMPTIONFAILURE:
-                    getOrCreateReporter( channelNumber ).testAssumptionFailure( createReportEntry( remaining ) );
+                    getOrCreateReporter( channelNumber )
+                            .testAssumptionFailure( createReportEntry( remaining ) );
                     break;
                 case BOOTERCODE_SYSPROPS:
                     int keyEnd = remaining.indexOf( "," );
@@ -198,7 +213,6 @@ public class ForkClient
                     StringBuilder value = new StringBuilder();
                     unescapeString( key, remaining.substring( 0, keyEnd ) );
                     unescapeString( value, remaining.substring( keyEnd + 1 ) );
-
                     synchronized ( testVmSystemProperties )
                     {
                         testVmSystemProperties.put( key.toString(), value.toString() );
@@ -211,7 +225,8 @@ public class ForkClient
                     writeTestOutput( channelNumber, remaining, false );
                     break;
                 case BOOTERCODE_CONSOLE:
-                    getOrCreateConsoleLogger( channelNumber ).info( createConsoleMessage( remaining ) );
+                    getOrCreateConsoleLogger( channelNumber )
+                            .info( createConsoleMessage( remaining ) );
                     break;
                 case BOOTERCODE_NEXT_TEST:
                     notifiableTestStream.provideNewTest();
@@ -225,19 +240,27 @@ public class ForkClient
                 case BOOTERCODE_STOP_ON_NEXT_TEST:
                     stopOnNextTest();
                     break;
+                case BOOTERCODE_DEBUG:
+                    getOrCreateConsoleLogger( channelNumber )
+                            .debug( createConsoleMessage( remaining ) );
+                    break;
+                case BOOTERCODE_WARNING:
+                    getOrCreateConsoleLogger( channelNumber )
+                            .warning( createConsoleMessage( remaining ) );
+                    break;
                 default:
-                    System.out.println( s );
+                    log.warning( s );
             }
         }
         catch ( NumberFormatException e )
         {
             // SUREFIRE-859
-            System.out.println( s );
+            log.warning( s );
         }
         catch ( NoSuchElementException e )
         {
             // SUREFIRE-859
-            System.out.println( s );
+            log.warning( s );
         }
         catch ( ReporterException e )
         {
@@ -245,7 +268,7 @@ public class ForkClient
         }
     }
 
-    private void writeTestOutput( final int channelNumber, final String remaining, boolean isStdout )
+    private void writeTestOutput( final int channelNumber, final String remaining, final boolean isStdout )
     {
         int csNameEnd = remaining.indexOf( ',' );
         String charsetName = remaining.substring( 0, csNameEnd );
@@ -255,7 +278,6 @@ public class ForkClient
         if ( unescaped.hasArray() )
         {
             byte[] convertedBytes = unescaped.array();
-
             getOrCreateConsoleOutputReceiver( channelNumber )
                 .writeTestOutput( convertedBytes, unescaped.position(), unescaped.remaining(), isStdout );
         }
@@ -263,7 +285,6 @@ public class ForkClient
         {
             byte[] convertedBytes = new byte[unescaped.remaining()];
             unescaped.get( convertedBytes, 0, unescaped.remaining() );
-
             getOrCreateConsoleOutputReceiver( channelNumber )
                 .writeTestOutput( convertedBytes, 0, convertedBytes.length, isStdout );
         }
@@ -294,7 +315,7 @@ public class ForkClient
             String group = nullableCsv( tokens.nextToken() );
             String message = nullableCsv( tokens.nextToken() );
             String elapsedStr = tokens.nextToken();
-            Integer elapsed = "null".equals( elapsedStr ) ? null : Integer.decode( elapsedStr );
+            Integer elapsed = "null".equals( elapsedStr ) ? null : decode( elapsedStr );
             final StackTraceWriter stackTraceWriter =
                 tokens.hasMoreTokens() ? deserializeStackTraceWriter( tokens ) : null;
 
@@ -344,7 +365,11 @@ public class ForkClient
         if ( reporter == null )
         {
             reporter = defaultReporterFactory.createReporter();
-            testSetReporters.put( channelNumber, reporter );
+            RunListener old = testSetReporters.putIfAbsent( channelNumber, reporter );
+            if ( old != null )
+            {
+                reporter = old;
+            }
         }
         return reporter;
     }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/6a79127a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/NativeStdErrStreamConsumer.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/NativeStdErrStreamConsumer.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/NativeStdErrStreamConsumer.java
new file mode 100644
index 0000000..84ca474
--- /dev/null
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/NativeStdErrStreamConsumer.java
@@ -0,0 +1,38 @@
+package org.apache.maven.plugin.surefire.booterclient.output;
+
+/*
+ * 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.apache.maven.shared.utils.cli.StreamConsumer;
+
+/**
+ * Used by forked JMV, see {@link org.apache.maven.plugin.surefire.booterclient.ForkStarter}.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19.2
+ * @see org.apache.maven.plugin.surefire.booterclient.ForkStarter
+ */
+public final class NativeStdErrStreamConsumer
+    implements StreamConsumer
+{
+    public void consumeLine( String line )
+    {
+        System.err.println( line );
+    }
+}