/*******************************************************************************
 * 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 = new FilenameFilter() {
			@Override
			public boolean accept(File acceptDir, String name) {
				return 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;
	}
}