/*******************************************************************************
 * Copyright (c) 2004, 2017 Richard Hoefter and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Contributors:
 *     Richard Hoefter (richard.hoefter@web.de) - initial API and implementation, bug 95297, bug 97051, bug 128103, bug 201180, bug 161354, bug 313386
 *     IBM Corporation - nlsing and incorporating into Eclipse, bug 108276, bug 124210, bug 161845, bug 177833
 *     Nikolay Metchev (N.Metchev@teamphone.com) - bug 108276
 *     Ryan Fong (rfong@trapezenetworks.com) - bug 201143
 *******************************************************************************/

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.HashMap;
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.core.IAntCoreConstants;
import org.eclipse.ant.internal.ui.AntUIPlugin;
import org.eclipse.ant.internal.ui.model.IAntModelConstants;
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.runtime.SubMonitor;
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.jdt.launching.JavaRuntime;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.osgi.util.NLS;
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.NodeList;
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<String, String> variable2valueMap;
	private Shell shell;
	private Set<String> visited = new TreeSet<>(); // record used subclasspaths
	private Node classpathNode;

	/**
	 * 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<String> createBuildFiles(Set<IJavaProject> projects, Shell shell, IProgressMonitor pm) throws JavaModelException, ParserConfigurationException, TransformerConfigurationException, TransformerException, IOException, CoreException, InterruptedException {
		List<String> res = new ArrayList<>();
		try {
			createBuildFilesLoop(projects, shell, pm, res);
		}
		finally {
			if (pm != null) {
				pm.done();
			}
		}
		return res;
	}

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

		// determine files to create/change
		List<IFile> files = new ArrayList<>();
		for (IJavaProject currentProject : projects) {
			IFile file = currentProject.getProject().getFile(BuildFileCreator.BUILD_XML);
			files.add(file);
		}

		// trigger checkout
		Set<IFile> confirmedFiles = ExportUtil.validateEdit(shell, files);
		SubMonitor localmonitor = SubMonitor.convert(pm, DataTransferMessages.AntBuildfileExportPage_0, confirmedFiles.size());
		try {
			Iterator<IJavaProject> iter = projects.iterator();
			while (iter.hasNext()) {
				IJavaProject currentProject = iter.next();
				IFile file = currentProject.getProject().getFile(BuildFileCreator.BUILD_XML);
				if (!confirmedFiles.contains(file)) {
					continue;
				}

				localmonitor.setTaskName(NLS.bind(DataTransferMessages.BuildFileCreator_generating_buildfile_for, 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, classpath.inclusionLists, classpath.exclusionLists);
				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 (localmonitor.isCanceled()) {
					return;
				}
				localmonitor.worked(1);
				res.add(instance.projectName);
			}
		}
		finally {
			if (!localmonitor.isCanceled()) {
				localmonitor.done();
			}
		}
	}

	/**
	 * 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<String> 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.isEmpty()) {
			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 (String key : variable2valueMap.keySet()) {
			String value = variable2valueMap.get(key);
			Element prop = doc.createElement("property"); //$NON-NLS-1$
			prop.setAttribute(IAntCoreConstants.NAME, key);
			prop.setAttribute(IAntCoreConstants.VALUE, value);
			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(IAntCoreConstants.NAME, projectName);
		root.setAttribute(IAntCoreConstants.DEFAULT, "build"); //$NON-NLS-1$
		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 = (acceptDir, name) -> name.endsWith(".xml"); //$NON-NLS-1$

		File[] files = dir.listFiles(filter);
		if (files == null) {
			return;
		}
		for (File file : files) {
			// import file if it is an XML document with marker comment as first
			// child
			Document docCandidate;
			try {
				docCandidate = ExportUtil.parseXmlFile(file);
				NodeList nodes = docCandidate.getChildNodes();
				for (int j = 0; j < nodes.getLength(); j++) {
					Node node = nodes.item(j);
					if (node instanceof ProcessingInstruction
							&& IMPORT_BUILDFILE_PROCESSING_TARGET.equals(((ProcessingInstruction) node).getTarget().trim())) {
						Element element = doc.createElement("import"); //$NON-NLS-1$
						element.setAttribute(IAntCoreConstants.FILE, file.getName());
						root.appendChild(element);
						break;
					}
				}
			}
			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$
		String pathid = pathId;
		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 (String entry : ExportUtil.removeDuplicates(classpath.rawClassPathEntries)) {
			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.isLibraryReference(entry)) {
				addUserLibrary(element, entry);
			} else if (EclipseClasspath.isUserSystemLibraryReference(entry)) {
				if (pathid.endsWith(".bootclasspath")) { //$NON-NLS-1$
					addUserLibrary(element, entry);
				}
			} else if (EclipseClasspath.isJreReference(entry)) {
				if (pathid.endsWith(".bootclasspath")) { //$NON-NLS-1$
					addJre(element);
				}
			} else {
				// prefix with ${project.location}
				String prefix = IAntCoreConstants.EMPTY_STRING;
				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(IAntModelConstants.ATTR_LOCATION, path);
				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$
		element.appendChild(pathElement);

		// add classpath
		if (visited.add(entry)) {
			Element userElement = doc.createElement("path"); //$NON-NLS-1$
			userElement.setAttribute("id", name); //$NON-NLS-1$
			for (IClasspathEntry cpentry : container.getClasspathEntries()) {
				String jarFile = cpentry.getPath().toString();
				// use ECLIPSE_HOME variable for library jars
				if (EclipseClasspath.isLibraryReference(entry)) {
					IPath home = JavaCore.getClasspathVariable("ECLIPSE_HOME"); //$NON-NLS-1$
					if (home != null && home.isPrefixOf(cpentry.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(IAntModelConstants.ATTR_LOCATION, jarFile);
				userElement.appendChild(userPathElement);
			}
			addToClasspathBlock(userElement);
		}
	}

	/**
	 * Add JRE to given classpath.
	 * 
	 * @param element
	 *            classpath tag
	 */
	private void addJre(Element element) {
		// <fileset dir="${java.home}/lib" includes="*.jar"/>
		// <fileset dir="${java.home}/lib/ext" includes="*.jar"/>
		Element pathElement = doc.createElement("fileset"); //$NON-NLS-1$
		pathElement.setAttribute(IAntCoreConstants.DIR, "${java.home}/lib"); //$NON-NLS-1$
		pathElement.setAttribute("includes", "*.jar"); //$NON-NLS-1$ //$NON-NLS-2$
		element.appendChild(pathElement);
		pathElement = doc.createElement("fileset"); //$NON-NLS-1$
		pathElement.setAttribute(IAntCoreConstants.DIR, "${java.home}/lib/ext"); //$NON-NLS-1$
		pathElement.setAttribute("includes", "*.jar"); //$NON-NLS-1$ //$NON-NLS-2$
		element.appendChild(pathElement);
	}

	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 sub-projects to internal properties map.
	 */
	public void addSubProperties(IJavaProject subproject, EclipseClasspath classpath) throws JavaModelException {
		for (IJavaProject subProject : ExportUtil.getClasspathProjectsRecursive(subproject)) {
			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<String> srcDirs, List<String> classDirs, List<List<String>> inclusionLists, List<List<String>> exclusionLists) {
		// <target name="init">
		// <mkdir dir="classes"/>
		// </target>
		Element element = doc.createElement("target"); //$NON-NLS-1$
		element.setAttribute(IAntCoreConstants.NAME, "init"); //$NON-NLS-1$
		for (String classDir : ExportUtil.removeDuplicates(classDirs)) {
			if (!classDir.equals(".") && !EclipseClasspath.isReference(classDir)) { //$NON-NLS-1$
				Element pathElement = doc.createElement("mkdir"); //$NON-NLS-1$
				pathElement.setAttribute(IAntCoreConstants.DIR, classDir);
				element.appendChild(pathElement);
			}
		}
		root.appendChild(element);
		createCopyResources(srcDirs, classDirs, element, inclusionLists, exclusionLists);
	}

	private void createCopyResources(List<String> srcDirs, List<String> classDirs, Element element, List<List<String>> inclusionLists, List<List<String>> exclusionLists) {
		// 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$
		ArrayList<String> filters = new ArrayList<>();
		while (tokenizer.hasMoreTokens()) {
			filters.add(tokenizer.nextToken());
		}
		filters.add("*.java"); //$NON-NLS-1$

		// prefix filters with wildcard
		for (int i = 0; i < filters.size(); i++) {
			String item = 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 = srcDirs.get(i);
			String classDir = 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(IAntCoreConstants.DIR, srcDir);

				List<String> inclusions = inclusionLists.get(i);
				List<String> exclusions = exclusionLists.get(i);

				for (String inclusion : inclusions) {
					Element includeElement = doc.createElement("include"); //$NON-NLS-1$
					includeElement.setAttribute(IAntCoreConstants.NAME, inclusion);
					filesetElement.appendChild(includeElement);
				}
				for (String exclusion : filters) {
					Element excludeElement = doc.createElement("exclude"); //$NON-NLS-1$
					excludeElement.setAttribute(IAntCoreConstants.NAME, exclusion);
					filesetElement.appendChild(excludeElement);
				}

				for (String exclusion : exclusions) {
					Element excludeElement = doc.createElement("exclude"); //$NON-NLS-1$
					excludeElement.setAttribute(IAntCoreConstants.NAME, exclusion);
					filesetElement.appendChild(excludeElement);
				}

				copyElement.appendChild(filesetElement);
				element.appendChild(copyElement);
			}
		}
	}

	/**
	 * Create clean target.
	 * 
	 * @param classDirs
	 *            classes directories to delete
	 */
	public void createClean(List<String> classDirs) {
		// <target name="clean">
		// <delete dir="classes"/>
		// </target>
		Element element = doc.createElement("target"); //$NON-NLS-1$
		element.setAttribute(IAntCoreConstants.NAME, "clean"); //$NON-NLS-1$
		for (String classDir : ExportUtil.removeDuplicates(classDirs)) {
			if (!classDir.equals(".") && //$NON-NLS-1$
					!EclipseClasspath.isReference(classDir)) {
				Element deleteElement = doc.createElement("delete"); //$NON-NLS-1$
				deleteElement.setAttribute(IAntCoreConstants.DIR, classDir);
				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(IAntCoreConstants.DIR, "."); //$NON-NLS-1$
			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="build.xml" dir="${hello.location}" inheritAll="false" target="clean"/>
		// </target>
		Element element = doc.createElement("target"); //$NON-NLS-1$
		element.setAttribute(IAntCoreConstants.NAME, "cleanall"); //$NON-NLS-1$
		element.setAttribute("depends", "clean"); //$NON-NLS-1$ //$NON-NLS-2$
		for (IJavaProject subProject : ExportUtil.getClasspathProjectsRecursive(project)) {
			Element antElement = doc.createElement("ant"); //$NON-NLS-1$
			antElement.setAttribute("antfile", BUILD_XML); //$NON-NLS-1$
			antElement.setAttribute(IAntCoreConstants.DIR, "${" + subProject.getProject().getName() + ".location}"); //$NON-NLS-1$ //$NON-NLS-2$
			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<String> srcDirs, List<String> classDirs, List<List<String>> inclusionLists, List<List<String>> exclusionLists) throws JavaModelException {
		// <target name="build" depends="build-subprojects,build-project"/>
		Element element = doc.createElement("target"); //$NON-NLS-1$
		element.setAttribute(IAntCoreConstants.NAME, "build"); //$NON-NLS-1$
		element.setAttribute("depends", "build-subprojects,build-project"); //$NON-NLS-1$ //$NON-NLS-2$
		root.appendChild(element);

		// <target name="build-subprojects">
		// <ant antfile="build.xml" dir="${hello.location}" inheritAll="false" target="build-project"/>
		// </target>
		element = doc.createElement("target"); //$NON-NLS-1$
		element.setAttribute(IAntCoreConstants.NAME, "build-subprojects"); //$NON-NLS-1$
		for (IJavaProject subProject : ExportUtil.getClasspathProjectsRecursive(project)) {
			Element antElement = doc.createElement("ant"); //$NON-NLS-1$
			antElement.setAttribute("antfile", BUILD_XML); //$NON-NLS-1$
			antElement.setAttribute(IAntCoreConstants.DIR, "${" + subProject.getProject().getName() + ".location}"); //$NON-NLS-1$ //$NON-NLS-2$
			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(IAntCoreConstants.NAME, "build.compiler"); //$NON-NLS-1$
				propertysetElement.appendChild(propertyrefElement);
				antElement.appendChild(propertysetElement);
			}
			element.appendChild(antElement);
		}
		root.appendChild(element);

		// Bug 313386 optimization:
		// Source directories with the same classes directory get only one <javac> tag
		// Side effect: Eclipse inclusion and exclusion filters apply to the specified source directory.
		// Ant inclusion and exclusion filters apply to all source directories.
		// This may lead to unexpected behavior.
		HashMap<String, List<String>> class2sources = new HashMap<>();
		HashMap<String, List<String>> class2includes = new HashMap<>();
		HashMap<String, List<String>> class2excludes = new HashMap<>();
		for (int i = 0; i < srcDirs.size(); i++) {
			String srcDir = srcDirs.get(i);
			if (!EclipseClasspath.isReference(srcDir)) {
				String classDir = classDirs.get(i);
				List<String> inclusions = inclusionLists.get(i);
				List<String> exclusions = exclusionLists.get(i);
				List<String> list = class2sources.get(classDir);
				List<String> list2 = class2includes.get(classDir);
				List<String> list3 = class2excludes.get(classDir);
				if (list == null) {
					list = new ArrayList<>();
					list2 = new ArrayList<>();
					list3 = new ArrayList<>();
					class2sources.put(classDir, list);
					class2includes.put(classDir, list2);
					class2excludes.put(classDir, list3);
				}
				list.add(srcDir);
				list2.addAll(inclusions);
				list3.addAll(exclusions);
			}
		}

		// <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(IAntCoreConstants.NAME, "build-project"); //$NON-NLS-1$
		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 = srcDirs.get(i);
			if (!EclipseClasspath.isReference(srcDir)) {
				String classDir = classDirs.get(i);
				List<String> sources = class2sources.get(classDir);
				List<String> inclusions = class2includes.get(classDir);
				List<String> exclusions = class2excludes.get(classDir);
				if (sources != null && sources.size() > 1) {
					// remove list to exclude it from the next iteration
					class2sources.put(classDir, null);
				} else if (sources == null) {
					continue;
				}

				Element javacElement = doc.createElement("javac"); //$NON-NLS-1$
				javacElement.setAttribute("includeantruntime", "false"); //$NON-NLS-1$ //$NON-NLS-2$
				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$

				// Bug 313386: <javac> tag with several source directories
				for (String s : sources) {
					Element srcElement = doc.createElement("src"); //$NON-NLS-1$
					srcElement.setAttribute("path", s); //$NON-NLS-1$
					javacElement.appendChild(srcElement);
				}
				for (String inclusion : inclusions) {
					Element includeElement = doc.createElement("include"); //$NON-NLS-1$
					includeElement.setAttribute(IAntCoreConstants.NAME, inclusion);
					javacElement.appendChild(includeElement);
				}
				for (String exclusion : exclusions) {
					Element excludeElement = doc.createElement("exclude"); //$NON-NLS-1$
					excludeElement.setAttribute(IAntCoreConstants.NAME, exclusion);
					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);
				if (!JavaRuntime.isModularProject(project))
					addCompilerBootClasspath(srcDirs, javacElement);
			}
		}
		root.appendChild(element);
	}

	/**
	 * Create target build-refprojects which compiles projects which reference current project.
	 */
	private void createBuildRef() throws JavaModelException {
		Set<IJavaProject> refProjects = new TreeSet<>(ExportUtil.getJavaProjectComparator());
		for (IJavaProject javaProject : project.getJavaModel().getJavaProjects()) {
			for (IJavaProject subProject : ExportUtil.getClasspathProjects(javaProject)) {
				if (projectName.equals(subProject.getProject().getName())) {
					refProjects.add(javaProject);
				}
			}
		}

		// <target name="build-refprojects">
		// <ant antfile="build.xml" dir="${hello.location}" target="clean" inheritAll="false"/>
		// <ant antfile="build.xml" dir="${hello.location}" target="build" inheritAll="false"/>
		// </target>
		Element element = doc.createElement("target"); //$NON-NLS-1$
		element.setAttribute(IAntCoreConstants.NAME, "build-refprojects"); //$NON-NLS-1$
		element.setAttribute(IAntCoreConstants.DESCRIPTION, "Build all projects which " + //$NON-NLS-1$
				"reference this project. Useful to propagate changes."); //$NON-NLS-1$
		for (IJavaProject p : refProjects) {
			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", BUILD_XML); //$NON-NLS-1$
			antElement.setAttribute(IAntCoreConstants.DIR, "${" + p.getProject().getName() + ".location}"); //$NON-NLS-1$ //$NON-NLS-2$
			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", BUILD_XML); //$NON-NLS-1$
			antElement.setAttribute(IAntCoreConstants.DIR, "${" + p.getProject().getName() + ".location}"); //$NON-NLS-1$ //$NON-NLS-2$
			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(IAntCoreConstants.NAME, "build.compiler"); //$NON-NLS-1$
				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$
		if (value != null) {
			variable2valueMap.put("ECLIPSE_HOME", ExportUtil.getRelativePath( //$NON-NLS-1$
					value.toString(), projectRoot));
		}
		// <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(IAntCoreConstants.NAME, "init-eclipse-compiler"); //$NON-NLS-1$
		element.setAttribute(IAntCoreConstants.DESCRIPTION, "copy Eclipse compiler jars to ant lib directory"); //$NON-NLS-1$
		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(IAntCoreConstants.DIR, "${ECLIPSE_HOME}/plugins"); //$NON-NLS-1$
		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(IAntCoreConstants.NAME, "build-eclipse-compiler"); //$NON-NLS-1$
		element.setAttribute(IAntCoreConstants.DESCRIPTION, "compile project with Eclipse compiler"); //$NON-NLS-1$
		Element propertyElement = doc.createElement("property"); //$NON-NLS-1$
		propertyElement.setAttribute(IAntCoreConstants.NAME, "build.compiler"); //$NON-NLS-1$
		propertyElement.setAttribute(IAntCoreConstants.VALUE, "org.eclipse.jdt.core.JDTCompilerAdapter"); //$NON-NLS-1$
		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 all bootclasspaths in srcDirs to given javacElement.
	 */
	private void addCompilerBootClasspath(List<String> srcDirs, Element javacElement) {
		// <bootclasspath>
		// <path refid="mylib.bootclasspath"/>
		// <fileset dir="${java.home}/lib" includes="*.jar"/>
		// <fileset dir="${java.home}/lib/ext" includes="*.jar"/>
		// </bootclasspath>
		Element bootclasspathElement = doc.createElement("bootclasspath"); //$NON-NLS-1$
		boolean bootclasspathUsed = false;
		for (String entry : srcDirs) {
			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;
			} else if (EclipseClasspath.isJreReference(entry)) {
				addJre(bootclasspathElement);
			}
		}
		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>
		boolean junitUsed = false;
		for (ILaunchConfiguration conf : DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations()) {
			if (!projectName.equals(conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, IAntCoreConstants.EMPTY_STRING))) {
				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<String, String> variable2value, ILaunchConfiguration conf) throws CoreException {
		Element element = doc.createElement("target"); //$NON-NLS-1$
		element.setAttribute(IAntCoreConstants.NAME, conf.getName());
		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, IAntCoreConstants.EMPTY_STRING)); //$NON-NLS-1$
		javaElement.setAttribute("failonerror", "true"); //$NON-NLS-1$ //$NON-NLS-2$
		String dir = conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, IAntCoreConstants.EMPTY_STRING);
		ExportUtil.addVariable(variable2value, dir, projectRoot);
		if (!dir.equals(IAntCoreConstants.EMPTY_STRING)) {
			javaElement.setAttribute(IAntCoreConstants.DIR, ExportUtil.getRelativePath(dir, projectRoot));
		}
		if (!conf.getAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, true)) {
			javaElement.setAttribute("newenvironment", "true"); //$NON-NLS-1$ //$NON-NLS-2$
		}
		Map<String, String> props = conf.getAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, new TreeMap<>());
		addElements(props, doc, javaElement, "env", "key", IAntCoreConstants.VALUE); //$NON-NLS-1$ //$NON-NLS-2$
		addElement(conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, IAntCoreConstants.EMPTY_STRING), doc, javaElement, "jvmarg", "line", variable2value, projectRoot); //$NON-NLS-1$ //$NON-NLS-2$
		addElement(conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, IAntCoreConstants.EMPTY_STRING), doc, javaElement, "arg", "line", variable2value, projectRoot); //$NON-NLS-1$ //$NON-NLS-2$
		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<String, String> variable2value, ILaunchConfiguration conf) throws CoreException, TransformerFactoryConfigurationError, UnsupportedEncodingException {
		String dir = conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, IAntCoreConstants.EMPTY_STRING);
		if (dir.equals(IAntCoreConstants.EMPTY_STRING)) {
			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)
				&& !MessageDialog.openConfirm(shell, DataTransferMessages.AntBuildfileExportPage_4, DataTransferMessages.AntBuildfileExportPage_4
						+ ": " + htmlfile)) //$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(IAntCoreConstants.NAME, conf.getName());
		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(IAntCoreConstants.DIR, ExportUtil.getRelativePath(dir, projectRoot));
		}
		addElement(conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, IAntCoreConstants.EMPTY_STRING), doc, javaElement, "jvmarg", "line", variable2value, projectRoot); //$NON-NLS-1$//$NON-NLS-2$
		addElement(conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, IAntCoreConstants.EMPTY_STRING), doc, javaElement, "arg", "line", variable2value, projectRoot); //$NON-NLS-1$//$NON-NLS-2$
		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<String, String> 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, IAntCoreConstants.EMPTY_STRING);
		Element element = doc.createElement("target"); //$NON-NLS-1$
		element.setAttribute(IAntCoreConstants.NAME, conf.getName());

		Element mkdirElement = doc.createElement("mkdir"); //$NON-NLS-1$
		mkdirElement.setAttribute(IAntCoreConstants.DIR, "${junit.output.dir}"); //$NON-NLS-1$
		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, IAntCoreConstants.EMPTY_STRING);
		ExportUtil.addVariable(variable2value, dir, projectRoot);
		if (!dir.equals(IAntCoreConstants.EMPTY_STRING)) {
			junitElement.setAttribute(IAntCoreConstants.DIR, ExportUtil.getRelativePath(dir, projectRoot));
		}
		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(IAntCoreConstants.EMPTY_STRING)) {
			// Case 1: Single JUnit class
			Element testElement = doc.createElement("test"); //$NON-NLS-1$
			testElement.setAttribute(IAntCoreConstants.NAME, testClass);
			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 */, IAntCoreConstants.EMPTY_STRING); //$NON-NLS-1$
			IType[] types = ExportUtil.findTestsInContainer(container);
			Set<IType> sortedTypes = new TreeSet<>(ExportUtil.getITypeComparator());
			sortedTypes.addAll(Arrays.asList(types));
			for (IType type : sortedTypes) {
				Element testElement = doc.createElement("test"); //$NON-NLS-1$
				testElement.setAttribute(IAntCoreConstants.NAME, type.getFullyQualifiedName());
				testElement.setAttribute("todir", "${junit.output.dir}"); //$NON-NLS-1$ //$NON-NLS-2$
				junitElement.appendChild(testElement);
			}
		}
		Map<String, String> props = conf.getAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, new TreeMap<>());
		addElements(props, doc, junitElement, "env", "key", IAntCoreConstants.VALUE); //$NON-NLS-1$ //$NON-NLS-2$
		addElement(conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, IAntCoreConstants.EMPTY_STRING), doc, junitElement, "jvmarg", "line", variable2value, projectRoot); //$NON-NLS-1$ //$NON-NLS-2$
		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(IAntCoreConstants.NAME, "junitreport"); //$NON-NLS-1$
		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(IAntCoreConstants.DIR, "${junit.output.dir}"); //$NON-NLS-1$
		junitreport.appendChild(fileset);
		Element include = doc.createElement("include"); //$NON-NLS-1$
		include.setAttribute(IAntCoreConstants.NAME, "TEST-*.xml"); //$NON-NLS-1$
		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 CoreException {
		// <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 CoreException {
		// <bootclasspath>
		// <path refid="run.hello.bootclasspath"/>
		// </bootclasspath>
		if (JavaRuntime.isModularConfiguration(conf)) {
			// there is no bootclasspath entry from Java 9 onwards
			return;
		}
		EclipseClasspath bootClasspath = new EclipseClasspath(project, conf, true);
		if (bootClasspath.rawClassPathEntries.size() == 1 && EclipseClasspath.isJreReference(bootClasspath.rawClassPathEntries.get(0))) {
			// the default boot classpath contains exactly one element (the JRE)
			return;
		}

		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);
		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<String, String> 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<String, String> map, Document doc, Element element, String elementName, String keyAttributeName, String valueAttributeName) {
		for (String key : map.keySet()) {
			String value = 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;
	}
}