/*******************************************************************************
 * Copyright (c) 2004, 2006 Richard Hoefter and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Richard Hoefter (richard.hoefter@web.de) - initial API and implementation, bugs 95297, 97051, 128103
 *     IBM Corporation - nlsing and incorporating into Eclipse, bug 108276, bug 124210
 *     Nikolay Metchev (N.Metchev@teamphone.com) - bug 108276
 *******************************************************************************/

package org.eclipse.ant.internal.ui.datatransfer;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactoryConfigurationError;

import org.eclipse.ant.internal.ui.AntUIPlugin;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.swt.widgets.Shell;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.ProcessingInstruction;
import org.xml.sax.SAXException;

/**
 * Creates build.xml file.
 */
public class BuildFileCreator
{
    protected static final String IMPORT_BUILDFILE_PROCESSING_TARGET = "eclipse.ant.import"; //$NON-NLS-1$
    protected static final String WARNING = " WARNING: Eclipse auto-generated file." + ExportUtil.NEWLINE + //$NON-NLS-1$
                                            "              Any modifications will be overwritten."; //$NON-NLS-1$
    protected static final String NOTE =    "              To include a user specific buildfile here, " + //$NON-NLS-1$
                                            "simply create one in the same" + ExportUtil.NEWLINE + //$NON-NLS-1$
                                            "              directory with the processing instruction " + //$NON-NLS-1$
                                            "<?" +  IMPORT_BUILDFILE_PROCESSING_TARGET + "?>" + ExportUtil.NEWLINE + //$NON-NLS-1$ //$NON-NLS-2$
                                            "              as the first entry and export the buildfile again. "; //$NON-NLS-1$

    protected static String BUILD_XML = "build.xml"; //$NON-NLS-1$
    protected static String JUNIT_OUTPUT_DIR = "junit"; //$NON-NLS-1$
    protected static boolean CHECK_SOURCE_CYCLES = true;
    protected static boolean CREATE_ECLIPSE_COMPILE_TARGET = true;
    
    private Document doc;
    private Element root;
    private IJavaProject project;
    private String projectName;
    private String projectRoot;
    private Map variable2valueMap;
    private Shell shell;
    private Set visited = new TreeSet(); // record used subclasspaths
    private Node classpathNode;
    
    private BuildFileCreator() {}

    /**
     * Constructor. Please prefer {@link #createBuildFiles(Set, Shell, IProgressMonitor)} if
     * you do not want call the various createXXX() methods yourself.
     * 
     * @param project    create buildfile for this project
     * @param shell      parent instance for dialogs
     */
    public BuildFileCreator(IJavaProject project, Shell shell) throws ParserConfigurationException
    {
        this.project = project;
        this.projectName = project.getProject().getName();
        this.projectRoot = ExportUtil.getProjectRoot(project);
        this.variable2valueMap = new LinkedHashMap();
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        this.doc = dbf.newDocumentBuilder().newDocument();
        this.shell = shell;
    }
      
    /**
     * Create buildfile for given projects.
     * 
     * @param projects    create buildfiles for these <code>IJavaProject</code>
     *                    objects
     * @param shell       parent instance for dialogs
     * @return            project names for which buildfiles were created
     * @throws InterruptedException thrown when user cancels task
     */
    public static List createBuildFiles(Set projects, Shell shell, IProgressMonitor pm)
        throws JavaModelException, ParserConfigurationException,
               TransformerConfigurationException, TransformerException,
               IOException, CoreException, InterruptedException
    {
        List res = new ArrayList();
        try {
            createBuildFilesLoop(projects, shell, pm, res);
        } finally {
            if (pm != null) {
                pm.done();
            }
        }
        return res;
    }

    private static void createBuildFilesLoop(Set projects, Shell shell, IProgressMonitor pm,
            List res) throws CoreException, ParserConfigurationException,
            JavaModelException, TransformerConfigurationException,
            TransformerFactoryConfigurationError, TransformerException,
            UnsupportedEncodingException, InterruptedException {

        // determine files to create/change
        List files = new ArrayList();
        for (Iterator iter = projects.iterator(); iter.hasNext();)
        {
            IJavaProject currentProject = (IJavaProject) iter.next();
            IFile file = currentProject.getProject().getFile(BuildFileCreator.BUILD_XML);
            files.add(file);
        }

        // trigger checkout
        Map validator2files = ExportUtil.getFileModificationValidator(files);
        Set confirmedFiles = ExportUtil.validateEdit(shell, validator2files);

        if (pm != null) {
            pm.beginTask(DataTransferMessages.AntBuildfileExportPage_0,
                    confirmedFiles.size());
        }
        
        int i = 0;
        for (Iterator iter = projects.iterator(); iter.hasNext(); i++)
        {
            IJavaProject currentProject = (IJavaProject) iter.next();
            IFile file = currentProject.getProject().getFile(BuildFileCreator.BUILD_XML);
            if (! confirmedFiles.contains(file))
            {
                continue;
            }
            
            if (pm != null) {
                pm.subTask(currentProject.getProject().getName());
            }
            
            BuildFileCreator instance = new BuildFileCreator(currentProject, shell);
            instance.createRoot();
            instance.createImports();
            EclipseClasspath classpath = new EclipseClasspath(currentProject);
            if (CHECK_SOURCE_CYCLES) {
                SourceAnalyzer.checkCycles(currentProject, classpath, shell);
            }
            instance.createClasspaths(classpath);
            instance.createInit(classpath.srcDirs, classpath.classDirs);   
            instance.createClean(classpath.classDirs);
            instance.createCleanAll();
            instance.createBuild(classpath.srcDirs, classpath.classDirs,
                                 classpath.inclusionLists, classpath.exclusionLists);
            instance.createBuildRef();
            if (CREATE_ECLIPSE_COMPILE_TARGET) {
                instance.addInitEclipseCompiler();
                instance.addBuildEclipse();
            }
            instance.createRun();           
            instance.addSubProperties(currentProject, classpath);
            instance.createProperty();

            // write build file
            String xml = ExportUtil.toString(instance.doc);
            InputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8")); //$NON-NLS-1$
            if (file.exists())
            {
                file.setContents(is, true, true, null);
            }
            else
            {
                file.create(is, true, null);
            }

            if (pm != null) {
                pm.worked(1);
                if (pm.isCanceled()) {
                    throw new InterruptedException();
                }
            }
            res.add(instance.projectName);
        }
    }

    /**
     * Add property tag.
     */
    public void createProperty()
    {
        // read debug options from Eclipse settings
        boolean source = JavaCore.GENERATE.equals(project.getOption(JavaCore.COMPILER_SOURCE_FILE_ATTR, true));
        boolean lines = JavaCore.GENERATE.equals(project.getOption(JavaCore.COMPILER_LINE_NUMBER_ATTR, true));
        boolean vars = JavaCore.GENERATE.equals(project.getOption(JavaCore.COMPILER_LOCAL_VARIABLE_ATTR, true));
        
        List debuglevel = new ArrayList();
        if (source)
        {
            debuglevel.add("source"); //$NON-NLS-1$
        }
        if (lines)
        {
            debuglevel.add("lines"); //$NON-NLS-1$
        }
        if (vars)
        {
            debuglevel.add("vars"); //$NON-NLS-1$
        }
        if (debuglevel.size() == 0)
        {
            debuglevel.add("none"); //$NON-NLS-1$
        }
        variable2valueMap.put("debuglevel", ExportUtil.toString(debuglevel, ",")); //$NON-NLS-1$ //$NON-NLS-2$

        // "Generated .class files compatibility"
        String target = project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true); 
        variable2valueMap.put("target", target); //$NON-NLS-1$

        // "Compiler compliance level"
        //String compliance = project.getOption(JavaCore.COMPILER_COMPLIANCE, true); 
        
        // "Source compatibility"
        String sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true);
        variable2valueMap.put("source", sourceLevel); //$NON-NLS-1$
        
        // <property name="x" value="y"/>
        boolean first = true;
        Node node = root.getFirstChild();
        for (Iterator iterator = variable2valueMap.keySet().iterator(); iterator.hasNext();)
        {
            String key = (String) iterator.next();
            String value = (String) variable2valueMap.get(key);
            Element prop = doc.createElement("property"); //$NON-NLS-1$
            prop.setAttribute("name", key); //$NON-NLS-1$
            prop.setAttribute("value", value); //$NON-NLS-1$
            if (first)
            {
                first = false;               
            }
            else
            {
                node = node.getNextSibling();
            }
            node = root.insertBefore(prop, node);
        }
        
        // <property environment="env"/>
        Element env = doc.createElement("property"); //$NON-NLS-1$
        env.setAttribute("environment", "env"); //$NON-NLS-1$ //$NON-NLS-2$
        root.insertBefore(env, root.getFirstChild());
    }

    /**
     * Create project tag.
     */
    public void createRoot()
    {   
        // <project name="hello" default="build" basedir=".">
        root = doc.createElement("project"); //$NON-NLS-1$
        root.setAttribute("name" , projectName); //$NON-NLS-1$
        root.setAttribute("default" , "build"); //$NON-NLS-1$ //$NON-NLS-2$
        root.setAttribute("basedir" , "."); //$NON-NLS-1$ //$NON-NLS-2$
        doc.appendChild(root);
        
        // <!-- warning -->
        Comment comment = doc.createComment(WARNING + ExportUtil.NEWLINE + NOTE);
        doc.insertBefore(comment, root);
    }
    
    /**
     * Find buildfiles in projectroot directory and automatically import them.
     */
    public void createImports()
    {
        // <import file="javadoc.xml"/>
        File dir = new File(projectRoot);
        FilenameFilter filter = new FilenameFilter()
        {
            public boolean accept(File acceptDir, String name)
            {
                return name.endsWith(".xml") && !name.endsWith(BUILD_XML); //$NON-NLS-1$
            }
        };

        File[] files = dir.listFiles(filter);
        if (files == null)
        {
            return;
        }
        for (int i = 0; i < files.length; i++)
        {
            // import file if it is an XML document with marker comment as first
            // child
            File file = files[i];
            Document docCandidate;
            try {
                docCandidate = ExportUtil.parseXmlFile(file);
                Node node = docCandidate.getFirstChild();
                if (node instanceof ProcessingInstruction &&  
                        IMPORT_BUILDFILE_PROCESSING_TARGET.equals(((ProcessingInstruction) node).getTarget().trim())) {
                    Element element = doc.createElement("import"); //$NON-NLS-1$
                    element.setAttribute("file", file.getName()); //$NON-NLS-1$
                    root.appendChild(element);
                }
            } catch (ParserConfigurationException e){
                AntUIPlugin.log("invalid XML file not imported: " + file.getAbsolutePath(), e); //$NON-NLS-1$
            } catch (SAXException e) {
                AntUIPlugin.log("invalid XML file not imported: " + file.getAbsolutePath(), e); //$NON-NLS-1$
            } catch (IOException e) {
                AntUIPlugin.log("invalid XML file not imported: " + file.getAbsolutePath(), e); //$NON-NLS-1$
            }
        }
    }

    /**
     * Create classpath tags.
     */
    public void createClasspaths(EclipseClasspath classpath) throws JavaModelException
    {
        createClasspaths(null, project, classpath);
    }
    
    /**
     * Create classpath tags. Allows to specify ID.
     * @param pathId    specify id, if null project name is used
     */
    public void createClasspaths(String pathId, IJavaProject currentProject, EclipseClasspath classpath)
        throws JavaModelException
    {
        if (currentProject == null)
        {
            AntUIPlugin.log("project is not loaded in workspace: " + pathId, null); //$NON-NLS-1$ 
            return;
        }
        // <path id="hello.classpath">
        //     <pathelement location="${hello.location}/classes"/>
        //     <pathelement location="${hello.location}/x.jar"/>
        //     <path refid="${goodbye.classpath}"/>
        // </path>
        Element element = doc.createElement("path"); //$NON-NLS-1$
        if (pathId == null)
        {
            pathId = currentProject.getProject().getName() + ".classpath"; //$NON-NLS-1$
        }
        element.setAttribute("id", pathId); //$NON-NLS-1$
        visited.add(pathId);
        variable2valueMap.putAll(classpath.variable2valueMap);
        for (Iterator iter = ExportUtil.removeDuplicates(classpath.rawClassPathEntries).iterator(); iter.hasNext();)
        {
            String entry = (String) iter.next(); 
            if (EclipseClasspath.isProjectReference(entry))
            {
                Element pathElement = doc.createElement("path"); //$NON-NLS-1$
                IJavaProject referencedProject = EclipseClasspath.resolveProjectReference(entry); 
                if (referencedProject == null)
                {
                    AntUIPlugin.log("project is not loaded in workspace: " + pathId, null); //$NON-NLS-1$
                    continue;
                }
                String refPathId = referencedProject.getProject().getName() + ".classpath"; //$NON-NLS-1$
                pathElement.setAttribute("refid", refPathId); //$NON-NLS-1$
                element.appendChild(pathElement);               
                if (visited.add(refPathId))
                {
                    createClasspaths(null, referencedProject, new EclipseClasspath(referencedProject)); // recursion
                }
            }
            else if (EclipseClasspath.isUserLibraryReference(entry) ||
                     EclipseClasspath.isUserSystemLibraryReference(entry) ||
                     EclipseClasspath.isLibraryReference(entry))
            {
                addUserLibrary(element, entry);
            }
            else
            {
                // prefix with ${project.location}
                String prefix = ""; //$NON-NLS-1$
                if (!entry.startsWith("${") &&                                  // no variable ${var}/classes //$NON-NLS-1$
                    !projectName.equals(currentProject.getProject().getName())) // not main project 
                {
                    String currentProjectRoot= ExportUtil.getProjectRoot(currentProject);
                    entry= ExportUtil.getRelativePath(entry, currentProjectRoot);
                    if (!new Path(entry).isAbsolute()) {
                        prefix = "${" + currentProject.getProject().getName() + ".location}/"; //$NON-NLS-1$ //$NON-NLS-2$
                    }
                }
                Element pathElement = doc.createElement("pathelement"); //$NON-NLS-1$
                String path = ExportUtil.getRelativePath(prefix + entry, projectRoot);
                pathElement.setAttribute("location", path); //$NON-NLS-1$
                element.appendChild(pathElement);
            }
        }
        addToClasspathBlock(element);
    }

    private void addUserLibrary(Element element, String entry)
    {
        // add classpath reference
        Element pathElement = doc.createElement("path"); //$NON-NLS-1$
        IClasspathContainer container = EclipseClasspath.resolveUserLibraryReference(entry); 
        String name = ExportUtil.removePrefixAndSuffix(entry, "${", "}"); //$NON-NLS-1$ //$NON-NLS-2$
        pathElement.setAttribute("refid", name); //$NON-NLS-1$
        if (!EclipseClasspath.isUserSystemLibraryReference(entry))
        {
            element.appendChild(pathElement);
        }

        // add classpath
        if (visited.add(entry))
        {
            Element userElement = doc.createElement("path"); //$NON-NLS-1$
            userElement.setAttribute("id", name); //$NON-NLS-1$
            IClasspathEntry entries[] = container.getClasspathEntries();
            for (int i = 0; i < entries.length; i++)
            {   
                String jarFile = entries[i].getPath().toString();
                // use ECLIPSE_HOME variable for library jars
                if (EclipseClasspath.isLibraryReference(entry))
                {
                    IPath home = JavaCore.getClasspathVariable("ECLIPSE_HOME"); //$NON-NLS-1$
                    if (home.isPrefixOf(entries[i].getPath()))
                    {
                        variable2valueMap.put("ECLIPSE_HOME", home.toString()); //$NON-NLS-1$
                        jarFile = "${ECLIPSE_HOME}" + jarFile.substring(home.toString().length()); //$NON-NLS-1$ 
                    }
                    else if (! new File(jarFile).exists() &&
                            jarFile.startsWith('/' + projectName) &&
                            new File(projectRoot, jarFile.substring(('/' + projectName).length())).exists())
                    {
                        // workaround that additional jars are stored with
                        // leading project root in container object, although
                        // they are relative and indeed correctly stored in
                        // build.properties (jars.extra.classpath)
                        jarFile = jarFile.substring(('/' + projectName).length() + 1);
                    }
                }
                jarFile = ExportUtil.getRelativePath(jarFile, projectRoot);
                Element userPathElement = doc.createElement("pathelement"); //$NON-NLS-1$
                userPathElement.setAttribute("location", jarFile); //$NON-NLS-1$
                userElement.appendChild(userPathElement);
            }
            addToClasspathBlock(userElement);
        }
    }

    private void addToClasspathBlock(Element element)
    {
        // remember node to insert all classpaths at same location
        if (classpathNode == null)
        {
            classpathNode = root.appendChild(element);
        }
        else
        {
            classpathNode = classpathNode.getNextSibling();
            classpathNode = root.insertBefore(element, classpathNode);
        }
    }
    
    /**
     * Add properties of subprojects to internal properties map.
     */
    public void addSubProperties(IJavaProject subproject, EclipseClasspath classpath) throws JavaModelException
    {
        for (Iterator iterator = ExportUtil.getClasspathProjectsRecursive(subproject).iterator(); iterator.hasNext();)
        {
            IJavaProject subProject = (IJavaProject) iterator.next(); 
            String location = subProject.getProject().getName() + ".location"; //$NON-NLS-1$
            // add subproject properties to variable2valueMap
            String subProjectRoot = ExportUtil.getProjectRoot(subProject);
            String relativePath = ExportUtil.getRelativePath(subProjectRoot,
                    projectRoot);
            variable2valueMap.put(location, relativePath);
            variable2valueMap.putAll(classpath.variable2valueMap);    
        }
    }

    /**
     * Create init target. Creates directories and copies resources.
     * @param srcDirs            source directories to copy resources from
     * @param classDirs          classes directories to copy resources to
     */
    public void createInit(List srcDirs, List classDirs)
    {
        // <target name="init">
        //     <mkdir dir="classes"/>
        // </target>
        Element element = doc.createElement("target"); //$NON-NLS-1$
        element.setAttribute("name", "init"); //$NON-NLS-1$ //$NON-NLS-2$
        List classDirsUnique = ExportUtil.removeDuplicates(classDirs);        
        for (Iterator iterator = classDirsUnique.iterator(); iterator.hasNext();)
        {            
            String classDir = (String) iterator.next();
            if (!classDir.equals(".") && //$NON-NLS-1$
                !EclipseClasspath.isReference(classDir))
            {
                Element pathElement = doc.createElement("mkdir"); //$NON-NLS-1$
                pathElement.setAttribute("dir", classDir); //$NON-NLS-1$
                element.appendChild(pathElement);
            }
        }
        root.appendChild(element);

        createCopyResources(srcDirs, classDirs, element);
    }

    private void createCopyResources(List srcDirs, List classDirs, Element element)
    {
        // Check filter for copying resources
        String filter = project.getOption(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, true);
        StringTokenizer tokenizer = new StringTokenizer(filter, ","); //$NON-NLS-1$
        List filters = Collections.list(tokenizer);
        filters.add("*.java"); //$NON-NLS-1$
        
        // prefix filters with wildcard
        for (int i = 0; i < filters.size(); i++)
        {
            String item = ((String) filters.get(i)).trim();
            if (item.equals("*")) //$NON-NLS-1$
            {
                // everything is excluded from copying
                return;
            }            
            filters.set(i, "**/" + item); //$NON-NLS-1$
        }
        
        // <copy todir="classes" includeemptydirs="false">
        //     <fileset dir="src" excludes="**/*.java"/>
        // </copy>
        for (int i = 0; i < srcDirs.size(); i++)
        {
            String srcDir = (String) srcDirs.get(i);
            String classDir = (String) classDirs.get(i);
            if (! EclipseClasspath.isReference(classDir))
            {
                Element copyElement = doc.createElement("copy"); //$NON-NLS-1$
                copyElement.setAttribute("todir", classDir); //$NON-NLS-1$
                copyElement.setAttribute("includeemptydirs", "false"); //$NON-NLS-1$ //$NON-NLS-2$
                Element filesetElement = doc.createElement("fileset"); //$NON-NLS-1$
                filesetElement.setAttribute("dir", srcDir); //$NON-NLS-1$
                filesetElement.setAttribute("excludes", ExportUtil.toString(filters, ", ")); //$NON-NLS-1$ //$NON-NLS-2$
                copyElement.appendChild(filesetElement);
                element.appendChild(copyElement);
            }
        }
    }

    /**
     * Create clean target.
     * @param classDirs    classes directories to delete
     */
    public void createClean(List classDirs)
    {
        // <target name="clean">
        //     <delete dir="classes"/>
        // </target>
        Element element = doc.createElement("target"); //$NON-NLS-1$
        element.setAttribute("name", "clean"); //$NON-NLS-1$ //$NON-NLS-2$
        List classDirUnique = ExportUtil.removeDuplicates(classDirs);
        for (Iterator iterator = classDirUnique.iterator(); iterator.hasNext();)
        {
            String classDir = (String) iterator.next();
            if (!classDir.equals(".") && //$NON-NLS-1$
                !EclipseClasspath.isReference(classDir))
            {
                Element deleteElement = doc.createElement("delete"); //$NON-NLS-1$
                deleteElement.setAttribute("dir", classDir); //$NON-NLS-1$
                element.appendChild(deleteElement);
            }
        }
        root.appendChild(element);    

        // <target name="clean">
        //     <delete>
        //         <fileset dir="." includes="**/*.class"/>
        //     </delete>
        // </target>
        if (classDirs.contains(".")) //$NON-NLS-1$
        {
            Element deleteElement = doc.createElement("delete"); //$NON-NLS-1$
            Element filesetElement = doc.createElement("fileset"); //$NON-NLS-1$
            filesetElement.setAttribute("dir", "."); //$NON-NLS-1$ //$NON-NLS-2$
            filesetElement.setAttribute("includes", "**/*.class"); //$NON-NLS-1$ //$NON-NLS-2$
            deleteElement.appendChild(filesetElement);           
            element.appendChild(deleteElement);           
        }
    }
    
    /**
     * Create cleanall target.
     */
    public void createCleanAll() throws JavaModelException
    {
        // <target name="cleanall" depends="clean">
        //     <ant antfile="${hello.location}/build.xml" inheritAll="false" target="clean"/>
        // </target>
        Element element = doc.createElement("target"); //$NON-NLS-1$
        element.setAttribute("name", "cleanall"); //$NON-NLS-1$ //$NON-NLS-2$
        element.setAttribute("depends", "clean"); //$NON-NLS-1$ //$NON-NLS-2$
        List subProjects = ExportUtil.getClasspathProjectsRecursive(project);
        for (Iterator iterator = subProjects.iterator(); iterator.hasNext();)
        {
            IJavaProject subProject = (IJavaProject) iterator.next();
            Element antElement = doc.createElement("ant"); //$NON-NLS-1$
            antElement.setAttribute("antfile", "${" + subProject.getProject().getName() + ".location}/" + BUILD_XML); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
            antElement.setAttribute("target", "clean");  //$NON-NLS-1$ //$NON-NLS-2$
            antElement.setAttribute("inheritAll", "false");  //$NON-NLS-1$ //$NON-NLS-2$
            element.appendChild(antElement);
        }
        root.appendChild(element);
    }

    /**
     * Create build target.
     * @param srcDirs           source directories of mainproject
     * @param classDirs         class directories of mainproject
     * @param inclusionLists    inclusion filters of mainproject 
     * @param exclusionLists    exclusion filters of mainproject
     */
    public void createBuild(List srcDirs, List classDirs, List inclusionLists, List exclusionLists) throws JavaModelException
    {
        // <target name="build" depends="build-subprojects,build-project"/>
        Element element = doc.createElement("target"); //$NON-NLS-1$
        element.setAttribute("name", "build"); //$NON-NLS-1$ //$NON-NLS-2$
        element.setAttribute("depends", "build-subprojects,build-project"); //$NON-NLS-1$ //$NON-NLS-2$
        root.appendChild(element);
        
        // <target name="build-subprojects">
        //     <ant antfile="${hello.location}/build.xml" inheritAll="false" target="build-project"/>
        // </target>
        element = doc.createElement("target"); //$NON-NLS-1$
        element.setAttribute("name", "build-subprojects"); //$NON-NLS-1$ //$NON-NLS-2$
        List subProjects = ExportUtil.getClasspathProjectsRecursive(project);
        for (Iterator iterator = subProjects.iterator(); iterator.hasNext();)
        {
            IJavaProject subProject = (IJavaProject) iterator.next();
            Element antElement = doc.createElement("ant"); //$NON-NLS-1$
            antElement.setAttribute("antfile", "${" + subProject.getProject().getName() + ".location}/" + BUILD_XML); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
            antElement.setAttribute("target", "build-project");  //$NON-NLS-1$ //$NON-NLS-2$
            antElement.setAttribute("inheritAll", "false");  //$NON-NLS-1$ //$NON-NLS-2$
            if (CREATE_ECLIPSE_COMPILE_TARGET) {
                Element propertysetElement = doc.createElement("propertyset"); //$NON-NLS-1$
                Element propertyrefElement = doc.createElement("propertyref"); //$NON-NLS-1$
                propertyrefElement.setAttribute("name", "build.compiler");  //$NON-NLS-1$ //$NON-NLS-2$
                propertysetElement.appendChild(propertyrefElement);
                antElement.appendChild(propertysetElement);
            }
            element.appendChild(antElement);           
        }
        root.appendChild(element);
        
        // <target name="build-project" depends="init">
        //     <echo message="${ant.project.name}: ${ant.file}"/>
        //     <javac destdir="classes">
        //         <src path="src"/>
        //         <include name=""/>
        //         <exclude name=""/>
        //         <classpath refid="project.classpath"/>
        //     </javac>    
        // </target>        
        element = doc.createElement("target"); //$NON-NLS-1$
        element.setAttribute("name", "build-project"); //$NON-NLS-1$ //$NON-NLS-2$
        element.setAttribute("depends", "init"); //$NON-NLS-1$ //$NON-NLS-2$
        Element echoElement = doc.createElement("echo"); //$NON-NLS-1$
        echoElement.setAttribute("message", "${ant.project.name}: ${ant.file}"); //$NON-NLS-1$ //$NON-NLS-2$
        element.appendChild(echoElement);           
        for (int i = 0; i < srcDirs.size(); i++)
        {
            String srcDir = (String) srcDirs.get(i);
            if (!EclipseClasspath.isReference(srcDir))
            {
                String classDir = (String) classDirs.get(i);
                List inclusions = (List) inclusionLists.get(i);
                List exclusions = (List) exclusionLists.get(i);
                Element javacElement = doc.createElement("javac"); //$NON-NLS-1$
                javacElement.setAttribute("destdir", classDir); //$NON-NLS-1$
                javacElement.setAttribute("debug", "true"); //$NON-NLS-1$ //$NON-NLS-2$
                javacElement.setAttribute("debuglevel", "${debuglevel}"); //$NON-NLS-1$ //$NON-NLS-2$
                javacElement.setAttribute("source", "${source}"); //$NON-NLS-1$ //$NON-NLS-2$
                javacElement.setAttribute("target", "${target}"); //$NON-NLS-1$ //$NON-NLS-2$
    
                Element srcElement = doc.createElement("src"); //$NON-NLS-1$
                srcElement.setAttribute("path", srcDir); //$NON-NLS-1$
                javacElement.appendChild(srcElement);            
    
                for (Iterator iter = inclusions.iterator(); iter.hasNext();)
                {
                    String inclusion = (String) iter.next();
                    Element includeElement = doc.createElement("include"); //$NON-NLS-1$
                    includeElement.setAttribute("name", inclusion); //$NON-NLS-1$
                    javacElement.appendChild(includeElement);
                }           
                for (Iterator iter = exclusions.iterator(); iter.hasNext();)
                {
                    String exclusion = (String) iter.next();
                    Element excludeElement = doc.createElement("exclude"); //$NON-NLS-1$
                    excludeElement.setAttribute("name", exclusion); //$NON-NLS-1$
                    javacElement.appendChild(excludeElement);
                }           
                Element classpathRefElement = doc.createElement("classpath"); //$NON-NLS-1$
                classpathRefElement.setAttribute("refid", projectName + ".classpath"); //$NON-NLS-1$ //$NON-NLS-2$
                javacElement.appendChild(classpathRefElement);
                element.appendChild(javacElement);
                
                addCompilerBootClasspath(srcDirs, javacElement);
            }
        }
        root.appendChild(element);
    }
    
    /**
     * Create target build-refprojects which compiles projects which reference
     * current project.
     */
    private void createBuildRef() throws JavaModelException {
        
        Set refProjects = new TreeSet(ExportUtil.getJavaProjectComparator());
        IJavaProject[] projects = project.getJavaModel().getJavaProjects();
        for (int i = 0; i < projects.length; i++) {
            List subProjects = ExportUtil.getClasspathProjects(projects[i]);
            for (Iterator iter = subProjects.iterator(); iter.hasNext();) {
                IJavaProject p = (IJavaProject) iter.next();
                if (projectName.equals(p.getProject().getName())) {
                    refProjects.add(projects[i]);
                }
            }
        }
        
        // <target name="build-refprojects">
        //     <ant antfile="${hello.location}/build.xml" target="clean" inheritAll="false"/> 
        //     <ant antfile="${hello.location}/build.xml" target="build" inheritAll="false"/> 
        // </target>
        Element element = doc.createElement("target"); //$NON-NLS-1$
        element.setAttribute("name", "build-refprojects"); //$NON-NLS-1$ //$NON-NLS-2$
        element.setAttribute("description", "Build all projects which " + //$NON-NLS-1$ //$NON-NLS-2$
                "reference this project. Useful to propagate changes."); //$NON-NLS-1$
        for (Iterator iter = refProjects.iterator(); iter.hasNext();) {
            IJavaProject p = (IJavaProject) iter.next();
            String location = p.getProject().getName() + ".location"; //$NON-NLS-1$
            String refProjectRoot = ExportUtil.getProjectRoot(p);
            String relativePath = ExportUtil.getRelativePath(refProjectRoot,
                    projectRoot);
            variable2valueMap.put(location, relativePath);

            Element antElement = doc.createElement("ant"); //$NON-NLS-1$
            antElement.setAttribute("antfile", "${" + p.getProject().getName() + ".location}/" + BUILD_XML); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
            antElement.setAttribute("target", "clean"); //$NON-NLS-1$ //$NON-NLS-2$
            antElement.setAttribute("inheritAll", "false"); //$NON-NLS-1$ //$NON-NLS-2$
            element.appendChild(antElement);
            
            antElement = doc.createElement("ant"); //$NON-NLS-1$
            antElement.setAttribute("antfile", "${" + p.getProject().getName() + ".location}/" + BUILD_XML); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
            antElement.setAttribute("target", "build"); //$NON-NLS-1$ //$NON-NLS-2$
            antElement.setAttribute("inheritAll", "false");  //$NON-NLS-1$ //$NON-NLS-2$
            if (CREATE_ECLIPSE_COMPILE_TARGET) {
                Element propertysetElement = doc.createElement("propertyset"); //$NON-NLS-1$
                Element propertyrefElement = doc.createElement("propertyref"); //$NON-NLS-1$
                propertyrefElement.setAttribute("name", "build.compiler");  //$NON-NLS-1$ //$NON-NLS-2$
                propertysetElement.appendChild(propertyrefElement);
                antElement.appendChild(propertysetElement);
            }
            element.appendChild(antElement);
        }
        root.appendChild(element);
    }
    
    /**
     * Add target to initialize Eclipse compiler. It copies required jars to ant
     * lib directory.
     */
    public void addInitEclipseCompiler()
    {
        // use ECLIPSE_HOME classpath variable
        IPath value = JavaCore.getClasspathVariable("ECLIPSE_HOME"); //$NON-NLS-1$
        variable2valueMap.put("ECLIPSE_HOME", ExportUtil.getRelativePath( //$NON-NLS-1$
                value + "", projectRoot)); //$NON-NLS-1$
        
        // <target name="init-eclipse-compiler" description="copy Eclipse compiler jars to ant lib directory">
        //     <property name="ECLIPSE_HOME" value="C:/Programme/eclipse-3.1" />
        //     <copy todir="${ant.library.dir}">
        //         <fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar" />
        //     </copy>
        //     <unzip dest="${ant.library.dir}">
        //         <patternset includes="jdtCompilerAdapter.jar" />
        //         <fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar" />
        //     </unzip>
        // </target>
        Element element = doc.createElement("target"); //$NON-NLS-1$
        element.setAttribute("name", "init-eclipse-compiler"); //$NON-NLS-1$ //$NON-NLS-2$
        element.setAttribute("description", "copy Eclipse compiler jars to ant lib directory"); //$NON-NLS-1$ //$NON-NLS-2$
        Element copyElement = doc.createElement("copy"); //$NON-NLS-1$
        copyElement.setAttribute("todir", "${ant.library.dir}"); //$NON-NLS-1$ //$NON-NLS-2$
        Element filesetElement = doc.createElement("fileset"); //$NON-NLS-1$
        filesetElement.setAttribute("dir", "${ECLIPSE_HOME}/plugins"); //$NON-NLS-1$ //$NON-NLS-2$
        filesetElement.setAttribute("includes", "org.eclipse.jdt.core_*.jar"); //$NON-NLS-1$ //$NON-NLS-2$
        copyElement.appendChild(filesetElement);
        element.appendChild(copyElement);
        Element unzipElement = doc.createElement("unzip"); //$NON-NLS-1$
        unzipElement.setAttribute("dest", "${ant.library.dir}"); //$NON-NLS-1$ //$NON-NLS-2$
        Element patternsetElement = doc.createElement("patternset"); //$NON-NLS-1$
        patternsetElement.setAttribute("includes", "jdtCompilerAdapter.jar"); //$NON-NLS-1$ //$NON-NLS-2$
        unzipElement.appendChild(patternsetElement);
        unzipElement.appendChild(filesetElement.cloneNode(false));
        element.appendChild(unzipElement);
        root.appendChild(element);
    }

    /**
     * Add target to compile project using Eclipse compiler.
     */
    public void addBuildEclipse()
    {
        // <target name="build-eclipse-compiler" description="compile project with Eclipse compiler">
        //     <property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter" />
        //     <antcall target="build" />
        // </target>
        Element element = doc.createElement("target"); //$NON-NLS-1$
        element.setAttribute("name", "build-eclipse-compiler"); //$NON-NLS-1$ //$NON-NLS-2$
        element.setAttribute("description", "compile project with Eclipse compiler"); //$NON-NLS-1$ //$NON-NLS-2$
        Element propertyElement = doc.createElement("property"); //$NON-NLS-1$
        propertyElement.setAttribute("name", "build.compiler"); //$NON-NLS-1$ //$NON-NLS-2$
        propertyElement.setAttribute("value", "org.eclipse.jdt.core.JDTCompilerAdapter"); //$NON-NLS-1$ //$NON-NLS-2$
        element.appendChild(propertyElement);
        Element antcallElement = doc.createElement("antcall"); //$NON-NLS-1$
        antcallElement.setAttribute("target", "build"); //$NON-NLS-1$ //$NON-NLS-2$
        element.appendChild(antcallElement);
        root.appendChild(element);
    }

    /**
     * Add add all bootclasspaths in srcDirs to given javacElement.
     */
    private void addCompilerBootClasspath(List srcDirs, Element javacElement)
    {
        // <bootclasspath>
        //     <path refid="mylib.bootclasspath"/>
        // </bootclasspath>
        Element bootclasspathElement = doc.createElement("bootclasspath"); //$NON-NLS-1$
        boolean bootclasspathUsed = false;
        for (Iterator iter = srcDirs.iterator(); iter.hasNext();)
        {
            String entry = (String) iter.next();
            if (EclipseClasspath.isUserSystemLibraryReference(entry))
            {
                Element pathElement = doc.createElement("path"); //$NON-NLS-1$                        
                pathElement.setAttribute("refid", ExportUtil.removePrefixAndSuffix(entry, "${", "}")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                bootclasspathElement.appendChild(pathElement);
                bootclasspathUsed = true;
            }
        }
        if (bootclasspathUsed)
        {
            javacElement.appendChild(bootclasspathElement);
        }
    }

    /**
     * Add run targets.
     * @throws CoreException thrown if problem accessing the launch configuration
     * @throws TransformerFactoryConfigurationError thrown if applet file could not get created
     * @throws UnsupportedEncodingException thrown if applet file could not get created
     */
    public void createRun() throws CoreException, TransformerFactoryConfigurationError, UnsupportedEncodingException
    {
        // <target name="run">
        //     <java fork="yes" classname="class" failonerror="true" dir="." newenvironment="true">
        //         <env key="a" value="b"/>
        //         <jvmarg value="-Dx=y"/>
        //         <arg value="arg"/>
        //         <classpath refid="project.classpath"/>
        //     </java>
        // </target>
        ILaunchConfiguration[] confs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations();
        boolean junitUsed = false;
        for (int i = 0; i < confs.length; i++)
        {
            ILaunchConfiguration conf = confs[i];
            if (!projectName.equals(conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""))) //$NON-NLS-1$
            {
                continue;
            }
                    
            if (conf.getType().getIdentifier().equals(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION))
            {
                addJavaApplication(variable2valueMap, conf);
            }
            else if (conf.getType().getIdentifier().equals(IJavaLaunchConfigurationConstants.ID_JAVA_APPLET))
            {
                addApplet(variable2valueMap, conf);
            }
            else if (conf.getType().getIdentifier().equals("org.eclipse.jdt.junit.launchconfig" /*JUnitLaunchConfiguration.ID_JUNIT_APPLICATION*/)) //$NON-NLS-1$
            {                    
                addJUnit(variable2valueMap, conf);
                junitUsed = true;
            }           
        }
        
        if (junitUsed)
        {
            addJUnitReport();
        }
    }

    /**
     * Convert Java application launch configuration to ant target and add it to a document.
     * @param variable2value    adds Eclipse variables to this map,
     *                             if run configuration makes use of this feature
     * @param conf                 Java application launch configuration
     */
    public void addJavaApplication(Map variable2value, ILaunchConfiguration conf) throws CoreException
    {
        Element element = doc.createElement("target"); //$NON-NLS-1$
        element.setAttribute("name", conf.getName()); //$NON-NLS-1$
        Element javaElement = doc.createElement("java"); //$NON-NLS-1$
        javaElement.setAttribute("fork", "yes"); //$NON-NLS-1$ //$NON-NLS-2$
        javaElement.setAttribute("classname", conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, "")); //$NON-NLS-1$ //$NON-NLS-2$
        javaElement.setAttribute("failonerror", "true"); //$NON-NLS-1$ //$NON-NLS-2$
        String dir = conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, ""); //$NON-NLS-1$
        ExportUtil.addVariable(variable2value, dir, projectRoot);                
        if (!dir.equals("")) //$NON-NLS-1$
        {
            javaElement.setAttribute("dir", ExportUtil.getRelativePath(dir, projectRoot)); //$NON-NLS-1$
        }
        if (!conf.getAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, true))
        {
            javaElement.setAttribute("newenvironment", "true"); //$NON-NLS-1$ //$NON-NLS-2$
        }
        Map props = conf.getAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, new TreeMap());
        addElements(props, doc, javaElement, "env", "key", "value"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        addElement(conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, ""), doc, javaElement, "jvmarg", "line", variable2value, projectRoot); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        addElement(conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, ""), doc, javaElement, "arg", "line", variable2value, projectRoot); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        element.appendChild(javaElement);
        
        addRuntimeClasspath(conf, javaElement);
        addRuntimeBootClasspath(conf, javaElement);
        root.appendChild(element);
    }

    /**
     * Convert applet launch configuration to Ant target and add it to a document. 
     * @param variable2value    adds Eclipse variables to this map,
     *                             if run configuration makes use of this feature
     * @param conf                 applet configuration
     * @throws CoreException thrown if problem dealing with launch configuration or underlying resources 
     * @throws TransformerFactoryConfigurationError thrown if applet file could not get created 
     * @throws UnsupportedEncodingException thrown if applet file could not get created
     */
    public void addApplet(Map variable2value, ILaunchConfiguration conf) throws CoreException, TransformerFactoryConfigurationError, UnsupportedEncodingException
    {
        String dir = conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, ""); //$NON-NLS-1$
        if (dir.equals("")) //$NON-NLS-1$
        {
            dir = projectRoot;
        }
        ExportUtil.addVariable(variable2value, dir, projectRoot);
        String value;
        try
        {
            value = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(dir);    
        }
        catch (CoreException e)
        {
            // cannot resolve variable
            value = null;
        }

        String htmlfile = ((value != null) ? value : dir) + '/' + conf.getName() + ".html"; //$NON-NLS-1$
        // confirm overwrite
        if (ExportUtil.existsUserFile(htmlfile) && !ExportUtil.confirm(DataTransferMessages.AntBuildfileExportPage_4 + ": " + htmlfile, shell)) //$NON-NLS-1$
        {
            return;
        }
        IJavaProject javaProject = ExportUtil.getJavaProjectByName(projectName);
        IFile file = javaProject.getProject().getFile(conf.getName() + ".html"); //$NON-NLS-1$
        if (ExportUtil.validateEdit(shell, file)) // checkout file if required
        {
            // write build file
            String html = AppletUtil.buildHTMLFile(conf);
            InputStream is = new ByteArrayInputStream(html.getBytes("UTF-8")); //$NON-NLS-1$
            if (file.exists())
            {
                file.setContents(is, true, true, null);
            }
            else
            {
                file.create(is, true, null);
            }
        }
        
        Element element = doc.createElement("target"); //$NON-NLS-1$
        element.setAttribute("name", conf.getName()); //$NON-NLS-1$
        Element javaElement = doc.createElement("java"); //$NON-NLS-1$
        javaElement.setAttribute("fork", "yes");  //$NON-NLS-1$//$NON-NLS-2$
        javaElement.setAttribute("classname", conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_APPLET_APPLETVIEWER_CLASS, "sun.applet.AppletViewer")); //$NON-NLS-1$ //$NON-NLS-2$
        javaElement.setAttribute("failonerror", "true"); //$NON-NLS-1$ //$NON-NLS-2$
        if (value != null)
        {
            javaElement.setAttribute("dir", ExportUtil.getRelativePath(dir, projectRoot)); //$NON-NLS-1$
        }
        addElement(conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, ""), doc, javaElement, "jvmarg", "line", variable2value, projectRoot);   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
        addElement(conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, ""), doc, javaElement, "arg", "line", variable2value, projectRoot);   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
        addElement(conf.getName() + ".html", doc, javaElement, "arg", "line", variable2value, projectRoot); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        element.appendChild(javaElement);
        addRuntimeClasspath(conf, javaElement);
        addRuntimeBootClasspath(conf, javaElement);
        root.appendChild(element);
    }
    
    /**
     * Convert JUnit launch configuration to JUnit task and add it to a document. 
     * @param variable2value    adds Eclipse variables to this map,
     *                             if run configuration makes use of this feature
     * @param conf                 applet configuration
     */
    public void addJUnit(Map variable2value, ILaunchConfiguration conf) throws CoreException
    {
        // <target name="runtest">
        //     <mkdir dir="junit"/>
        //     <junit fork="yes" printsummary="withOutAndErr">
        //         <formatter type="xml"/>
        //         <test name="testclass"/>
        //         <env key="a" value="b"/>
        //         <jvmarg value="-Dx=y"/>
        //         <classpath refid="project.classpath"/>
        //     </junit>
        // </target>
        String testClass = conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, ""); //$NON-NLS-1$
        Element element = doc.createElement("target"); //$NON-NLS-1$
        element.setAttribute("name", conf.getName()); //$NON-NLS-1$
        
        Element mkdirElement = doc.createElement("mkdir"); //$NON-NLS-1$
        mkdirElement.setAttribute("dir", "${junit.output.dir}"); //$NON-NLS-1$ //$NON-NLS-2$
        element.appendChild(mkdirElement);
        
        Element junitElement = doc.createElement("junit"); //$NON-NLS-1$
        junitElement.setAttribute("fork", "yes"); //$NON-NLS-1$ //$NON-NLS-2$
        junitElement.setAttribute("printsummary", "withOutAndErr"); //$NON-NLS-1$ //$NON-NLS-2$
        String dir = conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, ""); //$NON-NLS-1$
        ExportUtil.addVariable(variable2value, dir, projectRoot);                
        if (!dir.equals("")) //$NON-NLS-1$
        {
            junitElement.setAttribute("dir", ExportUtil.getRelativePath(dir, projectRoot)); //$NON-NLS-1$
        }
        if (!conf.getAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, true))
        {
            junitElement.setAttribute("newenvironment", "true"); //$NON-NLS-1$ //$NON-NLS-2$
        }
        Element formatterElement = doc.createElement("formatter"); //$NON-NLS-1$
        formatterElement.setAttribute("type", "xml");  //$NON-NLS-1$//$NON-NLS-2$
        junitElement.appendChild(formatterElement);
        if (!testClass.equals("")) //$NON-NLS-1$
        {
            // Case 1: Single JUnit class
            Element testElement = doc.createElement("test"); //$NON-NLS-1$
            testElement.setAttribute("name", testClass); //$NON-NLS-1$
            testElement.setAttribute("todir", "${junit.output.dir}"); //$NON-NLS-1$ //$NON-NLS-2$
            junitElement.appendChild(testElement);                       
        }
        else
        {
            // Case 2: Run all tests in project, package or source folder
            String container = conf.getAttribute("org.eclipse.jdt.junit.CONTAINER" /*JUnitBaseLaunchConfiguration.LAUNCH_CONTAINER_ATTR*/, ""); //$NON-NLS-1$ //$NON-NLS-2$
            IType[] types = ExportUtil.findTestsInContainer(container);
            Set sortedTypes = new TreeSet(ExportUtil.getITypeComparator());
            sortedTypes.addAll(Arrays.asList(types));
            for (Iterator iter = sortedTypes.iterator(); iter.hasNext();) {
                IType type = (IType) iter.next();
                Element testElement = doc.createElement("test"); //$NON-NLS-1$
                testElement.setAttribute("name", type.getFullyQualifiedName()); //$NON-NLS-1$
                testElement.setAttribute("todir", "${junit.output.dir}"); //$NON-NLS-1$ //$NON-NLS-2$
                junitElement.appendChild(testElement);                       
            }
        }
        Map props = conf.getAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, new TreeMap());
        addElements(props, doc, junitElement, "env", "key", "value"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        addElement(conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, ""), doc, junitElement, "jvmarg", "line", variable2value, projectRoot); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        element.appendChild(junitElement);
        addRuntimeClasspath(conf, junitElement);
        addRuntimeBootClasspath(conf, junitElement);
        root.appendChild(element);
    }
    
    /**
     * Add junitreport target. 
     */
    public void addJUnitReport()
    {
        variable2valueMap.put("junit.output.dir", JUNIT_OUTPUT_DIR); //$NON-NLS-1$
        
        // <target name="junitreport">
        //     <junitreport todir="junit">
        //         <fileset dir="junit">
        //             <include name="TEST-*.xml"/>
        //         </fileset>
        //         <report format="frames" todir="junit"/>
        //     </junitreport>
        // </target>
        Element element = doc.createElement("target"); //$NON-NLS-1$
        element.setAttribute("name", "junitreport"); //$NON-NLS-1$ //$NON-NLS-2$
        Element junitreport = doc.createElement("junitreport"); //$NON-NLS-1$
        junitreport.setAttribute("todir", "${junit.output.dir}"); //$NON-NLS-1$ //$NON-NLS-2$
        Element fileset = doc.createElement("fileset"); //$NON-NLS-1$
        fileset.setAttribute("dir", "${junit.output.dir}"); //$NON-NLS-1$ //$NON-NLS-2$
        junitreport.appendChild(fileset);
        Element include = doc.createElement("include"); //$NON-NLS-1$
        include.setAttribute("name", "TEST-*.xml"); //$NON-NLS-1$ //$NON-NLS-2$
        fileset.appendChild(include);
        Element report = doc.createElement("report"); //$NON-NLS-1$
        report.setAttribute("format", "frames"); //$NON-NLS-1$ //$NON-NLS-2$
        report.setAttribute("todir", "${junit.output.dir}"); //$NON-NLS-1$ //$NON-NLS-2$
        junitreport.appendChild(report);
        element.appendChild(junitreport);
        root.appendChild(element);
    }

    /**
     * Add classpath tag to given javaElement.
     */
    private void addRuntimeClasspath(ILaunchConfiguration conf, Element javaElement) throws JavaModelException
    {
        // <classpath refid="hello.classpath"/>
        Element classpathRefElement = doc.createElement("classpath"); //$NON-NLS-1$
        EclipseClasspath runtimeClasspath = new EclipseClasspath(project, conf, false);
        if (ExportUtil.isDefaultClasspath(project, runtimeClasspath))
        {
            classpathRefElement.setAttribute("refid", projectName + ".classpath"); //$NON-NLS-1$ //$NON-NLS-2$
        }
        else
        {
            String pathId = "run." + conf.getName() + ".classpath"; //$NON-NLS-1$ //$NON-NLS-2$
            classpathRefElement.setAttribute("refid", pathId); //$NON-NLS-1$
            createClasspaths(pathId, project, runtimeClasspath);            
        }
        javaElement.appendChild(classpathRefElement);
    }
    
    /**
     * Add bootclasspath tag to given javaElement.
     */
    private void addRuntimeBootClasspath(ILaunchConfiguration conf, Element javaElement) throws JavaModelException
    {        
        // <bootclasspath>
        //     <path refid="hello.bootclasspath"/>
        //     <fileset dir="${java.home}/lib" includes="*.jar"/>
        // </bootclasspath>
        EclipseClasspath bootClasspath = new EclipseClasspath(project, conf, true);
        if (bootClasspath.rawClassPathEntries.size() > 0)
        {
            String pathId = "run." + conf.getName() + ".bootclasspath"; //$NON-NLS-1$ //$NON-NLS-2$
            createClasspaths(pathId, project, bootClasspath);
            Element bootclasspath = doc.createElement("bootclasspath"); //$NON-NLS-1$
            Element classpathRefElement = doc.createElement("path"); //$NON-NLS-1$
            classpathRefElement.setAttribute("refid", pathId); //$NON-NLS-1$
            bootclasspath.appendChild(classpathRefElement);
            Element jrelib = doc.createElement("fileset"); //$NON-NLS-1$
            jrelib.setAttribute("dir", "${java.home}/lib"); //$NON-NLS-1$ //$NON-NLS-2$
            jrelib.setAttribute("includes", "*.jar"); //$NON-NLS-1$ //$NON-NLS-2$
            bootclasspath.appendChild(jrelib);
            javaElement.appendChild(bootclasspath);
        }
    }

    /**
     * Create child node from <code>cmdLine</code> and add it to <code>element</code> which is part of
     * <code>doc</code>.
     * 
     * @param cmdLineArgs          command line arguments, separated with spaces or within double quotes, may also contain Eclipse variables 
     * @param doc                  XML document
     * @param element              node to add child to
     * @param elementName          name of new child node
     * @param attributeName        name of attribute for child node
     * @param variable2valueMap    adds Eclipse variables to this map,
     *                             if command line makes use of this feature
     */
    private static void addElement(String cmdLineArgs, Document doc,
            Element element, String elementName, String attributeName,
            Map variable2valueMap, String projectRoot) {

        if (cmdLineArgs == null || cmdLineArgs.length() == 0) {
            return;
        }
        ExportUtil.addVariable(variable2valueMap, cmdLineArgs, projectRoot);
        Element itemElement = doc.createElement(elementName);
        itemElement.setAttribute(attributeName, cmdLineArgs);
        element.appendChild(itemElement);            
    }
    
    /**
     * Create child nodes from string map and add them to <code>element</code> which is part of
     * <code>doc</code>.
     * 
     * @param map                   key/value string pairs
     * @param doc                   XML document
     * @param element               node to add children to
     * @param elementName           name of new child node
     * @param keyAttributeName      name of key attribute
     * @param valueAttributeName    name of value attribute
     */
    private static void addElements(Map map, Document doc, Element element, String elementName,
                                    String keyAttributeName, String valueAttributeName)
    {
        for (Iterator iter = map.keySet().iterator(); iter.hasNext();)
        {
            String key = (String) iter.next();
            String value = (String) map.get(key);
            Element itemElement = doc.createElement(elementName);
            itemElement.setAttribute(keyAttributeName, key);
            itemElement.setAttribute(valueAttributeName, value);
            element.appendChild(itemElement);            
        }
    }
    
    /**
     * Set config options.
     * @param buildfilename name for Ant buildfile
     * @param junitdir name of JUnit output directory
     * @param checkcycles check project for Ant compatibility
     * @param eclipsecompiler generate target for compiling project with Eclipse compiler
     */
    public static void setOptions(String buildfilename, String junitdir,
            boolean checkcycles, boolean eclipsecompiler) {

        if (buildfilename.length() > 0) {
            BUILD_XML = buildfilename;
        }
        if (junitdir.length() > 0) {
            JUNIT_OUTPUT_DIR = junitdir;
        }
        CHECK_SOURCE_CYCLES = checkcycles;
        CREATE_ECLIPSE_COMPILE_TARGET = eclipsecompiler;
    }
}