/*******************************************************************************
 * 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 (Iterator<IJavaProject> iter = projects.iterator(); iter.hasNext();) {
			IJavaProject currentProject = iter.next();
			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.size() == 0) {
			debuglevel.add("none"); //$NON-NLS-1$
		}
		variable2valueMap.put("debuglevel", ExportUtil.toString(debuglevel, ",")); //$NON-NLS-1$ //$NON-NLS-2$

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

		// "Compiler compliance level"
		// String compliance = project.getOption(JavaCore.COMPILER_COMPLIANCE, true);

		// "Source compatibility"
		String sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true);
		variable2valueMap.put("source", sourceLevel); //$NON-NLS-1$

		// <property name="x" value="y"/>
		boolean first = true;
		Node node = root.getFirstChild();
		for (Iterator<String> iterator = variable2valueMap.keySet().iterator(); iterator.hasNext();) {
			String key = iterator.next();
			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 (int i = 0; i < files.length; i++) {
			// import file if it is an XML document with marker comment as first
			// child
			File file = files[i];
			Document docCandidate;
			try {
				docCandidate = ExportUtil.parseXmlFile(file);
				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 (Iterator<String> iter = ExportUtil.removeDuplicates(classpath.rawClassPathEntries).iterator(); iter.hasNext();) {
			String entry = iter.next();
			if (EclipseClasspath.isProjectReference(entry)) {
				Element pathElement = doc.createElement("path"); //$NON-NLS-1$
				IJavaProject referencedProject = EclipseClasspath.resolveProjectReference(entry);
				if (referencedProject == null) {
					AntUIPlugin.log("project is not loaded in workspace: " + pathid, null); //$NON-NLS-1$
					continue;
				}
				String refPathId = referencedProject.getProject().getName() + ".classpath"; //$NON-NLS-1$
				pathElement.setAttribute("refid", refPathId); //$NON-NLS-1$
				element.appendChild(pathElement);
				if (visited.add(refPathId)) {
					createClasspaths(null, referencedProject, new EclipseClasspath(referencedProject)); // recursion
				}
			} else if (EclipseClasspath.isUserLibraryReference(entry) || EclipseClasspath.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$
			IClasspathEntry entries[] = container.getClasspathEntries();
			for (int i = 0; i < entries.length; i++) {
				String jarFile = entries[i].getPath().toString();
				// use ECLIPSE_HOME variable for library jars
				if (EclipseClasspath.isLibraryReference(entry)) {
					IPath home = JavaCore.getClasspathVariable("ECLIPSE_HOME"); //$NON-NLS-1$
					if (home != null && home.isPrefixOf(entries[i].getPath())) {
						variable2valueMap.put("ECLIPSE_HOME", home.toString()); //$NON-NLS-1$
						jarFile = "${ECLIPSE_HOME}" + jarFile.substring(home.toString().length()); //$NON-NLS-1$
					} else if (!new File(jarFile).exists() && jarFile.startsWith('/' + projectName)
							&& new File(projectRoot, jarFile.substring(('/' + projectName).length())).exists()) {
						// workaround that additional jars are stored with
						// leading project root in container object, although
						// they are relative and indeed correctly stored in
						// build.properties (jars.extra.classpath)
						jarFile = jarFile.substring(('/' + projectName).length() + 1);
					}
				}
				jarFile = ExportUtil.getRelativePath(jarFile, projectRoot);
				Element userPathElement = doc.createElement("pathelement"); //$NON-NLS-1$
				userPathElement.setAttribute(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 (Iterator<IJavaProject> iterator = ExportUtil.getClasspathProjectsRecursive(subproject).iterator(); iterator.hasNext();) {
			IJavaProject subProject = iterator.next();
			String location = subProject.getProject().getName() + ".location"; //$NON-NLS-1$
			// add subproject properties to variable2valueMap
			String subProjectRoot = ExportUtil.getProjectRoot(subProject);
			String relativePath = ExportUtil.getRelativePath(subProjectRoot, projectRoot);
			variable2valueMap.put(location, relativePath);
			variable2valueMap.putAll(classpath.variable2valueMap);
		}
	}

	/**
	 * Create init target. Creates directories and copies resources.
	 * 
	 * @param srcDirs
	 *            source directories to copy resources from
	 * @param classDirs
	 *            classes directories to copy resources to
	 */
	public void createInit(List<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$
		List<String> classDirsUnique = ExportUtil.removeDuplicates(classDirs);
		for (Iterator<String> iterator = classDirsUnique.iterator(); iterator.hasNext();) {
			String classDir = iterator.next();
			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$
		List<String> classDirUnique = ExportUtil.removeDuplicates(classDirs);
		for (Iterator<String> iterator = classDirUnique.iterator(); iterator.hasNext();) {
			String classDir = iterator.next();
			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$
		List<IJavaProject> subProjects = ExportUtil.getClasspathProjectsRecursive(project);
		for (Iterator<IJavaProject> iterator = subProjects.iterator(); iterator.hasNext();) {
			IJavaProject subProject = iterator.next();
			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$
		List<IJavaProject> subProjects = ExportUtil.getClasspathProjectsRecursive(project);
		for (Iterator<IJavaProject> iterator = subProjects.iterator(); iterator.hasNext();) {
			IJavaProject subProject = iterator.next();
			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());
		IJavaProject[] projects = project.getJavaModel().getJavaProjects();
		for (int i = 0; i < projects.length; i++) {
			List<IJavaProject> subProjects = ExportUtil.getClasspathProjects(projects[i]);
			for (Iterator<IJavaProject> iter = subProjects.iterator(); iter.hasNext();) {
				IJavaProject p = iter.next();
				if (projectName.equals(p.getProject().getName())) {
					refProjects.add(projects[i]);
				}
			}
		}

		// <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 (Iterator<IJavaProject> iter = refProjects.iterator(); iter.hasNext();) {
			IJavaProject p = iter.next();
			String location = p.getProject().getName() + ".location"; //$NON-NLS-1$
			String refProjectRoot = ExportUtil.getProjectRoot(p);
			String relativePath = ExportUtil.getRelativePath(refProjectRoot, projectRoot);
			variable2valueMap.put(location, relativePath);

			Element antElement = doc.createElement("ant"); //$NON-NLS-1$
			antElement.setAttribute("antfile", 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 (Iterator<String> iter = srcDirs.iterator(); iter.hasNext();) {
			String entry = iter.next();
			if (EclipseClasspath.isUserSystemLibraryReference(entry)) {
				Element pathElement = doc.createElement("path"); //$NON-NLS-1$
				pathElement.setAttribute("refid", ExportUtil.removePrefixAndSuffix(entry, "${", "}")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				bootclasspathElement.appendChild(pathElement);
				bootclasspathUsed = true;
			} 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>
		ILaunchConfiguration[] confs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations();
		boolean junitUsed = false;
		for (int i = 0; i < confs.length; i++) {
			ILaunchConfiguration conf = confs[i];
			if (!projectName.equals(conf.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, 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<String, String>());
		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 (Iterator<IType> iter = sortedTypes.iterator(); iter.hasNext();) {
				IType type = iter.next();
				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<String, String>());
		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 (Iterator<String> iter = map.keySet().iterator(); iter.hasNext();) {
			String key = iter.next();
			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;
	}
}