package org.apache.maven.plugin.ant;

/*
 * 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.artifact.Artifact;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Profile;
import org.apache.maven.model.Repository;
import org.apache.maven.model.Resource;
import org.apache.maven.project.MavenProject;
import org.apache.maven.settings.Settings;
import org.apache.tools.ant.Main;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
import org.codehaus.plexus.util.xml.XMLWriter;
import org.codehaus.plexus.util.xml.XmlWriterUtil;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * Write Ant build files from <code>Maven Project</code> for <a href="http://ant.apache.org">Ant</a> 1.6.2 or above:
 * <ul>
 * <li>build.xml</li>
 * <li>maven-build.xml</li>
 * <li>maven-build.properties</li>
 * </ul>
 *
 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
 * @version $Id$
 */
public class AntBuildWriter
{
    /**
     * The default line indenter
     */
    protected static final int DEFAULT_INDENTATION_SIZE = XmlWriterUtil.DEFAULT_INDENTATION_SIZE;

    /**
     * The default build file name (build.xml)
     */
    protected static final String DEFAULT_BUILD_FILENAME = Main.DEFAULT_BUILD_FILENAME;

    /**
     * The default generated build file name
     */
    protected static final String DEFAULT_MAVEN_BUILD_FILENAME = "maven-build.xml";

    /**
     * The default build properties file name
     */
    protected static final String DEFAULT_MAVEN_PROPERTIES_FILENAME = "maven-build.properties";

    private final MavenProject project;

    private final ArtifactResolverWrapper artifactResolverWrapper;

    private final File localRepository;

    private final Settings settings;

    private final boolean overwrite;

    private final Properties executionProperties;

    /**
     * @param project {@link MavenProject}
     * @param artifactResolverWrapper {@link ArtifactResolverWrapper}
     * @param settings {@link Settings}
     * @param overwrite true/false to overwrite or not.
     * @param executionProperties {@link Properties}
     */
    public AntBuildWriter( MavenProject project, ArtifactResolverWrapper artifactResolverWrapper, Settings settings,
                           boolean overwrite, Properties executionProperties )
    {
        this.project = project;
        this.artifactResolverWrapper = artifactResolverWrapper;
        this.localRepository = new File( artifactResolverWrapper.getLocalRepository().getBasedir() );
        this.settings = settings;
        this.overwrite = overwrite;
        this.executionProperties = ( executionProperties != null ) ? executionProperties : new Properties();
    }

    /**
     * Generate Ant build XML files
     *
     * @throws IOException In case of an error.
     */
    protected void writeBuildXmls()
        throws IOException
    {
        writeGeneratedBuildXml();
        writeBuildXml();
    }

    /**
     * Generate <code>maven-build.properties</code> only for a non-POM project
     *
     * @throws IOException In case of an failure {@link IOException}
     * @see #DEFAULT_MAVEN_PROPERTIES_FILENAME
     */
    protected void writeBuildProperties()
        throws IOException
    {
        if ( AntBuildWriterUtil.isPomPackaging( project ) )
        {
            return;
        }

        Properties properties = new Properties();

        // ----------------------------------------------------------------------
        // Build properties
        // ----------------------------------------------------------------------

        addProperty( properties, "maven.build.finalName",
                     AntBuildWriterUtil.toRelative( project.getBasedir(), project.getBuild().getFinalName() ) );

        // target
        addProperty( properties, "maven.build.dir",
                     AntBuildWriterUtil.toRelative( project.getBasedir(), project.getBuild().getDirectory() ) );
        addProperty( properties, "project.build.directory", "${maven.build.dir}" );

        // ${maven.build.dir}/classes
        addProperty( properties,
                     "maven.build.outputDir",
                     "${maven.build.dir}/"
                         + AntBuildWriterUtil.toRelative( new File( project.getBasedir(),
                                                                    properties.getProperty( "maven.build.dir" ) ),
                                                          project.getBuild().getOutputDirectory() ) );
        addProperty( properties, "project.build.outputDirectory", "${maven.build.outputDir}" );

        // src/main/java
        if ( !project.getCompileSourceRoots().isEmpty() )
        {
            List var = project.getCompileSourceRoots();
            String[] compileSourceRoots = (String[]) var.toArray( new String[var.size()] );
            for ( int i = 0; i < compileSourceRoots.length; i++ )
            {
                addProperty( properties, "maven.build.srcDir." + i,
                             AntBuildWriterUtil.toRelative( project.getBasedir(), compileSourceRoots[i] ) );
            }
        }
        // src/main/resources
        if ( project.getBuild().getResources() != null )
        {
            List<Resource> var = project.getBuild().getResources();
            Resource[] array = var.toArray( new Resource[var.size()] );
            for ( int i = 0; i < array.length; i++ )
            {
                addProperty( properties, "maven.build.resourceDir." + i,
                             AntBuildWriterUtil.toRelative( project.getBasedir(), array[i].getDirectory() ) );
            }
        }

        // ${maven.build.dir}/test-classes
        addProperty( properties,
                     "maven.build.testOutputDir",
                     "${maven.build.dir}/"
                         + AntBuildWriterUtil.toRelative( new File( project.getBasedir(),
                                                                    properties.getProperty( "maven.build.dir" ) ),
                                                          project.getBuild().getTestOutputDirectory() ) );
        // src/test/java
        if ( !project.getTestCompileSourceRoots().isEmpty() )
        {
            List var = project.getTestCompileSourceRoots();
            String[] compileSourceRoots = (String[]) var.toArray( new String[var.size()] );
            for ( int i = 0; i < compileSourceRoots.length; i++ )
            {
                addProperty( properties, "maven.build.testDir." + i,
                             AntBuildWriterUtil.toRelative( project.getBasedir(), compileSourceRoots[i] ) );
            }
        }
        // src/test/resources
        if ( project.getBuild().getTestResources() != null )
        {
            List<Resource> var = project.getBuild().getTestResources();
            Resource[] array = var.toArray( new Resource[var.size()] );
            for ( int i = 0; i < array.length; i++ )
            {
                addProperty( properties, "maven.build.testResourceDir." + i,
                             AntBuildWriterUtil.toRelative( project.getBasedir(), array[i].getDirectory() ) );
            }
        }

        addProperty( properties, "maven.test.reports", "${maven.build.dir}/test-reports" );

        addProperty( properties, "maven.reporting.outputDirectory", "${maven.build.dir}/site" );

        // ----------------------------------------------------------------------
        // Settings properties
        // ----------------------------------------------------------------------

        addProperty( properties, "maven.settings.offline", String.valueOf( settings.isOffline() ) );
        addProperty( properties, "maven.settings.interactiveMode", String.valueOf( settings.isInteractiveMode() ) );
        addProperty( properties, "maven.repo.local", getLocalRepositoryPath() );

        // ----------------------------------------------------------------------
        // Project properties
        // ----------------------------------------------------------------------

        if ( project.getProperties() != null )
        {
            for ( Map.Entry<Object, Object> objectObjectEntry : project.getProperties().entrySet() )
            {
                Map.Entry property = (Map.Entry) objectObjectEntry;
                addProperty( properties, property.getKey().toString(), property.getValue().toString() );
            }
        }

        FileOutputStream os =
            new FileOutputStream( new File( project.getBasedir(), DEFAULT_MAVEN_PROPERTIES_FILENAME ) );
        try
        {
            properties.store( os, "Generated by Maven Ant Plugin - DO NOT EDIT THIS FILE!" );
            os.close();
            os = null;
        }
        finally
        {
            IOUtil.close( os );
        }
    }

    /**
     * Generate an <code>maven-build.xml</code>
     *
     * @throws IOException
     * @see #DEFAULT_MAVEN_BUILD_FILENAME
     */
    private void writeGeneratedBuildXml()
        throws IOException
    {
        // TODO: parameter
        File outputFile = new File( project.getBasedir(), DEFAULT_MAVEN_BUILD_FILENAME );

        String encoding = "UTF-8";

        OutputStreamWriter w = new OutputStreamWriter( new FileOutputStream( outputFile ), encoding );

        XMLWriter writer =
            new PrettyPrintXMLWriter( w, StringUtils.repeat( " ", DEFAULT_INDENTATION_SIZE ), encoding, null );

        // ----------------------------------------------------------------------
        // <!-- comments -->
        // ----------------------------------------------------------------------

        AntBuildWriterUtil.writeHeader( writer );

        // ----------------------------------------------------------------------
        // <project/>
        // ----------------------------------------------------------------------

        writer.startElement( "project" );
        writer.addAttribute( "name", project.getArtifactId() + "-from-maven" );
        writer.addAttribute( "default", "package" );
        writer.addAttribute( "basedir", "." );

        XmlWriterUtil.writeLineBreak( writer );

        // ----------------------------------------------------------------------
        // <property/>
        // ----------------------------------------------------------------------

        writeProperties( writer );

        // ----------------------------------------------------------------------
        // <path/>
        // ----------------------------------------------------------------------

        writeBuildPathDefinition( writer );

        // ----------------------------------------------------------------------
        // <target name="clean" />
        // ----------------------------------------------------------------------

        writeCleanTarget( writer );

        // ----------------------------------------------------------------------
        // <target name="compile" />
        // ----------------------------------------------------------------------

        List compileSourceRoots = AntBuildWriterUtil.removeEmptyCompileSourceRoots( project.getCompileSourceRoots() );
        writeCompileTarget( writer, compileSourceRoots );

        // ----------------------------------------------------------------------
        // <target name="compile-tests" />
        // ----------------------------------------------------------------------

        List testCompileSourceRoots =
            AntBuildWriterUtil.removeEmptyCompileSourceRoots( project.getTestCompileSourceRoots() );
        writeCompileTestsTarget( writer, testCompileSourceRoots );

        // ----------------------------------------------------------------------
        // <target name="test" />
        // ----------------------------------------------------------------------

        writeTestTargets( writer, testCompileSourceRoots );

        // ----------------------------------------------------------------------
        // <target name="javadoc" />
        // ----------------------------------------------------------------------
        writeJavadocTarget( writer );

        // ----------------------------------------------------------------------
        // <target name="package" />
        // ----------------------------------------------------------------------
        writePackageTarget( writer );

        // ----------------------------------------------------------------------
        // <target name="get-deps" />
        // ----------------------------------------------------------------------
        writeGetDepsTarget( writer );

        XmlWriterUtil.writeLineBreak( writer );

        writer.endElement(); // project

        XmlWriterUtil.writeLineBreak( writer );

        w.close();
    }

    /**
     * Generate an generic <code>build.xml</code> if not already exist
     *
     * @throws IOException
     * @see #DEFAULT_BUILD_FILENAME
     */
    private void writeBuildXml()
        throws IOException
    {
        File outputFile = new File( project.getBasedir(), DEFAULT_BUILD_FILENAME );

        if ( outputFile.exists() && !overwrite )
        {
            return;
        }

        String encoding = "UTF-8";

        OutputStreamWriter w = new OutputStreamWriter( new FileOutputStream( outputFile ), encoding );

        XMLWriter writer =
            new PrettyPrintXMLWriter( w, StringUtils.repeat( " ", DEFAULT_INDENTATION_SIZE ), encoding, null );

        // ----------------------------------------------------------------------
        // <!-- comments -->
        // ----------------------------------------------------------------------

        AntBuildWriterUtil.writeAntVersionHeader( writer );

        // ----------------------------------------------------------------------
        // <project/>
        // ----------------------------------------------------------------------

        writer.startElement( "project" );
        writer.addAttribute( "name", project.getArtifactId() );
        writer.addAttribute( "default", "package" );
        writer.addAttribute( "basedir", "." );

        XmlWriterUtil.writeLineBreak( writer );

        XmlWriterUtil.writeCommentText( writer, "Import " + DEFAULT_MAVEN_BUILD_FILENAME + " into the current project",
                                        1 );

        writer.startElement( "import" );
        writer.addAttribute( "file", DEFAULT_MAVEN_BUILD_FILENAME );
        writer.endElement(); // import

        XmlWriterUtil.writeLineBreak( writer, 1, 1 );

        XmlWriterUtil.writeCommentText( writer, "Help target", 1 );

        writer.startElement( "target" );
        writer.addAttribute( "name", "help" );

        writer.startElement( "echo" );
        writer.addAttribute( "message", "Please run: $ant -projecthelp" );
        writer.endElement(); // echo

        writer.endElement(); // target

        XmlWriterUtil.writeLineBreak( writer, 2 );

        writer.endElement(); // project

        XmlWriterUtil.writeLineBreak( writer );

        w.close();
    }

    /**
     * Write properties in the writer only for a non-POM project.
     *
     * @param writer
     */
    private void writeProperties( XMLWriter writer )
    {
        if ( AntBuildWriterUtil.isPomPackaging( project ) )
        {
            return;
        }

        // TODO: optional in m1
        // TODO: USD properties
        XmlWriterUtil.writeCommentText( writer, "Build environment properties", 1 );

        // ----------------------------------------------------------------------
        // File properties to override local properties
        // ----------------------------------------------------------------------

        writer.startElement( "property" );
        writer.addAttribute( "file", "${user.home}/.m2/maven.properties" );
        writer.endElement(); // property

        writer.startElement( "property" );
        writer.addAttribute( "file", DEFAULT_MAVEN_PROPERTIES_FILENAME );
        writer.endElement(); // property

        // ----------------------------------------------------------------------
        // Build properties
        // ----------------------------------------------------------------------

        XmlWriterUtil.writeLineBreak( writer, 2, 1 );

        writer.startElement( "property" );
        writer.addAttribute( "name", "maven.build.finalName" );
        writer.addAttribute( "value", project.getBuild().getFinalName() );
        writer.endElement(); // property

        writer.startElement( "property" );
        writer.addAttribute( "name", "maven.build.dir" );
        writer.addAttribute( "value",
                             AntBuildWriterUtil.toRelative( project.getBasedir(), project.getBuild().getDirectory() ) );
        writer.endElement(); // property

        writer.startElement( "property" );
        writer.addAttribute( "name", "maven.build.outputDir" );
        writer.addAttribute( "value",
                             "${maven.build.dir}/"
                                 + AntBuildWriterUtil.toRelative( new File( project.getBuild().getDirectory() ),
                                                                  project.getBuild().getOutputDirectory() ) );
        writer.endElement(); // property

        if ( !project.getCompileSourceRoots().isEmpty() )
        {
            List var = project.getCompileSourceRoots();
            String[] compileSourceRoots = (String[]) var.toArray( new String[var.size()] );
            for ( int i = 0; i < compileSourceRoots.length; i++ )
            {
                writer.startElement( "property" );
                writer.addAttribute( "name", "maven.build.srcDir." + i );
                writer.addAttribute( "value",
                                     AntBuildWriterUtil.toRelative( project.getBasedir(), compileSourceRoots[i] ) );
                writer.endElement(); // property
            }
        }

        if ( project.getBuild().getResources() != null )
        {
            List<Resource> var = project.getBuild().getResources();
            Resource[] array = var.toArray( new Resource[var.size()] );
            for ( int i = 0; i < array.length; i++ )
            {
                writer.startElement( "property" );
                writer.addAttribute( "name", "maven.build.resourceDir." + i );
                writer.addAttribute( "value",
                                     AntBuildWriterUtil.toRelative( project.getBasedir(), array[i].getDirectory() ) );
                writer.endElement(); // property
            }
        }

        writer.startElement( "property" );
        writer.addAttribute( "name", "maven.build.testOutputDir" );
        writer.addAttribute( "value",
                             "${maven.build.dir}/"
                                 + AntBuildWriterUtil.toRelative( new File( project.getBuild().getDirectory() ),
                                                                  project.getBuild().getTestOutputDirectory() ) );
        writer.endElement(); // property

        if ( !project.getTestCompileSourceRoots().isEmpty() )
        {
            List var = project.getTestCompileSourceRoots();
            String[] compileSourceRoots = (String[]) var.toArray( new String[var.size()] );
            for ( int i = 0; i < compileSourceRoots.length; i++ )
            {
                writer.startElement( "property" );
                writer.addAttribute( "name", "maven.build.testDir." + i );
                writer.addAttribute( "value",
                                     AntBuildWriterUtil.toRelative( project.getBasedir(), compileSourceRoots[i] ) );
                writer.endElement(); // property
            }
        }

        if ( project.getBuild().getTestResources() != null )
        {
            List<Resource> var = project.getBuild().getTestResources();
            Resource[] array = var.toArray( new Resource[var.size()] );
            for ( int i = 0; i < array.length; i++ )
            {
                writer.startElement( "property" );
                writer.addAttribute( "name", "maven.build.testResourceDir." + i );
                writer.addAttribute( "value",
                                     AntBuildWriterUtil.toRelative( project.getBasedir(), array[i].getDirectory() ) );
                writer.endElement(); // property
            }
        }

        writer.startElement( "property" );
        writer.addAttribute( "name", "maven.test.reports" );
        writer.addAttribute( "value", "${maven.build.dir}/test-reports" );
        writer.endElement(); // property

        String reportingOutputDir = project.getReporting().getOutputDirectory();
        // workaround for MNG-3475
        if ( !new File( reportingOutputDir ).isAbsolute() )
        {
            reportingOutputDir = new File( project.getBasedir(), reportingOutputDir ).getAbsolutePath();
        }
        writer.startElement( "property" );
        writer.addAttribute( "name", "maven.reporting.outputDirectory" );
        writer.addAttribute( "value",
                             "${maven.build.dir}/"
                                 + AntBuildWriterUtil.toRelative( new File( project.getBuild().getDirectory() ),
                                                                  reportingOutputDir ) );
        writer.endElement(); // property

        // ----------------------------------------------------------------------
        // Setting properties
        // ----------------------------------------------------------------------

        XmlWriterUtil.writeLineBreak( writer, 2, 1 );

        writer.startElement( "property" );
        writer.addAttribute( "name", "maven.repo.local" );
        writer.addAttribute( "value", "${user.home}/.m2/repository" );
        writer.endElement(); // property

        writer.startElement( "property" );
        writer.addAttribute( "name", "maven.settings.offline" );
        writer.addAttribute( "value", String.valueOf( settings.isOffline() ) );
        writer.endElement(); // property

        writer.startElement( "property" );
        writer.addAttribute( "name", "maven.settings.interactiveMode" );
        writer.addAttribute( "value", String.valueOf( settings.isInteractiveMode() ) );
        writer.endElement(); // property

        XmlWriterUtil.writeLineBreak( writer );
    }

    /**
     * Check if the local repository is in the default location: <code>${user.home}/.m2/repository</code>. If that is
     * the case then return
     * the path with the system property "user.home" in it. If not then just
     * return the absolute path to the local repository.
     */
    private String getLocalRepositoryPath()
    {
        String userHome = System.getProperty( "user.home" );
        String defaultPath = ( userHome + "/.m2/repository" ).replace( '\\', '/' );
        String actualPath = localRepository.getAbsolutePath().replace( '\\', '/' );
        if ( actualPath.equals( defaultPath ) )
        {
            return "${user.home}/.m2/repository";
        }
        else
        {
            return localRepository.getAbsolutePath();
        }
    }

    /**
     * Write path definition in the writer only for a non-POM project.
     *
     * @param writer
     */
    private void writeBuildPathDefinition( XMLWriter writer )
    {
        if ( AntBuildWriterUtil.isPomPackaging( project ) )
        {
            return;
        }

        XmlWriterUtil.writeCommentText( writer, "Defining classpaths", 1 );

        writeBuildPathDefinition( writer, "build.classpath", project.getCompileArtifacts() );

        writeBuildPathDefinition( writer, "build.test.classpath", project.getTestArtifacts() );

        XmlWriterUtil.writeLineBreak( writer );
    }

    private void writeBuildPathDefinition( XMLWriter writer, String id, List artifacts )
    {
        writer.startElement( "path" );
        writer.addAttribute( "id", id );

        for ( Object artifact1 : artifacts )
        {
            Artifact artifact = (Artifact) artifact1;

            writer.startElement( "pathelement" );

            String path;
            if ( Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ) )
            {
                path = getUninterpolatedSystemPath( artifact );
            }
            else
            {
                path = "${maven.repo.local}/" + artifactResolverWrapper.getLocalArtifactPath( artifact );
            }
            writer.addAttribute( "location", path );

            writer.endElement(); // pathelement
        }

        writer.endElement(); // path
    }

    private String getUninterpolatedSystemPath( Artifact artifact )
    {
        String managementKey = artifact.getDependencyConflictId();

        for ( Dependency dependency : project.getOriginalModel().getDependencies() )
        {
            if ( managementKey.equals( dependency.getManagementKey() ) )
            {
                return dependency.getSystemPath();
            }
        }

        for ( Profile profile : project.getOriginalModel().getProfiles() )
        {
            for ( Dependency dependency : profile.getDependencies() )
            {
                if ( managementKey.equals( dependency.getManagementKey() ) )
                {
                    return dependency.getSystemPath();
                }
            }
        }

        String path = artifact.getFile().getAbsolutePath();

        Properties props = new Properties();
        props.putAll( project.getProperties() );
        props.putAll( executionProperties );
        props.remove( "user.dir" );
        props.put( "basedir", project.getBasedir().getAbsolutePath() );

        SortedMap<String, String> candidateProperties = new TreeMap<String, String>();
        for ( Object o : props.keySet() )
        {
            String key = (String) o;
            String value = new File( props.getProperty( key ) ).getPath();
            if ( path.startsWith( value ) && value.length() > 0 )
            {
                candidateProperties.put( value, key );
            }
        }
        if ( !candidateProperties.isEmpty() )
        {
            String value = candidateProperties.lastKey();
            String key = candidateProperties.get( value );
            path = path.substring( value.length() );
            path = path.replace( '\\', '/' );
            return "${" + key + "}" + path;
        }

        return path;
    }

    /**
     * Write clean target in the writer depending the packaging of the project.
     *
     * @param writer the writer
     */
    private void writeCleanTarget( XMLWriter writer )
    {
        XmlWriterUtil.writeCommentText( writer, "Cleaning up target", 1 );

        writer.startElement( "target" );
        writer.addAttribute( "name", "clean" );
        writer.addAttribute( "description", "Clean the output directory" );

        if ( AntBuildWriterUtil.isPomPackaging( project ) )
        {
            if ( project.getModules() != null )
            {
                for ( Object o : project.getModules() )
                {
                    String moduleSubPath = (String) o;
                    AntBuildWriterUtil.writeAntTask( writer, project, moduleSubPath, "clean" );
                }
            }
        }
        else
        {
            writer.startElement( "delete" );
            writer.addAttribute( "dir", "${maven.build.dir}" );
            writer.endElement(); // delete
        }

        writer.endElement(); // target

        XmlWriterUtil.writeLineBreak( writer );
    }

    /**
     * Write compile target in the writer depending the packaging of the project.
     *
     * @param writer
     * @param compileSourceRoots
     * @throws IOException if any
     */
    private void writeCompileTarget( XMLWriter writer, List compileSourceRoots )
        throws IOException
    {
        XmlWriterUtil.writeCommentText( writer, "Compilation target", 1 );

        if ( AntBuildWriterUtil.isPomPackaging( project ) )
        {
            writer.startElement( "target" );
            writer.addAttribute( "name", "compile" );
            writer.addAttribute( "description", "Compile the code" );
            if ( project.getModules() != null )
            {
                for ( Object o : project.getModules() )
                {
                    String moduleSubPath = (String) o;
                    AntBuildWriterUtil.writeAntTask( writer, project, moduleSubPath, "compile" );
                }
            }
            writer.endElement(); // target
        }
        else
        {
            writer.startElement( "target" );
            writer.addAttribute( "name", "compile" );
            writer.addAttribute( "depends", "get-deps" );
            writer.addAttribute( "description", "Compile the code" );

            writeCompileTasks( writer, "${maven.build.outputDir}", compileSourceRoots,
                               project.getBuild().getResources(), null, false );

            writer.endElement(); // target
        }

        XmlWriterUtil.writeLineBreak( writer );
    }

    /**
     * Write compile-test target in the writer depending the packaging of the project.
     *
     * @param writer
     * @param testCompileSourceRoots
     * @throws IOException if any
     */
    private void writeCompileTestsTarget( XMLWriter writer, List testCompileSourceRoots )
        throws IOException
    {
        XmlWriterUtil.writeCommentText( writer, "Test-compilation target", 1 );

        if ( AntBuildWriterUtil.isPomPackaging( project ) )
        {
            writer.startElement( "target" );
            writer.addAttribute( "name", "compile-tests" );
            writer.addAttribute( "description", "Compile the test code" );
            if ( project.getModules() != null )
            {
                for ( Object o : project.getModules() )
                {
                    String moduleSubPath = (String) o;
                    AntBuildWriterUtil.writeAntTask( writer, project, moduleSubPath, "compile-tests" );
                }
            }
            writer.endElement(); // target
        }
        else
        {
            writer.startElement( "target" );
            writer.addAttribute( "name", "compile-tests" );
            AntBuildWriterUtil.addWrapAttribute( writer, "target", "depends", "compile", 2 );
            AntBuildWriterUtil.addWrapAttribute( writer, "target", "description", "Compile the test code", 2 );
            AntBuildWriterUtil.addWrapAttribute( writer, "target", "unless", "maven.test.skip", 2 );

            writeCompileTasks( writer, "${maven.build.testOutputDir}", testCompileSourceRoots,
                               project.getBuild().getTestResources(), "${maven.build.outputDir}", true );

            writer.endElement(); // target
        }

        XmlWriterUtil.writeLineBreak( writer );
    }

    /**
     * Write test target in the writer depending the packaging of the project.
     *
     * @param writer
     * @param testCompileSourceRoots
     */
    private void writeTestTargets( XMLWriter writer, List testCompileSourceRoots )
        throws IOException
    {
        XmlWriterUtil.writeCommentText( writer, "Run all tests", 1 );

        if ( AntBuildWriterUtil.isPomPackaging( project ) )
        {
            writePomParts( writer );
        }
        else
        {
            writer.startElement( "target" );
            writer.addAttribute( "name", "test" );
            AntBuildWriterUtil.addWrapAttribute( writer, "target", "depends", "compile-tests, junit-missing", 2 );
            AntBuildWriterUtil.addWrapAttribute( writer, "target", "unless", "junit.skipped", 2 );
            AntBuildWriterUtil.addWrapAttribute( writer, "target", "description", "Run the test cases", 2 );

            if ( !testCompileSourceRoots.isEmpty() )
            {
                writer.startElement( "mkdir" );
                writer.addAttribute( "dir", "${maven.test.reports}" );
                writer.endElement(); // mkdir

                writer.startElement( "junit" );
                writer.addAttribute( "printSummary", "yes" );
                writer.addAttribute( "haltonerror", "true" );
                writer.addAttribute( "haltonfailure", "true" );
                writer.addAttribute( "fork", "true" );
                writer.addAttribute( "dir", "." );

                writer.startElement( "sysproperty" );
                writer.addAttribute( "key", "basedir" );
                writer.addAttribute( "value", "." );
                writer.endElement(); // sysproperty

                writer.startElement( "formatter" );
                writer.addAttribute( "type", "xml" );
                writer.endElement(); // formatter

                writer.startElement( "formatter" );
                writer.addAttribute( "type", "plain" );
                writer.addAttribute( "usefile", "false" );
                writer.endElement(); // formatter

                writer.startElement( "classpath" );
                writer.startElement( "path" );
                writer.addAttribute( "refid", "build.test.classpath" );
                writer.endElement(); // path
                writer.startElement( "pathelement" );
                writer.addAttribute( "location", "${maven.build.outputDir}" );
                writer.endElement(); // pathelement
                writer.startElement( "pathelement" );
                writer.addAttribute( "location", "${maven.build.testOutputDir}" );
                writer.endElement(); // pathelement
                writer.endElement(); // classpath

                writer.startElement( "batchtest" );
                writer.addAttribute( "todir", "${maven.test.reports}" );
                writer.addAttribute( "unless", "test" );

                List includes = getTestIncludes();
                List excludes = getTestExcludes();

                writeTestFilesets( writer, testCompileSourceRoots, includes, excludes );

                writer.endElement(); // batchtest

                writer.startElement( "batchtest" );
                writer.addAttribute( "todir", "${maven.test.reports}" );
                writer.addAttribute( "if", "test" );

                includes = Arrays.asList( "**/${test}.java" );

                writeTestFilesets( writer, testCompileSourceRoots, includes, excludes );

                writer.endElement(); // batchtest

                writer.endElement(); // junit
            }
            writer.endElement(); // target

            XmlWriterUtil.writeLineBreak( writer, 2, 1 );

            writer.startElement( "target" );
            writer.addAttribute( "name", "test-junit-present" );

            writer.startElement( "available" );
            writer.addAttribute( "classname", "junit.framework.Test" );
            writer.addAttribute( "property", "junit.present" );
            writer.addAttribute( "classpathref", "build.test.classpath" );
            writer.endElement(); // available

            writer.endElement(); // target

            XmlWriterUtil.writeLineBreak( writer, 2, 1 );

            writer.startElement( "target" );
            writer.addAttribute( "name", "test-junit-status" );
            AntBuildWriterUtil.addWrapAttribute( writer, "target", "depends", "test-junit-present", 2 );
            writer.startElement( "condition" );
            writer.addAttribute( "property", "junit.missing" );
            writer.startElement( "and" );
            writer.startElement( "isfalse" );
            writer.addAttribute( "value", "${junit.present}" );
            writer.endElement(); // isfalse
            writer.startElement( "isfalse" );
            writer.addAttribute( "value", "${maven.test.skip}" );
            writer.endElement(); // isfalse
            writer.endElement(); // and
            writer.endElement(); // condition
            writer.startElement( "condition" );
            writer.addAttribute( "property", "junit.skipped" );
            writer.startElement( "or" );
            writer.startElement( "isfalse" );
            writer.addAttribute( "value", "${junit.present}" );
            writer.endElement(); // isfalse
            writer.startElement( "istrue" );
            writer.addAttribute( "value", "${maven.test.skip}" );
            writer.endElement(); // istrue
            writer.endElement(); // or
            writer.endElement(); // condition
            writer.endElement(); // target

            XmlWriterUtil.writeLineBreak( writer, 2, 1 );

            writer.startElement( "target" );
            writer.addAttribute( "name", "junit-missing" );
            AntBuildWriterUtil.addWrapAttribute( writer, "target", "depends", "test-junit-status", 2 );
            AntBuildWriterUtil.addWrapAttribute( writer, "target", "if", "junit.missing", 2 );

            // CHECKSTYLE_OFF: MagicNumber
            writer.startElement( "echo" );
            writer.writeText( StringUtils.repeat( "=", 35 ) + " WARNING " + StringUtils.repeat( "=", 35 ) );
            writer.endElement(); // echo

            writer.startElement( "echo" );
            // CHECKSTYLE_OFF: LineLength
            writer.writeText( " JUnit is not present in the test classpath or your $ANT_HOME/lib directory. Tests not executed." );
            // CHECKSTYLE_ON: LineLength
            writer.endElement(); // echo

            writer.startElement( "echo" );
            writer.writeText( StringUtils.repeat( "=", 79 ) );
            writer.endElement(); // echo
            // CHECKSTYLE_ON: MagicNumber

            writer.endElement(); // target
        }

        XmlWriterUtil.writeLineBreak( writer );
    }

    /**
     * @param writer {@link XMLWriter}
     */
    private void writePomParts( XMLWriter writer )
    {
        writer.startElement( "target" );
        writer.addAttribute( "name", "test" );
        writer.addAttribute( "description", "Run the test cases" );
        if ( project.getModules() != null )
        {
            for ( Object o : project.getModules() )
            {
                String moduleSubPath = (String) o;
                AntBuildWriterUtil.writeAntTask( writer, project, moduleSubPath, "test" );
            }
        }
        writer.endElement(); // target
    }

    /**
     * Gets the include patterns for the unit tests.
     *
     * @return A list of strings with include patterns, might be empty but never <code>null</code>.
     */
    private List getTestIncludes()
        throws IOException
    {
        // CHECKSTYLE_OFF: LineLength
        List includes = getSelectorList( AntBuildWriterUtil.getMavenSurefirePluginOptions( project, "includes", null ) );
        // CHECKSTYLE_ON: LineLength
        if ( includes == null || includes.isEmpty() )
        {
            includes = Arrays.asList( "**/Test*.java", "**/*Test.java", "**/*TestCase.java" );
        }
        return includes;
    }

    /**
     * Gets the exclude patterns for the unit tests.
     *
     * @return A list of strings with exclude patterns, might be empty but never <code>null</code>.
     */
    private List getTestExcludes()
        throws IOException
    {
        // CHECKSTYLE_OFF: LineLength
        List excludes = getSelectorList( AntBuildWriterUtil.getMavenSurefirePluginOptions( project, "excludes", null ) );
        // CHECKSTYLE_ON: LineLength
        if ( excludes == null || excludes.isEmpty() )
        {
            excludes = Arrays.asList( "**/*Abstract*Test.java" );
        }
        return excludes;
    }

    /**
     * Write the <code>&lt;fileset&gt;</code> elements for the test compile source roots.
     *
     * @param writer
     * @param testCompileSourceRoots
     * @param includes
     * @param excludes
     */
    private void writeTestFilesets( XMLWriter writer, List testCompileSourceRoots, List includes, List excludes )
    {
        for ( int i = 0; i < testCompileSourceRoots.size(); i++ )
        {
            writer.startElement( "fileset" );
            writer.addAttribute( "dir", "${maven.build.testDir." + i + "}" );
            // TODO: m1 allows additional test exclusions via maven.ant.excludeTests
            AntBuildWriterUtil.writeIncludesExcludes( writer, includes, excludes );
            writer.endElement(); // fileset
        }
    }

    /**
     * Write javadoc target in the writer depending the packaging of the project.
     *
     * @param writer
     * @throws IOException if any
     */
    private void writeJavadocTarget( XMLWriter writer )
        throws IOException
    {
        XmlWriterUtil.writeCommentText( writer, "Javadoc target", 1 );

        writer.startElement( "target" );
        writer.addAttribute( "name", "javadoc" );
        writer.addAttribute( "description", "Generates the Javadoc of the application" );

        if ( AntBuildWriterUtil.isPomPackaging( project ) )
        {
            if ( project.getModules() != null )
            {
                for ( Object o : project.getModules() )
                {
                    String moduleSubPath = (String) o;
                    AntBuildWriterUtil.writeAntTask( writer, project, moduleSubPath, "javadoc" );
                }
            }
        }
        else
        {
            AntBuildWriterUtil.writeJavadocTask( writer, project, artifactResolverWrapper );
        }

        writer.endElement(); // target

        XmlWriterUtil.writeLineBreak( writer );
    }

    /**
     * Write package target in the writer depending the packaging of the project.
     *
     * @param writer
     * @throws IOException if any
     */
    private void writePackageTarget( XMLWriter writer )
        throws IOException
    {
        String synonym = null; // type of the package we are creating (for example jar)
        XmlWriterUtil.writeCommentText( writer, "Package target", 1 );

        writer.startElement( "target" );
        writer.addAttribute( "name", "package" );

        if ( !AntBuildWriterUtil.isPomPackaging( project ) )
        {
            writer.addAttribute( "depends", "compile,test" );
        }
        writer.addAttribute( "description", "Package the application" );

        if ( AntBuildWriterUtil.isPomPackaging( project ) )
        {
            if ( project.getModules() != null )
            {
                for ( Object o : project.getModules() )
                {
                    String moduleSubPath = (String) o;
                    AntBuildWriterUtil.writeAntTask( writer, project, moduleSubPath, "package" );
                }
            }
        }
        else
        {
            if ( AntBuildWriterUtil.isJarPackaging( project ) )
            {
                AntBuildWriterUtil.writeJarTask( writer, project );
                synonym = "jar";
            }
            else if ( AntBuildWriterUtil.isEarPackaging( project ) )
            {
                AntBuildWriterUtil.writeEarTask( writer, project, artifactResolverWrapper );
                synonym = "ear";
            }
            else if ( AntBuildWriterUtil.isWarPackaging( project ) )
            {
                AntBuildWriterUtil.writeWarTask( writer, project, artifactResolverWrapper );
                synonym = "war";
            }
            else
            {
                writer.startElement( "echo" );
                writer.addAttribute( "message", "No Ant task exists for the packaging '" + project.getPackaging()
                    + "'. " + "You could overrided the Ant package target in your build.xml." );
                writer.endElement(); // echo
            }
        }

        writer.endElement(); // target

        XmlWriterUtil.writeLineBreak( writer );

        if ( synonym != null )
        {
            // CHECKSTYLE_OFF: LineLength
            XmlWriterUtil.writeCommentText( writer, "A dummy target for the package named after the type it creates", 1 );
            // CHECKSTYLE_ON: LineLength
            writer.startElement( "target" );
            writer.addAttribute( "name", synonym );
            writer.addAttribute( "depends", "package" );
            writer.addAttribute( "description", "Builds the " + synonym + " for the application" );
            writer.endElement(); // target

            XmlWriterUtil.writeLineBreak( writer );
        }
    }

    private void writeCompileTasks( XMLWriter writer, String outputDirectory, List compileSourceRoots, List resources,
                                    String additionalClassesDirectory, boolean isTest )
        throws IOException
    {
        writer.startElement( "mkdir" );
        writer.addAttribute( "dir", outputDirectory );
        writer.endElement(); // mkdir

        // CHECKSTYLE_OFF: LineLength
        if ( !compileSourceRoots.isEmpty() )
        {
            writer.startElement( "javac" );
            writer.addAttribute( "destdir", outputDirectory );
            Map[] includes = AntBuildWriterUtil.getMavenCompilerPluginOptions( project, "includes", null );
            AntBuildWriterUtil.addWrapAttribute( writer, "javac", "includes",
                                                 getCommaSeparatedList( includes, "include" ), 3 );
            Map[] excludes = AntBuildWriterUtil.getMavenCompilerPluginOptions( project, "excludes", null );
            AntBuildWriterUtil.addWrapAttribute( writer, "javac", "excludes",
                                                 getCommaSeparatedList( excludes, "exclude" ), 3 );
            AntBuildWriterUtil.addWrapAttribute( writer,
                                                 "javac",
                                                 "encoding",
                                                 AntBuildWriterUtil.getMavenCompilerPluginBasicOption( project,
                                                                                                       "encoding", null ),
                                                 3 );
            AntBuildWriterUtil.addWrapAttribute( writer, "javac", "nowarn",
                                                 AntBuildWriterUtil.getMavenCompilerPluginBasicOption( project,
                                                                                                       "showWarnings",
                                                                                                       "false" ), 3 );
            AntBuildWriterUtil.addWrapAttribute( writer,
                                                 "javac",
                                                 "debug",
                                                 AntBuildWriterUtil.getMavenCompilerPluginBasicOption( project,
                                                                                                       "debug", "true" ),
                                                 3 );
            AntBuildWriterUtil.addWrapAttribute( writer, "javac", "optimize",
                                                 AntBuildWriterUtil.getMavenCompilerPluginBasicOption( project,
                                                                                                       "optimize",
                                                                                                       "false" ), 3 );
            AntBuildWriterUtil.addWrapAttribute( writer,
                                                 "javac",
                                                 "deprecation",
                                                 AntBuildWriterUtil.getMavenCompilerPluginBasicOption( project,
                                                                                                       "showDeprecation",
                                                                                                       "true" ), 3 );
            AntBuildWriterUtil.addWrapAttribute( writer,
                                                 "javac",
                                                 "target",
                                                 AntBuildWriterUtil.getMavenCompilerPluginBasicOption( project,
                                                                                                       "target", "1.1" ),
                                                 3 );
            AntBuildWriterUtil.addWrapAttribute( writer, "javac", "verbose",
                                                 AntBuildWriterUtil.getMavenCompilerPluginBasicOption( project,
                                                                                                       "verbose",
                                                                                                       "false" ), 3 );
            AntBuildWriterUtil.addWrapAttribute( writer, "javac", "fork",
                                                 AntBuildWriterUtil.getMavenCompilerPluginBasicOption( project, "fork",
                                                                                                       "false" ), 3 );
            AntBuildWriterUtil.addWrapAttribute( writer, "javac", "memoryMaximumSize",
                                                 AntBuildWriterUtil.getMavenCompilerPluginBasicOption( project,
                                                                                                       "meminitial",
                                                                                                       null ), 3 );
            AntBuildWriterUtil.addWrapAttribute( writer,
                                                 "javac",
                                                 "memoryInitialSize",
                                                 AntBuildWriterUtil.getMavenCompilerPluginBasicOption( project,
                                                                                                       "maxmem", null ),
                                                 3 );
            AntBuildWriterUtil.addWrapAttribute( writer,
                                                 "javac",
                                                 "source",
                                                 AntBuildWriterUtil.getMavenCompilerPluginBasicOption( project,
                                                                                                       "source", "1.3" ),
                                                 3 );

            String[] compileSourceRootsArray =
                (String[]) compileSourceRoots.toArray( new String[compileSourceRoots.size()] );
            for ( int i = 0; i < compileSourceRootsArray.length; i++ )
            {
                writer.startElement( "src" );
                writer.startElement( "pathelement" );
                if ( isTest )
                {
                    writer.addAttribute( "location", "${maven.build.testDir." + i + "}" );
                }
                else
                {
                    writer.addAttribute( "location", "${maven.build.srcDir." + i + "}" );
                }
                writer.endElement(); // pathelement
                writer.endElement(); // src
            }

            if ( additionalClassesDirectory == null )
            {
                writer.startElement( "classpath" );
                if ( isTest )
                {
                    writer.addAttribute( "refid", "build.test.classpath" );
                }
                else
                {
                    writer.addAttribute( "refid", "build.classpath" );
                }
                writer.endElement(); // classpath
            }
            else
            {
                writer.startElement( "classpath" );
                writer.startElement( "path" );
                if ( isTest )
                {
                    writer.addAttribute( "refid", "build.test.classpath" );
                }
                else
                {
                    writer.addAttribute( "refid", "build.classpath" );
                }
                writer.endElement(); // path
                writer.startElement( "pathelement" );
                writer.addAttribute( "location", additionalClassesDirectory );
                writer.endElement(); // pathelement
                writer.endElement(); // classpath
            }

            writer.endElement(); // javac
        }
        // CHECKSTYLE_ON: LineLength

        Resource[] array = (Resource[]) resources.toArray( new Resource[resources.size()] );
        for ( int i = 0; i < array.length; i++ )
        {
            Resource resource = array[i];

            if ( new File( resource.getDirectory() ).exists() )
            {
                String outputDir = outputDirectory;
                if ( resource.getTargetPath() != null && resource.getTargetPath().length() > 0 )
                {
                    outputDir = outputDir + "/" + resource.getTargetPath();

                    writer.startElement( "mkdir" );
                    writer.addAttribute( "dir", outputDir );
                    writer.endElement(); // mkdir
                }

                writer.startElement( "copy" );
                writer.addAttribute( "todir", outputDir );

                writer.startElement( "fileset" );
                if ( isTest )
                {
                    writer.addAttribute( "dir", "${maven.build.testResourceDir." + i + "}" );
                }
                else
                {
                    writer.addAttribute( "dir", "${maven.build.resourceDir." + i + "}" );
                }

                AntBuildWriterUtil.writeIncludesExcludes( writer, resource.getIncludes(), resource.getExcludes() );

                writer.endElement(); // fileset

                writer.endElement(); // copy
            }
        }
    }

    /**
     * Write get-deps target in the writer only for a non-POM project
     *
     * @param writer
     */
    private void writeGetDepsTarget( XMLWriter writer )
    {
        if ( AntBuildWriterUtil.isPomPackaging( project ) )
        {
            return;
        }

        XmlWriterUtil.writeCommentText( writer, "Download dependencies target", 1 );

        writer.startElement( "target" );
        writer.addAttribute( "name", "test-offline" );

        writer.startElement( "condition" );
        writer.addAttribute( "property", "maven.mode.offline" );
        writer.startElement( "equals" );
        writer.addAttribute( "arg1", "${maven.settings.offline}" );
        writer.addAttribute( "arg2", "true" );
        writer.endElement(); // equals
        writer.endElement(); // condition
        writer.endElement(); // target

        XmlWriterUtil.writeLineBreak( writer, 2, 1 );

        writer.startElement( "target" );
        writer.addAttribute( "name", "get-deps" );
        AntBuildWriterUtil.addWrapAttribute( writer, "target", "depends", "test-offline", 2 );
        AntBuildWriterUtil.addWrapAttribute( writer, "target", "description", "Download all dependencies", 2 );
        AntBuildWriterUtil.addWrapAttribute( writer, "target", "unless", "maven.mode.offline", 2 ); // TODO: check, and
                                                                                                    // differs from m1

        writer.startElement( "mkdir" );
        writer.addAttribute( "dir", "${maven.repo.local}" );
        writer.endElement(); // mkdir

        String basedir = project.getBasedir().getAbsolutePath();

        // CHECKSTYLE_OFF: LineLength
        // TODO: proxy - probably better to use wagon!
        for ( Object o : project.getTestArtifacts() )
        {
            Artifact artifact = (Artifact) o;

            if ( Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ) )
            {
                continue;
            }

            String path = artifactResolverWrapper.getLocalArtifactPath( artifact );

            if ( !new File( path ).exists() )
            {
                File parentDirs = new File( path ).getParentFile();
                if ( parentDirs != null )
                {
                    writer.startElement( "mkdir" );
                    // Replace \ with / in the parent dir path
                    writer.addAttribute( "dir", "${maven.repo.local}/" + parentDirs.getPath().replace( '\\', '/' ) );
                    writer.endElement(); // mkdir
                }

                for ( Object o1 : project.getRepositories() )
                {
                    Repository repository = (Repository) o1;
                    String url = repository.getUrl();

                    String localDir = getProjectRepoDirectory( url, basedir );
                    if ( localDir != null )
                    {
                        if ( localDir.length() > 0 && !localDir.endsWith( "/" ) )
                        {
                            localDir += '/';
                        }

                        writer.startElement( "copy" );
                        writer.addAttribute( "file", localDir + path );
                        AntBuildWriterUtil.addWrapAttribute( writer, "copy", "tofile", "${maven.repo.local}/" + path, 3 );
                        AntBuildWriterUtil.addWrapAttribute( writer, "copy", "failonerror", "false", 3 );
                        writer.endElement(); // copy
                    }
                    else
                    {
                        writer.startElement( "get" );
                        writer.addAttribute( "src", url + '/' + path );
                        AntBuildWriterUtil.addWrapAttribute( writer, "get", "dest", "${maven.repo.local}/" + path, 3 );
                        AntBuildWriterUtil.addWrapAttribute( writer, "get", "usetimestamp", "false", 3 );
                        AntBuildWriterUtil.addWrapAttribute( writer, "get", "ignoreerrors", "true", 3 );
                        writer.endElement(); // get
                    }
                }
            }
        }
        // CHECKSTYLE_ON: LineLength

        writer.endElement(); // target

        XmlWriterUtil.writeLineBreak( writer );
    }

    /**
     * Gets the relative path to a repository that is rooted in the project. The returned path (if any) will always use
     * the forward slash ('/') as the directory separator. For example, the path "target/it-repo" will be returned for a
     * repository constructed from the URL "file://${basedir}/target/it-repo".
     *
     * @param repoUrl The URL to the repository, must not be <code>null</code>.
     * @param projectDir The absolute path to the base directory of the project, must not be <code>null</code>
     * @return The path to the repository (relative to the project base directory) or <code>null</code> if the
     *         repository is not rooted in the project.
     */
    static String getProjectRepoDirectory( String repoUrl, String projectDir )
    {
        try
        {
            /*
             * NOTE: The usual way of constructing repo URLs rooted in the project is "file://${basedir}" or
             * "file:/${basedir}". None of these forms delivers a valid URL on both Unix and Windows (even ignoring URL
             * encoding), one platform will end up with the first directory of the path being interpreted as the host
             * name...
             */
            if ( repoUrl.regionMatches( true, 0, "file://", 0, 7 ) )
            {
                String temp = repoUrl.substring( 7 );
                if ( !temp.startsWith( "/" ) && !temp.regionMatches( true, 0, "localhost/", 0, 10 ) )
                {
                    repoUrl = "file:///" + temp;
                }
            }
            String path = FileUtils.toFile( new URL( repoUrl ) ).getPath();
            if ( path.startsWith( projectDir ) )
            {
                path = path.substring( projectDir.length() ).replace( '\\', '/' );
                if ( path.startsWith( "/" ) )
                {
                    path = path.substring( 1 );
                }
                if ( path.endsWith( "/" ) )
                {
                    path = path.substring( 0, path.length() - 1 );
                }
                return path;
            }
        }
        catch ( Exception e )
        {
            // not a "file:" URL or simply malformed
        }
        return null;
    }

    // ----------------------------------------------------------------------
    // Convenience methods
    // ----------------------------------------------------------------------

    /**
     * Put a property in properties defined by a name and a value
     *
     * @param properties not null
     * @param name
     * @param value not null
     */
    private static void addProperty( Properties properties, String name, String value )
    {
        properties.put( name, StringUtils.isNotEmpty( value ) ? value : "" );
    }

    /**
     * @param includes an array of includes or exludes map
     * @param key a key wanted in the map, like <code>include</code> or <code>exclude</code>
     * @return a String with comma-separated value of a key in each map
     */
    private static String getCommaSeparatedList( Map[] includes, String key )
    {
        if ( ( includes == null ) || ( includes.length == 0 ) )
        {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        for ( int i = 0; i < includes.length; i++ )
        {
            String s = (String) includes[i].get( key );
            if ( StringUtils.isEmpty( s ) )
            {
                continue;
            }

            sb.append( s );

            if ( i < ( includes.length - 1 ) )
            {
                sb.append( "," );
            }
        }

        if ( sb.length() == 0 )
        {
            return null;
        }

        return sb.toString();
    }

    /**
     * Flattens the specified file selector options into a simple string list. For instance, the input
     * <p/>
     * 
     * <pre>
     * [ {include=&quot;*Test.java&quot;}, {include=&quot;*TestCase.java&quot;} ]
     * </pre>
     * <p/>
     * is converted to
     * <p/>
     * 
     * <pre>
     * [ &quot;*Test.java&quot;, &quot;*TestCase.java&quot; ]
     * </pre>
     *
     * @param options The file selector options to flatten, may be <code>null</code>.
     * @return The string list, might be empty but never <code>null</code>.
     */
    private static List getSelectorList( Map[] options )
    {
        List list = new ArrayList();
        if ( options != null && options.length > 0 )
        {
            for ( Map option : options )
            {
                list.addAll( option.values() );
            }
        }
        return list;
    }

}
