package org.apache.maven.surefire;

/*
 * Copyright 2001-2005 The Codehaus.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      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.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.cli.CommandLineException;
import org.codehaus.plexus.util.cli.CommandLineUtils;
import org.codehaus.plexus.util.cli.Commandline;
import org.codehaus.plexus.util.cli.StreamConsumer;
import org.codehaus.plexus.util.cli.WriterStreamConsumer;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

/**
 * @author Jason van Zyl
 * @author Emmanuel Venisse
 * @version $Id$
 */
public class SurefireBooter
{
    protected static final String EOL = System.getProperty( "line.separator" );

    protected static final String PS = System.getProperty( "path.separator" );

    private static String RUNNER = "org.apache.maven.surefire.SurefireBooter";

    private static String BATTERY_EXECUTOR = "org.apache.maven.surefire.Surefire";

    private static String SINGLE_TEST_BATTERY = "org.apache.maven.surefire.battery.JUnitBattery";

    private List batteries = new ArrayList();

    private List reports = new ArrayList();

    private List classpathUrls = new ArrayList();

    private String reportsDirectory;

    private String forkMode;

    private String basedir;

    private String jvm;

    private Properties systemProperties;

    private String argLine;

    private boolean childDelegation;

    private boolean debug;

    private String surefireBooterJar;

    private String plexusUtilsJar;

    // ----------------------------------------------------------------------
    //
    // ----------------------------------------------------------------------

    public static final String FORK_ONCE = "once";

    public static final String FORK_PERTEST = "pertest";

    public static final String FORK_NONE = "none";

    public static final String SUREFIRE_PROPERTIES = "surefire.properties";

    public static final String SYSTEM_PROPERTIES = "surefire-system.properties";

    public static final String CLASSLOADER_PROPERTIES = "surefire-classloader.properties";

    static int TESTS_SUCCEEDED = 0;

    static int TESTS_FAILED = 255;

    static int ILLEGAL_ARGUMENT_EXCEPTION = 100;

    static int OTHER_EXCEPTION = 200;

    // ----------------------------------------------------------------------
    // Accessors
    // ----------------------------------------------------------------------

    public void setReportsDirectory( String reportsDirectory )
    {
        this.reportsDirectory = reportsDirectory;
    }

    public String getReportsDirectory()
    {
        return this.reportsDirectory;
    }

    public void addBattery( String battery, Object[] params )
    {
        batteries.add( new Object[]{battery, params} );
    }

    public void addBattery( String battery )
    {
        batteries.add( new Object[]{battery, null} );
    }

    public void addReport( String report )
    {
        reports.add( report );
    }

    public void addClassPathUrl( String path )
    {
        if ( !classpathUrls.contains( path ) )
        {
            classpathUrls.add( path );
        }
    }

    public void setClassPathUrls( List classpathUrls )
    {
        this.classpathUrls = classpathUrls;
    }

    // ----------------------------------------------------------------------
    // Forking options
    // ----------------------------------------------------------------------

    public void setForkMode( String forkMode )
    {
        this.forkMode = forkMode;
    }

    public void setJvm( String jvm )
    {
        this.jvm = jvm;
    }

    public void setSystemProperties( Properties systemProperties )
    {
        this.systemProperties = systemProperties;
    }

    public void setArgLine( String argLine )
    {
        this.argLine = argLine;
    }

    public void setBasedir( String basedir )
    {
        this.basedir = basedir;
    }

    public void setChildDelegation( boolean childDelegation )
    {
        this.childDelegation = childDelegation;
    }

    public void setDebug( boolean debug )
    {
        this.debug = debug;
    }

    // ----------------------------------------------------------------------
    //
    // ----------------------------------------------------------------------

    public boolean run()
        throws Exception
    {
        boolean result = false;

        if ( forkMode.equals( FORK_NONE ) )
        {
            result = runTestsInProcess();
        }
        else if ( forkMode.equals( FORK_ONCE ) )
        {
            result = runTestsForkOnce();
        }
        else if ( forkMode.equals( FORK_PERTEST ) )
        {
            result = runTestsForkEach();
        }

        return result;
    }

    private ClassLoader createClassLoader() throws Exception
    {
        return createClassLoader( classpathUrls, childDelegation );
    }

    static private ClassLoader createClassLoader( List classpathUrls, boolean childDelegation ) throws Exception
    {
        ArrayList urls = new ArrayList();

        for ( Iterator i = classpathUrls.iterator(); i.hasNext(); )
        {
            String url = (String) i.next();

            if ( url == null )
            {
                continue;
            }

            File f = new File( url );
            urls.add( f.toURL() );
        }

        if ( childDelegation )
        {
            IsolatedClassLoader surefireClassLoader = new IsolatedClassLoader( ClassLoader.getSystemClassLoader(), true );
            for ( Iterator iter = urls.iterator(); iter.hasNext(); )
            {
                URL url = (URL) iter.next();
                surefireClassLoader.addURL( url );
            }
            return surefireClassLoader;
        }
        else
        {
            URL u[] = new URL[urls.size()];
            urls.toArray( u );
            return new URLClassLoader( u, ClassLoader.getSystemClassLoader() );
        }
    }

    private static ClassLoader createForkingClassLoader( String basedir )
        throws Exception
    {
        Properties p = loadProperties( basedir, CLASSLOADER_PROPERTIES );

        String cp = p.getProperty( "classpath" );

        boolean childDelegation = "true".equals( p.getProperty( "childDelegation", "false" ) );

        List urls = Arrays.asList( cp.split( ":" ) );

        return createClassLoader( urls, childDelegation );
    }


    private boolean runTestsInProcess()
        throws Exception
    {
        ClassLoader surefireClassLoader = createClassLoader();

        Class batteryExecutorClass = surefireClassLoader.loadClass( BATTERY_EXECUTOR );

        Object batteryExecutor = batteryExecutorClass.newInstance();

        Method run = batteryExecutorClass.getMethod( "run", new Class[]{List.class, List.class, ClassLoader.class, String.class} );

        ClassLoader oldContextClassLoader = Thread.currentThread() .getContextClassLoader();

        Thread.currentThread().setContextClassLoader( surefireClassLoader );

        Boolean result = (Boolean) run.invoke( batteryExecutor, new Object[]{reports, batteries, surefireClassLoader, reportsDirectory} );

        Thread.currentThread().setContextClassLoader( oldContextClassLoader );

        return result.booleanValue();
    }

    private boolean runTestsForkOnce()
        throws Exception
    {
        getForkOnceArgs();

        return fork();
    }

    private boolean runTestsForkEach()
        throws Exception
    {
        boolean noFailures = true;

        List testClasses = getTestClasses();

        for ( Iterator i = testClasses.iterator(); i.hasNext(); )
        {
            String testClass = (String) i.next();

            getForkPerTestArgs( testClass );

            boolean result = fork();

            if ( !result )
            {
                noFailures = false;
            }
        }

        return noFailures;
    }

    private boolean fork()
        throws Exception
    {
        Commandline cli = new Commandline();

        cli.setWorkingDirectory( basedir );

        cli.setExecutable( jvm );

        if ( argLine != null )
        {
            cli.addArguments( StringUtils.split( argLine, " " ) );
        }

        cli.createArgument().setValue( "-classpath" );

        cli.createArgument().setValue( surefireBooterJar + PS + plexusUtilsJar );

        cli.createArgument().setValue( RUNNER );

        cli.createArgument().setValue( basedir );

        if ( debug )
        {
            System.out.println( Commandline.toString( cli.getCommandline() ) );
        }

        Writer stringWriter = new StringWriter();

        StreamConsumer out = new WriterStreamConsumer( stringWriter );

        StreamConsumer err = new WriterStreamConsumer( stringWriter );

        int returnCode;

        try
        {
            returnCode = CommandLineUtils.executeCommandLine( cli, out, err );
        }
        catch ( CommandLineException e )
        {
            throw new Exception( "Error while executing forked tests.", e );
        }
        catch ( Exception e )
        {
            throw new SurefireBooterForkException( "Error while executing forked tests.", e );
        }

        /*

        The standard reporting modules should do this work ... jvz
        
        String string = stringWriter.toString();

        if ( string != null && string.length() > 0 )
        {
            StringReader sr = new StringReader( string );

            BufferedReader br = new BufferedReader( sr );

            while ( ( string = br.readLine() ) != null )
            {
                System.out.println( string );
            }
        }
        */

        if ( returnCode != 0 )
        {
            return false;
        }

        return true;
    }

    private List getTestClasses()
        throws Exception
    {
        ClassLoader classLoader = createClassLoader();

        List instantiatedBatteries = Surefire.instantiateBatteries( batteries, classLoader );

        List testClasses = new ArrayList();

        for ( Iterator i = instantiatedBatteries.iterator(); i.hasNext(); )
        {
            Object o = i.next();

            Method m = o.getClass().getMethod( "getSubBatteryClassNames", new Class[]{} );

            List tests = (List) m.invoke( o, new Object[]{} );

            // This class comes from a different classloader then the isolated classloader.
            // This is the battery class that is from a different loader.

            testClasses.addAll( tests );
        }

        return testClasses;
    }

    private void getForkOnceArgs()
        throws Exception
    {
        getForkArgs( getStringArrayFromBatteries()[0] );
    }

    private void getForkPerTestArgs( String testClass )
        throws Exception
    {
        getForkArgs( SINGLE_TEST_BATTERY + "|" + testClass );
    }


    private void getForkArgs( String batteryConfig )
        throws Exception
    {
        String reportClassNames = getListOfStringsAsString( reports, "," );

        Properties p = new Properties();

        String cp = "";
        for ( int i = 0; i < classpathUrls.size(); i++ )
        {
            String url = (String) classpathUrls.get( i );

            // Exclude the surefire booter
            // Exclude the surefire booter
            if ( url.indexOf( "surefire-booter" ) > 0 )
            {
                surefireBooterJar = url;
            }
            else if ( url.indexOf( "plexus-utils" ) > 0 )
            {
                plexusUtilsJar = url;
            }
            else
            {
                if ( cp.length() == 0 )
                    cp = url;
                else
                    cp += ":" + url;
            }
        }
        p.setProperty( "classpath", cp );
        p.setProperty( "childDelegation", "" + childDelegation );

        FileOutputStream fos = new FileOutputStream( new File( basedir, CLASSLOADER_PROPERTIES ) );

        p.store( fos, "classpath entries" );

        fos.close();

        if ( systemProperties != null )
        {
            File f = new File( basedir, SYSTEM_PROPERTIES );

            fos = new FileOutputStream( f );

            systemProperties.store( fos, "system properties" );

            fos.close();
        }

        p = new Properties();

        p.setProperty( "reportClassNames", reportClassNames );

        p.setProperty( "reportsDirectory", reportsDirectory );

        p.setProperty( "batteryExecutorName", BATTERY_EXECUTOR );

        p.setProperty( "forkMode", forkMode );

        p.setProperty( "batteryConfig", batteryConfig );

        p.setProperty( "debug", "" + debug );

        fos = new FileOutputStream( new File( basedir, SUREFIRE_PROPERTIES ) );

        p.store( fos, "surefire properties" );

        fos.close();

    }

    public void reset()
    {
        batteries.clear();

        reports.clear();

        classpathUrls.clear();
    }

    private String getListOfStringsAsString( List listOfStrings, String delimiterParm )
    {
        StringBuffer stringBuffer = new StringBuffer();

        Iterator listOfStringsIterator = listOfStrings.iterator();

        String delimiter = "";

        while ( listOfStringsIterator.hasNext() )
        {
            String string = (String) listOfStringsIterator.next();

            stringBuffer.append( delimiter );

            stringBuffer.append( string );

            delimiter = delimiterParm;
        }

        return new String( stringBuffer );
    }

    private String[] getStringArrayFromBatteries()
    {
        String[] batteryConfig = new String[batteries.size()];

        StringBuffer batteryBuffer = new StringBuffer();

        int batteryCounter = 0;

        for ( Iterator j = batteries.iterator(); j.hasNext(); )
        {
            Object[] batteryArray = (Object[]) j.next();

            batteryBuffer.append( (String) batteryArray[0] );

            if ( batteryArray[1] != null )
            {
                Object[] batteryParms = (Object[]) batteryArray[1];

                for ( int i = 0; i < 3; i++ )
                {
                    batteryBuffer.append( "|" );

                    batteryBuffer.append( batteryParms[i] );
                }
            }

            batteryConfig[batteryCounter++] = new String( batteryBuffer );
        }

        return batteryConfig;
    }

    // ----------------------------------------------------------------------
    //
    // ----------------------------------------------------------------------

    private static Properties loadProperties( String basedir, String file )
        throws Exception
    {
        File f = new File( basedir, file );

        Properties p = new Properties();

        if ( !f.exists() )
        {
            return p;
        }

        f.deleteOnExit();

        p.load( new FileInputStream( f ) );

        return p;
    }

    private static Properties getSurefireProperties( String basedir )
        throws Exception
    {
        return loadProperties( basedir, SUREFIRE_PROPERTIES );
    }

    private static void setSystemProperties( String basedir )
        throws Exception
    {
        Properties p = loadProperties( basedir, SYSTEM_PROPERTIES );

        for ( Iterator i = p.keySet().iterator(); i.hasNext(); )
        {
            String key = (String) i.next();

            System.setProperty( key, p.getProperty( key ) );
        }
    }

    /**
     * This method is invoked when Surefire is forked - this method parses and
     * organizes the arguments passed to it and then calls the Surefire class'
     * run method.
     *
     * @param args
     * @throws Exception
     */
    public static void main( String[] args )
        throws Exception
    {
        String basedir = args[0];

        ClassLoader classLoader = createForkingClassLoader( basedir );


        Thread.currentThread().setContextClassLoader( classLoader );

        setSystemProperties( basedir );

        Properties p = getSurefireProperties( basedir );

        boolean debug = "true".equals( p.getProperty( "debug", "false" ) );
        if ( debug )
        {
            logClassLoader( classLoader );
        }

        String batteryExecutorName = p.getProperty( "batteryExecutorName" );

        Class batteryExecutorClass = classLoader.loadClass( batteryExecutorName );

        Object batteryExecutor = batteryExecutorClass.newInstance();

        String reports = p.getProperty( "reportClassNames" );

        String[] reportClasses = reports.split( "," );

        List reportList = Arrays.asList( reportClasses );

        String batteryConfig = p.getProperty( "batteryConfig" );

        String[] batteryParts = batteryConfig.split( "\\|" );

        String batteryClassName = batteryParts[0];

        Object[] batteryParms;

        String forkMode = p.getProperty( "forkMode" );

        if ( forkMode.equals( FORK_ONCE ) )
        {
            batteryParms = new Object[batteryParts.length - 1];

            batteryParms[0] = new File( batteryParts[1] );

            String stringList = batteryParts[2];

            if ( stringList.startsWith( "[" ) && stringList.endsWith( "]" ) )
            {
                stringList = stringList.substring( 1, stringList.length() - 1 );
            }

            ArrayList includesList = new ArrayList();

            String[] stringArray = stringList.split( "," );

            for ( int i = 0; i < stringArray.length; i++ )
            {
                includesList.add( stringArray[i].trim() );
            }

            batteryParms[1] = includesList;

            stringList = batteryParts[3];

            ArrayList excludesList = new ArrayList();

            if ( stringList.startsWith( "[" ) && stringList.endsWith( "]" ) )
            {
                stringList = stringList.substring( 1, stringList.length() - 1 );
            }

            stringArray = stringList.split( "," );

            for ( int i = 0; i < stringArray.length; i++ )
            {
                excludesList.add( stringArray[i].trim() );
            }

            batteryParms[2] = excludesList;
        }
        else
        {
            batteryParms = new Object[1];

            batteryParms[0] = batteryParts[1];
        }

        List batteryHolders = new ArrayList();

        batteryHolders.add( new Object[]{batteryClassName, batteryParms} );

        String reportsDirectory = p.getProperty( "reportsDirectory" );

        Method run = batteryExecutorClass.getMethod( "run", new Class[]{List.class, List.class, String.class} );

        Object[] parms = new Object[]{reportList, batteryHolders, reportsDirectory};

        int returnCode = TESTS_FAILED;

        try
        {
            boolean result = ( (Boolean) run.invoke( batteryExecutor, parms ) ).booleanValue();

            if ( result )
            {
                returnCode = TESTS_SUCCEEDED;
            }

        }
        catch ( IllegalArgumentException e )
        {
            returnCode = ILLEGAL_ARGUMENT_EXCEPTION;
        }
        catch ( Exception e )
        {
            e.printStackTrace();

            returnCode = OTHER_EXCEPTION;
        }

        System.exit( returnCode );
    }


    private static void logClassLoader( ClassLoader classLoader )
    {
        if ( classLoader.getParent() != null )
        {
            logClassLoader( classLoader.getParent() );
        }

        if ( classLoader instanceof URLClassLoader )
        {
            System.out.println( "ClassLoader: type" + classLoader.getClass() + ", value=" + classLoader );

            URLClassLoader ucl = (URLClassLoader) classLoader;

            URL[] u = ucl.getURLs();

            for ( int i = 0; i < u.length; i++ )
            {
                System.out.println( "           : " + u[i] );
            }
        }
        else
        {
            System.out.println( "ClassLoader: type" + classLoader.getClass() + ", value=" + classLoader );
        }
    }
}

