/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ant.internal.ui;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.apache.tools.ant.Target;
import org.eclipse.ant.core.AntCorePlugin;
import org.eclipse.ant.internal.core.AntCoreUtil;
import org.eclipse.ant.internal.core.IAntCoreConstants;
import org.eclipse.ant.internal.launching.AntLaunchingUtil;
import org.eclipse.ant.internal.ui.editor.AntEditor;
import org.eclipse.ant.internal.ui.model.AntElementNode;
import org.eclipse.ant.internal.ui.model.AntModel;
import org.eclipse.ant.internal.ui.model.AntProjectNode;
import org.eclipse.ant.internal.ui.model.AntTargetNode;
import org.eclipse.ant.internal.ui.model.IAntElement;
import org.eclipse.ant.internal.ui.model.IAntModel;
import org.eclipse.ant.internal.ui.model.LocationProvider;
import org.eclipse.ant.launching.IAntLaunchConstants;
import org.eclipse.core.externaltools.internal.IExternalToolConstants;
import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.filebuffers.LocationKind;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.ui.console.FileLink;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.swt.SWT;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWebBrowser;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
import org.eclipse.ui.console.IHyperlink;
import org.eclipse.ui.externaltools.internal.launchConfigurations.ExternalToolsUtil;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;

import com.ibm.icu.text.MessageFormat;

/**
 * General utility class dealing with Ant build files
 */
public final class AntUtil {
	public static final String ATTRIBUTE_SEPARATOR = ","; //$NON-NLS-1$ ;
	public static final char ANT_CLASSPATH_DELIMITER = '*';
	public static final String ANT_HOME_CLASSPATH_PLACEHOLDER = "G"; //$NON-NLS-1$
	public static final String ANT_GLOBAL_USER_CLASSPATH_PLACEHOLDER = "UG"; //$NON-NLS-1$
	private static String fgBrowserId;

	/**
	 * No instances allowed
	 */
	private AntUtil() {
		super();
	}

	/**
	 * Returns a single-string of the strings for storage.
	 * 
	 * @param strings
	 *            the array of strings
	 * @return a single-string representation of the strings or <code>null</code> if the array is empty.
	 */
	public static String combineStrings(String[] strings) {
		return AntLaunchingUtil.combineStrings(strings);
	}

	/**
	 * Returns an array of targets to be run, or <code>null</code> if none are specified (indicating the default target or implicit target should be
	 * run).
	 * 
	 * @param configuration
	 *            launch configuration
	 * @return array of target names, or <code>null</code>
	 * @throws CoreException
	 *             if unable to access the associated attribute
	 */
	public static String[] getTargetNames(ILaunchConfiguration configuration) throws CoreException {
		return AntLaunchingUtil.getTargetNames(configuration);
	}

	/**
	 * Returns a map of properties to be defined for the build, or <code>null</code> if none are specified (indicating no additional properties
	 * specified for the build).
	 * 
	 * @param configuration
	 *            launch configuration
	 * @return map of properties (name --> value), or <code>null</code>
	 * @throws CoreException
	 *             if unable to access the associated attribute
	 */
	public static Map<String, String> getProperties(ILaunchConfiguration configuration) throws CoreException {
		return AntLaunchingUtil.getProperties(configuration);
	}

	/**
	 * Returns a String specifying the Ant home to use for the build.
	 * 
	 * @param configuration
	 *            launch configuration
	 * @return String specifying Ant home to use or <code>null</code>
	 * @throws CoreException
	 *             if unable to access the associated attribute
	 */
	public static String getAntHome(ILaunchConfiguration configuration) throws CoreException {
		return AntLaunchingUtil.getAntHome(configuration);
	}

	/**
	 * Returns an array of property files to be used for the build, or <code>null</code> if none are specified (indicating no additional property
	 * files specified for the build).
	 * 
	 * @param configuration
	 *            launch configuration
	 * @return array of property file names, or <code>null</code>
	 * @throws CoreException
	 *             if unable to access the associated attribute
	 */
	public static String[] getPropertyFiles(ILaunchConfiguration configuration) throws CoreException {
		String attribute = configuration.getAttribute(IAntLaunchConstants.ATTR_ANT_PROPERTY_FILES, (String) null);
		if (attribute == null) {
			return null;
		}
		String[] propertyFiles = AntUtil.parseString(attribute, ","); //$NON-NLS-1$
		for (int i = 0; i < propertyFiles.length; i++) {
			String propertyFile = propertyFiles[i];
			propertyFile = expandVariableString(propertyFile, AntUIModelMessages.AntUtil_6);
			propertyFiles[i] = propertyFile;
		}
		return propertyFiles;
	}

	public static AntTargetNode[] getTargets(String path, ILaunchConfiguration config) throws CoreException {
		File buildfile = getBuildFile(path);
		if (buildfile == null) {
			return null;
		}
		URL[] urls = getCustomClasspath(config);
		// no lexical, no position, no task
		IAntModel model = getAntModel(buildfile, urls, false, false, false);
		try {
			model.setProperties(getAllProperties(config));
		}
		catch (CoreException ex) {
			// do nothing
		}
		model.setPropertyFiles(getPropertyFiles(config));
		AntProjectNode project = model.getProjectNode(); // forces a reconcile
		model.dispose();
		return getTargets(project);
	}

	private static Map<String, String> getAllProperties(ILaunchConfiguration config) throws CoreException {
		String allArgs = config.getAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS, (String) null);
		Map<String, String> properties = new HashMap<>();
		if (allArgs != null) {
			String[] arguments = ExternalToolsUtil.parseStringIntoList(allArgs);
			// filter arguments to avoid resolving variables that will prompt the user
			List<String> filtered = new ArrayList<>();
			Pattern pattern = Pattern.compile("\\$\\{.*_prompt.*\\}"); //$NON-NLS-1$
			IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager();
			for (int i = 0; i < arguments.length; i++) {
				String arg = arguments[i];
				if (arg.startsWith("-D")) { //$NON-NLS-1$
					if (!pattern.matcher(arg).find()) {
						filtered.add(manager.performStringSubstitution(arg, false));
					}
				}
			}
			AntCoreUtil.processMinusDProperties(filtered, properties);
		}
		Map<String, String> configProperties = getProperties(config);
		if (configProperties != null) {
			Iterator<String> keys = configProperties.keySet().iterator();
			while (keys.hasNext()) {
				String name = keys.next();
				if (properties.get(name) == null) {
					properties.put(name, configProperties.get(name));
				}
			}
		}
		return properties;
	}

	private static AntTargetNode[] getTargets(AntProjectNode project) {
		if (project == null || !project.hasChildren()) {
			return null;
		}
		List<IAntElement> targets = new ArrayList<>();
		for (IAntElement node : project.getChildNodes()) {
			if (node instanceof AntTargetNode) {
				targets.add(node);
			}
		}
		if (targets.size() == 0) {
			return null;
		}
		return targets.toArray(new AntTargetNode[targets.size()]);
	}

	public static AntTargetNode[] getTargets(String path) {
		File buildfile = getBuildFile(path);
		if (buildfile == null) {
			return null;
		}
		// tasks and position info but no lexical info
		IAntModel model = getAntModel(buildfile, null, false, true, true);
		AntProjectNode project = model.getProjectNode();
		if (project == null) {
			model.dispose();
			return null;
		}
		AntTargetNode[] targets = getTargets(project);
		if (targets == null) {
			Hashtable<String, Target> antTargets = project.getProject().getTargets();
			Target implicitTarget = antTargets.get(IAntCoreConstants.EMPTY_STRING);
			if (implicitTarget != null) {
				AntTargetNode implicitTargetNode = AntTargetNode.newAntTargetNode(implicitTarget);
				project.addChildNode(implicitTargetNode);
				return new AntTargetNode[] { implicitTargetNode };
			}
		}
		return targets;
	}

	public static IAntModel getAntModel(String buildFilePath, boolean needsLexicalResolution, boolean needsPositionResolution, boolean needsTaskResolution) {
		IAntModel model = getAntModel(getBuildFile(buildFilePath), null, needsLexicalResolution, needsPositionResolution, needsTaskResolution);
		return model;
	}

	/**
	 * Return a buildfile from the specified location. If there isn't one return null.
	 */
	private static File getBuildFile(String path) {
		File buildFile = new File(path);
		if (!buildFile.isFile() || !buildFile.exists()) {
			return null;
		}

		return buildFile;
	}

	private static IAntModel getAntModel(final File buildFile, URL[] urls, boolean needsLexical, boolean needsPosition, boolean needsTask) {
		if (buildFile == null || !buildFile.exists()) {
			return null;
		}
		IDocument doc = getDocument(buildFile);
		if (doc == null) {
			return null;
		}
		final IFile file = getFileForLocation(buildFile.getAbsolutePath(), null);
		LocationProvider provider = new LocationProvider(null) {
			/*
			 * (non-Javadoc)
			 * 
			 * @see org.eclipse.ant.internal.ui.model.LocationProvider#getFile()
			 */
			@Override
			public IFile getFile() {
				return file;
			}

			/*
			 * (non-Javadoc)
			 * 
			 * @see org.eclipse.ant.internal.ui.model.LocationProvider#getLocation()
			 */
			@Override
			public IPath getLocation() {
				if (file == null) {
					return new Path(buildFile.getAbsolutePath());
				}
				return file.getLocation();
			}
		};
		IAntModel model = new AntModel(doc, null, provider, needsLexical, needsPosition, needsTask);

		if (urls != null) {
			model.setClassLoader(AntCorePlugin.getPlugin().getNewClassLoader(urls));
		}
		return model;
	}

	private static IDocument getDocument(File buildFile) {
		ITextFileBufferManager manager = FileBuffers.getTextFileBufferManager();
		IPath location = new Path(buildFile.getAbsolutePath());
		boolean connected = false;
		try {
			ITextFileBuffer buffer = manager.getTextFileBuffer(location, LocationKind.NORMALIZE);
			if (buffer == null) {
				// no existing file buffer..create one
				manager.connect(location, LocationKind.NORMALIZE, new NullProgressMonitor());
				connected = true;
				buffer = manager.getTextFileBuffer(location, LocationKind.NORMALIZE);
				if (buffer == null) {
					return null;
				}
			}

			return buffer.getDocument();
		}
		catch (CoreException ce) {
			AntUIPlugin.log(ce.getStatus());
			return null;
		}
		finally {
			if (connected) {
				try {
					manager.disconnect(location, LocationKind.NORMALIZE, new NullProgressMonitor());
				}
				catch (CoreException e) {
					AntUIPlugin.log(e.getStatus());
				}
			}
		}
	}

	/**
	 * Returns the list of URLs that define the custom classpath for the Ant build, or <code>null</code> if the global classpath is to be used.
	 * 
	 * @param config
	 *            launch configuration
	 * @return a list of <code>URL</code>
	 * 
	 * @throws CoreException
	 *             if file does not exist, IO problems, or invalid format.
	 */
	public static URL[] getCustomClasspath(ILaunchConfiguration config) throws CoreException {
		return AntLaunchingUtil.getCustomClasspath(config);
	}

	private static String expandVariableString(String variableString, String invalidMessage) throws CoreException {
		String expandedString = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(variableString);
		if (expandedString == null || expandedString.length() == 0) {
			String msg = MessageFormat.format(invalidMessage, new Object[] { variableString });
			throw new CoreException(new Status(IStatus.ERROR, IAntUIConstants.PLUGIN_ID, 0, msg, null));
		}

		return expandedString;
	}

	/**
	 * Returns the list of target names to run
	 * 
	 * @param extraAttibuteValue
	 *            the external tool's extra attribute value for the run targets key.
	 * @return a list of target names
	 */
	public static String[] parseRunTargets(String extraAttibuteValue) {
		return AntLaunchingUtil.parseRunTargets(extraAttibuteValue);
	}

	/**
	 * Returns the list of Strings that were delimiter separated.
	 * 
	 * @param delimString
	 *            the String to be tokenized based on the delimiter
	 * @param delim
	 *            the delimiter
	 * @return a list of Strings
	 */
	public static String[] parseString(String delimString, String delim) {
		return AntLaunchingUtil.parseString(delimString, delim);
	}

	/**
	 * Returns an IFile with the given fully qualified path (relative to the workspace root). The returned IFile may or may not exist.
	 * 
	 * @param fullPath
	 *            the path to look up
	 * @return the {@link IFile} which may or may not exist
	 */
	public static IFile getFile(String fullPath) {
		return AntLaunchingUtil.getFile(fullPath);
	}

	public static IHyperlink getLocationLink(String path, File buildFileParent) {
		path = path.trim();
		if (path.length() == 0) {
			return null;
		}
		if (path.startsWith(IAntCoreConstants.FILE_PROTOCOL)) {
			// remove "file:"
			path = path.substring(5, path.length());
		}
		// format is file:F:L: where F is file path, and L is line number
		int index = path.lastIndexOf(':');
		if (index == -1) {
			// incorrect format
			return null;
		}
		if (index == path.length() - 1) {
			// remove trailing ':'
			path = path.substring(0, index);
			index = path.lastIndexOf(':');
		}
		// split file and line number
		String fileName = path.substring(0, index);
		try {
			String lineNumber = path.substring(index + 1);
			int line = Integer.parseInt(lineNumber);
			IFile file = getFileForLocation(fileName, buildFileParent);
			if (file != null) {
				return new FileLink(file, null, -1, -1, line);
			}
		}
		catch (NumberFormatException e) {
			// do nothing
		}

		return null;
	}

	/**
	 * Returns the workspace file associated with the given path in the local file system, or <code>null</code> if none. If the path happens to be a
	 * relative path, then the path is interpreted as relative to the specified parent file.
	 * 
	 * Attempts to handle linked files; the first found linked file with the correct path is returned.
	 * 
	 * @param path
	 * @param buildFileParent
	 * @return file or <code>null</code>
	 * @see org.eclipse.core.resources.IWorkspaceRoot#findFilesForLocation(IPath)
	 */
	public static IFile getFileForLocation(String path, File buildFileParent) {
		return AntLaunchingUtil.getFileForLocation(path, buildFileParent);
	}

	/**
	 * Migrates the classpath in the given configuration from the old format to the new format. The old format is not preserved. Instead, the default
	 * classpath will be used. However, ANT_HOME settings are preserved.
	 * 
	 * @param configuration
	 *            a configuration to migrate
	 * @throws CoreException
	 *             if unable to migrate
	 * @since 3.0
	 */
	public static void migrateToNewClasspathFormat(ILaunchConfiguration configuration) throws CoreException {
		AntLaunchingUtil.migrateToNewClasspathFormat(configuration);
	}

	private static int getOffset(int line, int column, ITextEditor editor) {
		IDocumentProvider provider = editor.getDocumentProvider();
		IEditorInput input = editor.getEditorInput();
		try {
			provider.connect(input);
		}
		catch (CoreException e) {
			return -1;
		}
		try {
			IDocument document = provider.getDocument(input);
			if (document != null) {
				if (column > -1) {
					// column marks the length..adjust to 0 index and to be within the element's source range
					return document.getLineOffset(line - 1) + column - 1 - 2;
				}
				return document.getLineOffset(line - 1);
			}
		}
		catch (BadLocationException e) {
			// do nothing
		}
		finally {
			provider.disconnect(input);
		}
		return -1;
	}

	/**
	 * Opens the given editor on the buildfile of the provided node and selects that node in the editor.
	 * 
	 * @param page
	 *            the page to open the editor in
	 * @param editorDescriptor
	 *            the editor descriptor, or <code>null</code> for the system editor
	 * @param node
	 *            the node from the buildfile to open and then select in the editor
	 */
	public static void openInEditor(IWorkbenchPage page, IEditorDescriptor editorDescriptor, AntElementNode node) {
		IEditorPart editorPart = null;
		IFile fileResource = node.getIFile();
		try {
			if (editorDescriptor == null) {
				editorPart = page.openEditor(new FileEditorInput(fileResource), IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID);
			} else {
				editorPart = page.openEditor(new FileEditorInput(fileResource), editorDescriptor.getId());
			}
		}
		catch (PartInitException e) {
			AntUIPlugin.log(MessageFormat.format(AntUIModelMessages.AntUtil_0, new Object[] { fileResource.getLocation().toOSString() }), e);
		}

		if (editorPart instanceof AntEditor) {
			AntEditor editor = (AntEditor) editorPart;
			if (node.getImportNode() != null) {
				AntModel model = editor.getAntModel();
				AntProjectNode project = model.getProjectNode();
				if (project == null) {
					return;
				}
				int[] info = node.getExternalInfo();
				int offset = getOffset(info[0], info[1], editor);
				node = project.getNode(offset);
			}
			editor.setSelection(node, true);
		}
	}

	/**
	 * Opens an editor on the buildfile of the provided node and selects that node in the editor.
	 * 
	 * @param page
	 *            the page to open the editor in
	 * @param node
	 *            the node from the buildfile to open and then select in the editor
	 */
	public static void openInEditor(IWorkbenchPage page, AntElementNode node) {
		IFile file = node.getIFile();
		IEditorDescriptor editorDesc;
		try {
			editorDesc = IDE.getEditorDescriptor(file, true, true);
		}
		catch (PartInitException e) {
			return;
		}
		openInEditor(page, editorDesc, node);
	}

	/**
	 * Opens an external browser on the provided <code>urlString</code>
	 *
	 * @param urlString
	 *            The url to open
	 * @param shell
	 *            the shell
	 * @param errorDialogTitle
	 *            the title of any error dialog
	 */
	public static void openBrowser(final String urlString, final Shell shell, final String errorDialogTitle) {
		shell.getDisplay().syncExec(() -> {
			IWorkbenchBrowserSupport support = PlatformUI.getWorkbench().getBrowserSupport();
			try {
				IWebBrowser browser = support.createBrowser(fgBrowserId);
				fgBrowserId = browser.getId();
				browser.openURL(new URL(urlString));
				return;
			}
			catch (PartInitException e1) {
				AntUIPlugin.log(e1.getStatus());
			}
			catch (MalformedURLException e2) {
				AntUIPlugin.log(e2);
			}

			String platform = SWT.getPlatform();
			boolean succeeded = true;
			if ("motif".equals(platform) || "gtk".equals(platform)) { //$NON-NLS-1$ //$NON-NLS-2$
				Program program = Program.findProgram("html"); //$NON-NLS-1$
				if (program == null) {
					program = Program.findProgram("htm"); //$NON-NLS-1$
				}
				if (program != null) {
					succeeded = program.execute(urlString.toString());
				}
			} else {
				succeeded = Program.launch(urlString.toString());
			}
			if (!succeeded) {
				MessageDialog.openInformation(shell, errorDialogTitle, AntUIModelMessages.AntUtil_1);
			}
		});
	}

	public static boolean isSeparateJREAntBuild(ILaunchConfiguration configuration) {
		return AntLaunchingUtil.isSeparateJREAntBuild(configuration);
	}

	/**
	 * Returns if the given extension is a known extension to Ant i.e. a supported content type extension.
	 *
	 * @param resource
	 * @return true if the file extension is supported false otherwise
	 *
	 * @since 3.6
	 */
	public static boolean isKnownAntFile(IResource resource) {
		if (resource != null) {
			// workspace file
			IFile file = null;
			if (resource.getType() == IResource.FILE) {
				file = (IFile) resource;
			} else {
				file = resource.getAdapter(IFile.class);
			}
			if (file != null) {
				IContentType fileType = IDE.getContentType(file);
				if (fileType == null) {
					return false;
				}
				IContentType antType = Platform.getContentTypeManager().getContentType(AntCorePlugin.ANT_BUILDFILE_CONTENT_TYPE);
				if (antType != null) {
					return fileType.isKindOf(antType);
				}
			}
		}
		return false;
	}

	/**
	 * Returns if the given extension is a known extension to Ant i.e. a supported content type extension.
	 * 
	 * @param file
	 * @return true if the file extension is supported false otherwise
	 * 
	 * @since 3.8
	 */
	public static boolean isKnownAntFile(File file) {
		if (file != null && !file.isDirectory()) {
			String filename = file.getName();
			IContentType type = Platform.getContentTypeManager().findContentTypeFor(filename);
			if (type != null) {
				IContentType antType = Platform.getContentTypeManager().getContentType(AntCorePlugin.ANT_BUILDFILE_CONTENT_TYPE);
				if (antType != null) {
					return type.isKindOf(antType);
				}
			}
			String[] names = getKnownBuildfileNames();
			for (int i = 0; names != null && i < names.length; i++) { // names can be null!
				if (filename.endsWith(names[i])) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Returns an array of build file names from the ant preference store
	 * 
	 * @return an array of build file names
	 * @since 3.6
	 */
	public static String[] getKnownBuildfileNames() {
		IPreferenceStore prefs = AntUIPlugin.getDefault().getPreferenceStore();
		String buildFileNames = prefs.getString(IAntUIPreferenceConstants.ANT_FIND_BUILD_FILE_NAMES);
		if (buildFileNames.length() == 0) {
			// the user has not specified any names to look for
			return null;
		}
		return parseString(buildFileNames, ","); //$NON-NLS-1$
	}

	/**
	 * Returns if the given file is a known build file name, based on the given names from the Ant &gt; Names preference
	 * 
	 * @param filename
	 * @return true if the name of the file is given in the Ant &gt; Names preference, false otherwise
	 * @since 3.6
	 */
	public static boolean isKnownBuildfileName(String filename) {
		String[] names = getKnownBuildfileNames();
		for (int i = 0; names != null && i < names.length; i++) { // names can be null!
			if (names[i].equalsIgnoreCase(filename)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * A helper method to extract the build filename extensions as defined in the extender of the content-types extension-point.
	 * 
	 * @return An empty array or list of filename extensions as specified in the content-types extension
	 * @since 3.8
	 */
	public static String[] getKnownBuildFileExtensions() {
		IContentType antType = null;
		String[] result = null;
		try {
			antType = Platform.getContentTypeManager().getContentType(AntCorePlugin.ANT_BUILDFILE_CONTENT_TYPE);
			if (antType != null) {
				result = antType.getFileSpecs(IContentType.FILE_EXTENSION_SPEC);
			}
		}
		catch (Exception e) {
			// Empty block and fall-thru is intentional!
		}
		return result == null ? new String[0] : result;
	}

	/**
	 * A helper method to construct a RegEx pattern out of the extensions
	 * 
	 * @return A String that is a RegEx pattern representing the extensions
	 * @since 3.8
	 */
	public static String getKnownBuildFileExtensionsAsPattern() {
		String[] extns = AntUtil.getKnownBuildFileExtensions();
		if (extns.length == 0) {
			return IAntCoreConstants.XML_EXTENSION;
		}
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < extns.length; i++) {
			if (i > 0)
				sb.append('|');
			sb.append(extns[i]);
		}
		return sb.toString();
	}

	/**
	 * Returns if the given file name is known as a build file. This method consults all of the known file extensions from the Ant-defined content
	 * types
	 * 
	 * @param name
	 * @return <code>true</code> if the file name matches an Ant build file pattern <code>false</code> otherwise
	 * @since 3.8
	 */
	public static boolean isKnownAntFileName(String name) {
		StringBuffer buf = new StringBuffer(".*.("); //$NON-NLS-1$
		buf.append(getKnownBuildFileExtensionsAsPattern());
		buf.append(")"); //$NON-NLS-1$
		try {
			Pattern p = Pattern.compile(buf.toString());
			return p.matcher(name).matches();
		}
		catch (PatternSyntaxException pse) {
			return false;
		}
	}
}