/*******************************************************************************
 * Copyright (c) 2004, 2016 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.help.search;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Properties;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.help.internal.base.HelpBasePlugin;
import org.eclipse.help.internal.base.HelpBaseResources;
import org.eclipse.help.internal.entityresolver.LocalEntityResolver;
import org.eclipse.help.internal.search.AnalyzerDescriptor;
import org.eclipse.help.internal.search.PluginVersionInfo;
import org.eclipse.help.internal.search.SearchIndex;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

/**
 * Builds a help search index for a plug-in by looking for the
 * <code>org.eclipse.help.toc</code> extensions in the provided manifest file.
 * Search index is only created if index path is specified in the extension.
 * Index will contain data for all the topics listed in all the TOCs declared in
 * the plug-in.
 * <p>
 * If the index is created for a fragment, the manifest must point at the
 * referenced fragment plug-in, while the destination should be the fragment
 * itself.
 * <p>
 * Starting from the provided destination directory, index for each locale will
 * be placed in a directory with the following path:
 * <p>
 * <pre>
 *                  destination/nl/country/
 *
 *                  or
 *
 *                  destination/nl/country/language/
 * </pre>
 * <p>
 * The relative directory specified in the <code>index</code> element of the
 * <code>org.eclipse.help.toc</code> extention will be created in each of the
 * locale-specific paths (one per locale).
 * <p>
 * An instance of <code>HelpIndexBuilder</code> can be cached and used
 * multiple times for different manifest and destination values.
 *
 * @since 3.1
 */

public class HelpIndexBuilder {
	private static final String POINT_TOC = "org.eclipse.help.toc"; //$NON-NLS-1$

	private static final String EL_TOC = "toc"; //$NON-NLS-1$

	private static final String EL_INDEX = "index"; //$NON-NLS-1$

	private File manifest;

	private String indexPath;

	private File destination;

	private ArrayList<TocFile> tocFiles = new ArrayList<>();

	private ArrayList<LocaleDir> localeDirs = new ArrayList<>();

	private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
			.newInstance();

	private DocumentBuilder parser;

	private static Locale[] legalLocales = Locale.getAvailableLocales();
	private static HashSet<String> legalLanguages = null;
	private static HashSet<String> legalCountries = null;

	class PluginIdentifier {
		String id;

		Version version;

		public PluginIdentifier(String id, String version) {
			this.id = id;
			this.version = new Version(version);
		}
	}

	class LocaleDir {
		String locale;
		String relativePath;
		ArrayList<File> dirs = new ArrayList<>();

		public LocaleDir(String locale, String relativePath) {
			this.locale = locale;
			this.relativePath = relativePath;
		}

		public File findFile(String file) {
			for (int i=0; i<dirs.size(); i++) {
				File dir = dirs.get(i);
				File absoluteFile = new File(dir, file);
				if (absoluteFile.exists())
					return absoluteFile;
			}
			return null;
		}
		public URL findURL(String href) {
			File file = findFile(href);
			if (file!=null) {
				try {
						return file.toURI().toURL();
					}
				catch (MalformedURLException e) {
				}
			}
			return null;
		}
		public void addDirectory(File directory) {
			dirs.add(directory);
		}
	}

	class IndexerPluginVersionInfo extends PluginVersionInfo {
		private static final long serialVersionUID = 1L;

		public IndexerPluginVersionInfo(PluginIdentifier id,
				PluginIdentifier fid, File dir) {
			super(SearchIndex.INDEXED_CONTRIBUTION_INFO_FILE, null, dir, false);
			createInfo(id, fid);
		}

		@Override
		protected void createTable(Collection<String> docBundleIds) {
			// do nothing
		}

		protected void createInfo(PluginIdentifier id, PluginIdentifier fid) {
			// We will ignore docBundleIds which is null anyway,
			// and use id and fid to create plugin info
			// for the destination
			StringBuffer buffer = new StringBuffer();
			appendBundleInformation(buffer, id.id, id.version.toString());
			if (fid != null)
				appendBundleInformation(buffer, fid.id, fid.version.toString());

			this.put(id.id, buffer.toString());
		}
	}

	class TocFile {
		String href;
		boolean primary;
		String extraDir;

		public TocFile(String href, boolean primary, String extraDir) {
			this.href = href;
			this.primary = primary;
			this.extraDir = extraDir;
		}
	}

	/**
	 * Creates a new instance of the help index builder.
	 */
	public HelpIndexBuilder() {
	}

	/**
	 * Returns the manifest file for this builder. If the target is a plug-in,
	 * it is the absolute path of <code>plugin.xml</code> file. If the target
	 * is a fragment, it is the absolute path of <code>plugin.xml</code> of
	 * the fragment plug-in.
	 *
	 * @return the file that contains TOC extensions
	 */
	public File getManifest() {
		return manifest;
	}

	/**
	 * Sets the new manifest file (plugin.xml) to be used by this builder. If
	 * the target is a plug-in, it is the absolute path of
	 * <code>plugin.xml</code> file. If the target is a fragment, it is the
	 * absolute path of <code>plugin.xml</code> of the fragment plug-in.
	 *
	 * @param manifest
	 *            the file that contains TOC extensions
	 */
	public void setManifest(File manifest) {
		if (manifest.getName().equalsIgnoreCase("MANIFEST.MF")) { //$NON-NLS-1$
			File parent = manifest.getParentFile();
			if (parent.getName().equalsIgnoreCase("META-INF")) { //$NON-NLS-1$
				File project = parent.getParentFile();
				manifest = new File(project, "plugin.xml"); //$NON-NLS-1$
				if (!manifest.exists())
					manifest=null;
			}
		}
		this.manifest = manifest;
	}

	/**
	 * Returns the destination directory where index should be created.
	 *
	 * @return the destination index directory
	 */
	public File getDestination() {
		return destination;
	}

	/**
	 * Sets the destination directory where index should be created.
	 * Locale-specific directories will be created starting from this directory.
	 *
	 * @param destination
	 *            the directory where index should be created
	 */
	public void setDestination(File destination) {
		this.destination = destination;
	}

	/**
	 * Creates the plug-in search index by parsing the provided plugin.xml file,
	 * looking for TOC extensions. If at least one of them has
	 * <code>index</code> element, all topics listed in all the TOCs in the
	 * plug-in will be indexed and stored in the path specified by the
	 * <code>index</code> element.
	 *
	 * @param monitor
	 *            the monitor to track index creation progress
	 * @throws CoreException
	 *             if there are problems during index creation.
	 */

	public void execute(IProgressMonitor monitor) throws CoreException {
		reset();
		if (manifest == null || destination == null)
			return;
		Document doc = readXMLFile(manifest);
		if (doc == null)
			return;

		PluginIdentifier pid = getPluginID(manifest.getParentFile(), doc);
		PluginIdentifier fid = null;

		if (!manifest.getParentFile().equals(destination)) {
			// target is a fragment, source is a plug-in
			File fragmentFile = new File(destination, "fragment.xml"); //$NON-NLS-1$
			Document fdoc=null;
			if (fragmentFile.exists())
				fdoc = readXMLFile(fragmentFile);
			fid = getPluginID(destination, fdoc);
			fdoc=null;
		}

		Element[] extensions = getTocExtensions(doc);
		for (int i = 0; i < extensions.length; i++) {
			processExtension(extensions[i]);
		}
		if (indexPath == null) {
			throwCoreException(HelpBaseResources.HelpIndexBuilder_noDestinationPath, null);
		}
		doc = null; // discard the DOM

		// compute the dir tree
		computeLocaleDirs(fid!=null);

		SubMonitor subMonitor = SubMonitor.convert(monitor, HelpBaseResources.HelpIndexBuilder_buildingIndex, localeDirs.size());
		MultiStatus multiStatus = null;

		for (int i=0; i<localeDirs.size(); i++) {
			// process locale dir
			LocaleDir localeDir = localeDirs.get(i);
			MultiStatus localeStatus = processLocaleDir(pid, fid, localeDir, subMonitor.split(1));
			if (localeStatus != null) {
				if (multiStatus == null)
					multiStatus = localeStatus;
				else
					multiStatus.addAll(localeStatus);
			}
		}
		subMonitor.done();
		if (multiStatus != null)
			throw new CoreException(multiStatus);
	}

	/*
	 * Extracts TOCs and the index path from the extensions.
	 */
	private void processExtension(Element extensionNode) {
		NodeList children = extensionNode.getElementsByTagName(EL_TOC);
		for (int i = 0; i < children.getLength(); i++) {
			Node node = children.item(i);
			String file = getAttribute(node, "file"); //$NON-NLS-1$
			String primary = getAttribute(node, "primary"); //$NON-NLS-1$
			String extradir = getAttribute(node, "extradir"); //$NON-NLS-1$
			addTocFile(file, primary, extradir);
		}
		children = extensionNode.getElementsByTagName(EL_INDEX);
		if (children.getLength() == 1) {
			Node node = children.item(0);
			indexPath = getAttribute(node, "path"); //$NON-NLS-1$
		}
	}

	private void addTocFile(String file, String primary, String extradir) {
		boolean isPrimary = primary != null && primary.equalsIgnoreCase("true"); //$NON-NLS-1$
		tocFiles.add(new TocFile(file, isPrimary, extradir));
	}

	/*
	 * Computes the all os/*, ws/*, nl/language/ and
	 * nl/language/country/ locale dirs that contain files. We will
	 * produce an index for each one.
	 */
	private void computeLocaleDirs(boolean fragment) throws CoreException {
		if (!fragment) {
			LocaleDir dir = new LocaleDir(null, "/"); //$NON-NLS-1$
			dir.addDirectory(destination);
			localeDirs.add(dir);
		}
		File ws = new File(destination, "ws"); //$NON-NLS-1$
		computeSystem(ws, Platform.knownWSValues());
		File os = new File(destination, "os"); //$NON-NLS-1$
		computeSystem(os, Platform.knownOSValues());

		File nl = new File(destination, "nl"); //$NON-NLS-1$
		if (!nl.exists() || !nl.isDirectory())
			return;
		File [] languages = listFiles(nl);
		HashSet<String> locales = new HashSet<>();
		for (int i=0; i<languages.length; i++) {
			File language = languages[i];
			if (!language.isDirectory())
				continue;
			if (!isValidLanguage(language.getName()))
				continue;
			File [] countries = listFiles(language);
			for (int j=0; j<countries.length; j++) {
				File country = countries[j];
				String locale;
				boolean hasCountry = false;
				if (country.isDirectory() && isValidCountry(country.getName()))
					hasCountry = true;
				if (hasCountry)
					locale = language.getName()+"_"+country.getName(); //$NON-NLS-1$
				else
					locale = language.getName();
				if (isValidLocale(locale) && !locales.contains(locale)) {
					String relativePath;
					if (hasCountry)
						relativePath = "/nl/"+language.getName()+"/"+country.getName(); //$NON-NLS-1$ //$NON-NLS-2$
					else
						relativePath = "/nl/"+language.getName(); //$NON-NLS-1$
					LocaleDir dir = new LocaleDir(locale, relativePath);
					if (hasCountry)
						dir.addDirectory(country);
					dir.addDirectory(language);
					dir.addDirectory(destination);
					localeDirs.add(dir);
					locales.add(locale);
				}
			}
		}
	}

	private void computeSystem(File systemRoot, String [] values) throws CoreException {
		if (systemRoot.exists() && systemRoot.isDirectory()) {
			// check
			File [] files = listFiles(systemRoot);
			for (int i=0; i<files.length; i++) {
				File sdir = files[i];
				if (!sdir.isDirectory())
					continue;
				String sname = sdir.getName();
				for (int j=0; j<values.length; j++) {
					if (values[j].equals(sname)) {
						// valid
						String relativePath="/"+systemRoot.getName()+"/"+sname; //$NON-NLS-1$ //$NON-NLS-2$
						LocaleDir dir = new LocaleDir(sname, relativePath);
						dir.addDirectory(sdir);
						dir.addDirectory(destination);
						localeDirs.add(dir);
						break;
					}
				}
			}
		}
	}

	/*
	 * Reject bogus directories.
	 */
	private boolean isValidLocale(String locale) {
		for (int i=0; i<legalLocales.length; i++) {
			Locale legalLocale = legalLocales[i];
			if (legalLocale.toString().equals(locale))
				return true;
		}
		return false;
	}

	private boolean isValidLanguage(String language) {
		if (legalLanguages==null) {
			legalLanguages = new HashSet<>();
			String [] choices = Locale.getISOLanguages();
			for (int i=0; i<choices.length; i++) {
				legalLanguages.add(choices[i]);
			}
		}
		return legalLanguages.contains(language);
	}

	private boolean isValidCountry(String country) {
		if (legalCountries==null) {
			legalCountries = new HashSet<>();
			String [] choices = Locale.getISOCountries();
			for (int i=0; i<choices.length; i++) {
				legalCountries.add(choices[i]);
			}
		}
		return legalCountries.contains(country);
	}

	/*
	 * Build an index for the locale directory by collecting
	 * documents according to the tocs, then building the index.
	 */

	private MultiStatus processLocaleDir(PluginIdentifier id, PluginIdentifier fid, LocaleDir localeDir,
			SubMonitor monitor) throws CoreException {
		File directory = localeDir.dirs.get(0);
		File indexDirectory = new File(directory, indexPath);
		prepareDirectory(indexDirectory);
		Collection<String> docs = collectDocs(localeDir);
		MultiStatus status = null;
		if (docs.size()>0) {
			String locale = localeDir.locale!=null?localeDir.locale:Platform.getNL();
			SearchIndex index = new SearchIndex(indexDirectory, locale,
				new AnalyzerDescriptor(locale), null, localeDir.relativePath);
			IndexerPluginVersionInfo docPlugins = new IndexerPluginVersionInfo(id,
				fid, indexDirectory);
			index.setDocPlugins(docPlugins);
			status = createIndex(id.id, fid != null, localeDir, index, docs, monitor);
			index.deleteLockFile();
		}
		return status;
	}

	/*
	 * Using TOC files found either in the fragment or in the plug-in,
	 * collect hrefs for the topics.
	 */

	private Collection<String> collectDocs(LocaleDir localeDir)
			throws CoreException {
		HashSet<String> docs = new HashSet<>();
		for (int i = 0; i < tocFiles.size(); i++) {
			TocFile tocFile = tocFiles.get(i);
			collectDocs(docs, getTocFile(localeDir, tocFile.href));
			if (tocFile.extraDir!=null) {
				//TODO also include all the indexable documents
				//in the extraDir
			}
		}
		return docs;
	}

	/*
	 * Try to find the actual file for the TOC href. Look in the
	 * locale dirs first (best match first). If not found,
	 * look in the plug-in itself (for fragments).
	 */

	private File getTocFile(LocaleDir localeDir, String href) {
		// try the locale dir
		File file = localeDir.findFile(href);
		if (file!=null)
			return file;
		// try the plug-in
		File pdir = manifest.getParentFile();
		return new File(pdir, href);
	}

	/*
	 * Collect hrefs starting from the 'toc' element.
	 */
	private void collectDocs(Set<String> docs, File tocFile)
			throws CoreException {
		if (!tocFile.exists())
			return;
		Document doc = readXMLFile(tocFile);
		add(doc.getDocumentElement(), docs);
	}

	/*
	 * Recursive collection of hrefs from topics.
	 */
	private void add(Element topic, Set<String> hrefs) {
		String href = getAttribute(topic, "href"); //$NON-NLS-1$
		if (topic.getTagName().equals("toc")) { //$NON-NLS-1$
			// toc element has 'topic' attribute. Don't ask why :-)
			href = getAttribute(topic, "topic"); //$NON-NLS-1$
		}
		if (href != null
				&& !href.equals("") && !href.startsWith("http://") && !href.startsWith("https://")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			href = SearchIndex.getIndexableHref(href);
			if (href != null)
				hrefs.add(href);
		}
		NodeList subtopics = topic.getElementsByTagName("topic"); //$NON-NLS-1$
		for (int i = 0; i < subtopics.getLength(); i++) {
			Element subtopic = (Element) subtopics.item(i);
			href = getAttribute(subtopic, "href"); //$NON-NLS-1$
			if (href != null && !href.equals("") && !href.startsWith("http://") && !href.startsWith("https://")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				href = SearchIndex.getIndexableHref(href);
				if (href != null)
					hrefs.add(href);
			}
		}
	}

	/*
	 * Creates index for the locale dir by iterating over the doc hrefs
	 * and adding them into the index. Documents that cannot be found
	 * will be ignored.
	 */

	private MultiStatus createIndex(String pluginId, boolean fragment, LocaleDir localeDir, SearchIndex index,
			Collection<String> addedDocs, SubMonitor monitor)
			throws CoreException {
		// build an index for each locale directory
		String taskName = NLS.bind(HelpBaseResources.HelpIndexBuilder_indexFor, localeDir.dirs.get(0).getName());
		monitor.beginTask(taskName + HelpBaseResources.UpdatingIndex, addedDocs.size());
		if (!index.beginAddBatch(true)) {
			throwCoreException(HelpBaseResources.HelpIndexBuilder_error, null);
		}
		checkCancelled(monitor);
		MultiStatus multiStatus = null;

		for (Iterator<String> it = addedDocs.iterator(); it.hasNext();) {
			String href = it.next();
			URL url = localeDir.findURL(href);
			if (url != null) {
				IStatus status = index
						.addDocument(getName(pluginId, href), url);
				if (status.getCode() != IStatus.OK) {
					if (multiStatus == null)
						multiStatus = createMultiStatus();
					multiStatus.add(status);
				}
			}
			else {
				// report missing document when in a plug-in
				String locale = localeDir.locale!=null?localeDir.locale:Platform.getNL();
				String message = NLS.bind(HelpBaseResources.HelpIndexBuilder_cannotFindDoc, locale, href);
				IStatus status = new Status(IStatus.WARNING, pluginId, IStatus.OK, message, null);
				if (multiStatus == null)
					multiStatus = createMultiStatus();
				multiStatus.add(status);
			}
			checkCancelled(monitor);
			monitor.worked(1);
		}
		monitor.subTask(taskName + HelpBaseResources.Writing_index);
		if (!index.endAddBatch(true, true)) {
			IStatus status = new Status(IStatus.ERROR, HelpBasePlugin.PLUGIN_ID,
					IStatus.OK, HelpBaseResources.HelpIndexBuilder_errorWriting, null);
			if (multiStatus==null)
				multiStatus = createMultiStatus();
			multiStatus.add(status);
		}
		return multiStatus;
	}

	private MultiStatus createMultiStatus() {
		return new MultiStatus(
				HelpBasePlugin.PLUGIN_ID,
				IStatus.OK,
				HelpBaseResources.HelpIndexBuilder_incompleteIndex,
				null);
	}

	private void checkCancelled(IProgressMonitor pm)
			throws OperationCanceledException {
		if (pm.isCanceled())
			throw new OperationCanceledException();
	}

	private String getName(String pluginId, String href) {
		// remove query string if any
		int i = href.indexOf('?');
		if (i != -1)
			href = href.substring(0, i);
		return "/" + pluginId + "/" + href; //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * If the path does not exist, create it. Otherwise, delete all the files in
	 * it.
	 *
	 * @param indexDirectory
	 */

	private void prepareDirectory(File indexDirectory) throws CoreException {
		if (indexDirectory.exists()) {
			File[] files = listFiles(indexDirectory);
			for (int i = 0; i < files.length; i++) {
				File file = files[i];
				boolean result = file.delete();
				if (!result)
					throwCoreException(
							HelpBaseResources.HelpIndexBuilder_cannotScrub, null);
			}
		} else {
			boolean result = indexDirectory.mkdirs();
			if (!result)
				throwCoreException(HelpBaseResources.HelpIndexBuilder_cannotCreateDest,
						null);
		}
	}

	private void reset() {
		localeDirs.clear();
		tocFiles.clear();
		indexPath = null;
	}

	private PluginIdentifier getPluginID(File dir, Document doc) throws CoreException {
		String id = null;
		String version = null;
		if (doc != null) {
			Node root = doc.getDocumentElement();
			id = getAttribute(root, "id"); //$NON-NLS-1$
			version = getAttribute(root, "version"); //$NON-NLS-1$
			if (id != null && version != null)
				return new PluginIdentifier(id, version);
		}
		// check for the OSGi manifest
		File OSGiFile = new File(dir,
				"META-INF/MANIFEST.MF"); //$NON-NLS-1$

		if (OSGiFile.exists()) {
			try {
				Manifest OSGiManifest = new Manifest(new FileInputStream(
						OSGiFile));
				Properties headers = manifestToProperties(OSGiManifest
						.getMainAttributes());
				String value = headers.get(Constants.BUNDLE_SYMBOLICNAME)
						.toString();
				if (value == null)
					return null;
				ManifestElement[] elements = ManifestElement.parseHeader(
						Constants.BUNDLE_SYMBOLICNAME, value);
				if (elements.length > 0)
					id = elements[0].getValue();
				value = headers.get(Constants.BUNDLE_VERSION).toString();
				if (value == null)
					return null;
				elements = ManifestElement.parseHeader(
						Constants.BUNDLE_VERSION, value);
				if (elements.length > 0)
					version = elements[0].getValue();
				if (id != null && version != null)
					return new PluginIdentifier(id, version);
			} catch (Exception e1) {
				throwCoreException(HelpBaseResources.HelpIndexBuilder_errorExtractingId, e1);
			}
		}
		return null;
	}

	private String getAttribute(Node node, String name) {
		NamedNodeMap atts = node.getAttributes();
		if (atts != null) {
			Node att = atts.getNamedItem(name);
			if (att != null)
				return att.getNodeValue();
		}
		return null;
	}

	private Document readXMLFile(File file) throws CoreException {
		Document d = null;
		try (InputStream stream = new FileInputStream(file);
				InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) {
			InputSource inputSource = new InputSource(reader);
			inputSource.setSystemId(manifest.toString());

			if (parser == null)
				parser = documentBuilderFactory.newDocumentBuilder();
			parser.setEntityResolver(new LocalEntityResolver());
			d = parser.parse(inputSource);
		} catch (Exception e) {
			String message = NLS.bind(HelpBaseResources.HelpIndexBuilder_errorParsing, file.getName());
			throwCoreException(message, e);
		}
		return d;
	}

	private Element[] getTocExtensions(Document doc) {
		ArrayList<Node> list = new ArrayList<>();
		//Node root = doc.getDocumentElement();
		NodeList children = doc.getElementsByTagName("extension"); //$NON-NLS-1$
		for (int i = 0; i < children.getLength(); i++) {
			Node child = children.item(i);
			String point = getAttribute(child, "point"); //$NON-NLS-1$
			if (point.equals(POINT_TOC))
				list.add(child);
		}
		return list.toArray(new Element[list.size()]);
	}

	private Properties manifestToProperties(Attributes d) {
		Iterator<Object> iter = d.keySet().iterator();
		Properties result = new Properties();
		while (iter.hasNext()) {
			Attributes.Name key = (Attributes.Name) iter.next();
			result.put(key.toString(), d.get(key));
		}
		return result;
	}

	private void throwCoreException(String message, Throwable t)
			throws CoreException {
		IStatus status = new Status(IStatus.ERROR, HelpBasePlugin.PLUGIN_ID,
				IStatus.OK, message, t);
		throw new CoreException(status);
	}
	
	private File[] listFiles(File file) throws CoreException {
		File[] fileList = file.listFiles();
		if(fileList == null) {
			throwCoreException("Content from directory '" + file.getAbsolutePath() + "' can not be listed.", null); //$NON-NLS-1$ //$NON-NLS-2$
		}
		return fileList;
	}
}
