/*******************************************************************************
 * Copyright (c) 2004, 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
 *     Semion Chichelnitsky (semion@il.ibm.com) - bug 208564
 *     Jan-Ove Weichel (janove.weichel@vogella.com) - bug 474359
 *******************************************************************************/
package org.eclipse.core.internal.preferences;

import java.io.*;
import java.lang.ref.WeakReference;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.core.internal.runtime.RuntimeLog;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.preferences.*;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;

/**
 * @since 3.0
 */
public class PreferencesService implements IPreferencesService {
	/**
	 * The interval between passes over the preference tree to canonicalize
	 * strings.
	 */
	private static final long STRING_SHARING_INTERVAL = 300000;
	private static final String MATCH_TYPE_PREFIX = "prefix"; //$NON-NLS-1$

	// the order of search scopes when people don't have a specific order set
	private static String[] DEFAULT_DEFAULT_LOOKUP_ORDER = new String[] { //
	InstanceScope.SCOPE, //
			ConfigurationScope.SCOPE, //
			DefaultScope.SCOPE};
	private static final char EXPORT_ROOT_PREFIX = '!';
	private static final char BUNDLE_VERSION_PREFIX = '@';
	private static final float EXPORT_VERSION = 3;
	private static final String VERSION_KEY = "file_export_version"; //$NON-NLS-1$
	private static final String EMPTY_STRING = ""; //$NON-NLS-1$

	private static PreferencesService instance;
	static final RootPreferences root = new RootPreferences();
	private static final Map<String, LookupOrder> defaultsRegistry = Collections.synchronizedMap(new HashMap<String, LookupOrder>());
	private Object registryHelper = null;
	private final Map<String, EclipsePreferences> defaultScopes = new HashMap<>();

	/**
	 * The last time analysis was done to remove duplicate strings
	 */
	private long lastStringSharing = 0;

	/*
	 * Create and return an IStatus object with ERROR severity and the
	 * given message and exception.
	 */
	private static IStatus createStatusError(String message, Exception e) {
		return new Status(IStatus.ERROR, PrefsMessages.OWNER_NAME, IStatus.ERROR, message, e);
	}

	/*
	 * Return the instance.
	 */
	public static PreferencesService getDefault() {
		if (instance == null)
			instance = new PreferencesService();
		return instance;
	}

	static void log(IStatus status) {
		RuntimeLog.log(status);
	}

	PreferencesService() {
		super();
		initializeDefaultScopes();
	}


	@Override
	public void applyPreferences(IEclipsePreferences tree, IPreferenceFilter[] filters) throws CoreException {
		if (filters == null || filters.length == 0)
			return;
		try {
			internalApply(tree, filters);
			// save the preferences
			try {
				getRootNode().node(tree.absolutePath()).flush();
			} catch (BackingStoreException e) {
				throw new CoreException(createStatusError(PrefsMessages.preferences_saveProblems, e));
			}

			//this typically causes a major change to the preference tree, so force string sharing
			lastStringSharing = 0;
			shareStrings();
		} catch (BackingStoreException e) {
			throw new CoreException(createStatusError(PrefsMessages.preferences_applyProblems, e));
		}
	}


	@Override
	public IStatus applyPreferences(IExportedPreferences preferences) throws CoreException {
		// TODO investigate refactoring to merge with new #apply(IEclipsePreferences, IPreferenceFilter[]) APIs
		if (preferences == null)
			throw new IllegalArgumentException();

		if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
			PrefsMessages.message("Applying exported preferences: " + ((ExportedPreferences) preferences).toDeepDebugString()); //$NON-NLS-1$

		final MultiStatus result = new MultiStatus(PrefsMessages.OWNER_NAME, IStatus.OK, PrefsMessages.preferences_applyProblems, null);

		IEclipsePreferences modifiedNode = firePreApplyEvent(preferences);

		// create a visitor to apply the given set of preferences
		IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() {
			@Override
			public boolean visit(IEclipsePreferences node) throws BackingStoreException {
				IEclipsePreferences globalNode;
				if (node.parent() == null)
					globalNode = root;
				else
					globalNode = (IEclipsePreferences) root.node(node.absolutePath());
				ExportedPreferences epNode = (ExportedPreferences) node;

				// if this node is an export root then we need to remove
				// it from the global preferences before continuing.
				boolean removed = false;
				if (epNode.isExportRoot()) {
					if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
						PrefsMessages.message("Found export root: " + epNode.absolutePath()); //$NON-NLS-1$
					// TODO should only have to do this if any of my children have properties to set
					globalNode.removeNode();
					removed = true;
				}

				// iterate over the preferences in this node and set them
				// in the global space.
				String[] keys = epNode.properties.keys();

				// if this node was removed then we need to create a new one
				if (removed)
					globalNode = (IEclipsePreferences) root.node(node.absolutePath());

				// the list for properties to remove
				List<String> propsToRemove = new ArrayList<>();
				for (int i = 0; i < globalNode.keys().length; i++) {
					propsToRemove.add(globalNode.keys()[i]);
				}

				if (keys.length > 0) {
					String key = null;
					for (int i = 0; i < keys.length; i++) {
						key = keys[i];

						// preferences that are not in the applied node
						// will be removed
						propsToRemove.remove(key);

						// intern strings we import because some people
						// in their property change listeners use identity
						// instead of equals. See bug 20193 and 20534.
						key = key.intern();
						String value = node.get(key, null);
						if (value != null) {
							if (EclipsePreferences.DEBUG_PREFERENCE_SET)
								PrefsMessages.message("Setting: " + globalNode.absolutePath() + '/' + key + '=' + value); //$NON-NLS-1$
							globalNode.put(key, value);
						}
					}
				}

				String keyToRemove = null;
				for (Iterator<String> it = propsToRemove.iterator(); it.hasNext();) {
					keyToRemove = it.next();
					keyToRemove = keyToRemove.intern();
					if (EclipsePreferences.DEBUG_PREFERENCE_SET)
						PrefsMessages.message("Removing: " + globalNode.absolutePath() + '/' + keyToRemove); //$NON-NLS-1$
					globalNode.remove(keyToRemove);
				}

				// keep visiting children
				return true;
			}
		};

		try {
			// start by visiting the root
			modifiedNode.accept(visitor);
		} catch (BackingStoreException e) {
			throw new CoreException(createStatusError(PrefsMessages.preferences_applyProblems, e));
		}

		// save the preferences
		try {
			getRootNode().node(modifiedNode.absolutePath()).flush();
		} catch (BackingStoreException e) {
			throw new CoreException(createStatusError(PrefsMessages.preferences_saveProblems, e));
		}

		if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
			PrefsMessages.message("Current list of all settings: " + ((EclipsePreferences) getRootNode()).toDeepDebugString()); //$NON-NLS-1$
		//this typically causes a major change to the preference tree, so force string sharing
		lastStringSharing = 0;
		shareStrings();
		return result;
	}

	private boolean containsKeys(IEclipsePreferences aRoot) throws BackingStoreException {
		final boolean result[] = new boolean[] {false};
		IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() {
			@Override
			public boolean visit(IEclipsePreferences node) throws BackingStoreException {
				if (node.keys().length != 0)
					result[0] = true;
				return !result[0];
			}
		};
		aRoot.accept(visitor);
		return result[0];
	}

	/*
	 * Convert the given properties file from legacy format to
	 * one which is Eclipse 3.0 compliant.
	 *
	 * Convert the plug-in version indicator entries to export roots.
	 */
	private Properties convertFromLegacy(Properties properties) {
		Properties result = new Properties();
		String prefix = IPath.SEPARATOR + InstanceScope.SCOPE + IPath.SEPARATOR;
		for (Entry<?, ?> entry : properties.entrySet()) {
			String key = (String) entry.getKey();
			String value = (String) entry.getValue();
			if (value != null) {
				int index = key.indexOf(IPath.SEPARATOR);
				if (index == -1) {
					result.put(BUNDLE_VERSION_PREFIX + key, value);
					result.put(EXPORT_ROOT_PREFIX + prefix + key, EMPTY_STRING);
				} else {
					String path = key.substring(0, index);
					key = key.substring(index + 1);
					result.put(EclipsePreferences.encodePath(prefix + path, key), value);
				}
			}
		}
		return result;
	}

	/*
	 * Convert the given properties file into a node hierarchy suitable for
	 * importing.
	 */
	private IExportedPreferences convertFromProperties(Properties properties) {
		IExportedPreferences result = ExportedPreferences.newRoot();
		for (Entry<?, ?> entry : properties.entrySet()) {
			String path = (String) entry.getKey();
			String value = (String) entry.getValue();
			if (path.charAt(0) == EXPORT_ROOT_PREFIX) {
				ExportedPreferences current = (ExportedPreferences) result.node(path.substring(1));
				current.setExportRoot();
			} else if (path.charAt(0) == BUNDLE_VERSION_PREFIX) {
				ExportedPreferences current = (ExportedPreferences) result.node(InstanceScope.SCOPE).node(path.substring(1));
				current.setVersion(value);
			} else {
				String[] decoded = EclipsePreferences.decodePath(path);
				path = decoded[0] == null ? EMPTY_STRING : decoded[0];
				ExportedPreferences current = (ExportedPreferences) result.node(path);
				String key = decoded[1];
				current.put(key, value);
			}
		}
		if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
			PrefsMessages.message("Converted preferences file to IExportedPreferences tree: " + ((ExportedPreferences) result).toDeepDebugString()); //$NON-NLS-1$
		return result;
	}

	/*
	 * excludesList is guaranteed not to be null
	 */
	private SortedProperties convertToProperties(IEclipsePreferences preferences, final String[] excludesList) throws BackingStoreException {
		final SortedProperties result = new SortedProperties();
		final int baseLength = preferences.absolutePath().length();

		// create a visitor to do the export
		IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() {
			@Override
			public boolean visit(IEclipsePreferences node) throws BackingStoreException {
				// don't store defaults
				String absolutePath = node.absolutePath();
				String scope = getScope(absolutePath);
				if (DefaultScope.SCOPE.equals(scope))
					return false;
				String path = absolutePath.length() <= baseLength ? EMPTY_STRING : EclipsePreferences.makeRelative(absolutePath.substring(baseLength));
				// check the excludes list to see if this node should be considered
				for (int i = 0; i < excludesList.length; i++) {
					String exclusion = EclipsePreferences.makeRelative(excludesList[i]);
					if (path.startsWith(exclusion))
						return false;
				}
				boolean needToAddVersion = InstanceScope.SCOPE.equals(scope);
				// check the excludes list for each preference
				String[] keys = node.keys();
				for (int i = 0; i < keys.length; i++) {
					String key = keys[i];
					boolean ignore = false;
					for (int j = 0; !ignore && j < excludesList.length; j++)
						if (EclipsePreferences.encodePath(path, key).startsWith(EclipsePreferences.makeRelative(excludesList[j])))
							ignore = true;
					if (!ignore) {
						String value = node.get(key, null);
						if (value != null) {
							if (needToAddVersion) {
								String bundle = getBundleName(absolutePath);
								if (bundle != null) {
									String version = getBundleVersion(bundle);
									if (version != null)
										result.put(BUNDLE_VERSION_PREFIX + bundle, version);
								}
								needToAddVersion = false;
							}
							result.put(EclipsePreferences.encodePath(absolutePath, key), value);
						}
					}
				}
				return true;
			}
		};

		// start by visiting the root that we were passed in
		preferences.accept(visitor);

		// return the properties object
		return result;
	}

	/**
	 * Copy key/value pairs from the source to the destination. If the key list is null
	 * then copy all associations.
	 *
	 * If the depth is 0, then this operation is performed only on the source node. Otherwise
	 * it is performed on the source node's subtree.
	 *
	 * @param depth one of 0 or -1
	 */
	void copyFromTo(Preferences source, Preferences destination, String[] keys, int depth) throws BackingStoreException {
		String[] keysToCopy = keys == null ? source.keys() : keys;
		for (int i = 0; i < keysToCopy.length; i++) {
			String value = source.get(keysToCopy[i], null);
			if (value != null)
				destination.put(keysToCopy[i], value);
		}
		if (depth == 0)
			return;
		String[] children = source.childrenNames();
		for (int i = 0; i < children.length; i++)
			copyFromTo(source.node(children[i]), destination.node(children[i]), keys, depth);
	}

	public WeakReference<Object> applyRuntimeDefaults(String name, WeakReference<Object> pluginReference) {
		if (registryHelper == null)
			return null;
		return ((PreferenceServiceRegistryHelper) registryHelper).applyRuntimeDefaults(name, pluginReference);
	}

	private void initializeDefaultScopes() {
		defaultScopes.put(BundleDefaultsScope.SCOPE, new BundleDefaultPreferences());
		root.addChild(BundleDefaultsScope.SCOPE, null);
		defaultScopes.put(DefaultScope.SCOPE, new DefaultPreferences());
		root.addChild(DefaultScope.SCOPE, null);
		defaultScopes.put(InstanceScope.SCOPE, new InstancePreferences());
		root.addChild(InstanceScope.SCOPE, null);
		defaultScopes.put(ConfigurationScope.SCOPE, new ConfigurationPreferences());
		root.addChild(ConfigurationScope.SCOPE, null);
	}

	public IEclipsePreferences createNode(String key) {
		IScope scope = defaultScopes.get(key);
		if (scope == null) {
			if (registryHelper == null)
				return new EclipsePreferences(root, key);
			return ((PreferenceServiceRegistryHelper) registryHelper).createNode(root, key);
		}
		return scope.create(root, key);
	}


	@Override
	public void exportPreferences(IEclipsePreferences node, IPreferenceFilter[] filters, OutputStream stream) throws CoreException {
		if (filters == null || filters.length == 0)
			return;
		try {
			internalExport(node, filters, stream);
		} catch (BackingStoreException e) {
			throw new CoreException(createStatusError(PrefsMessages.preferences_exportProblems, e));
		}
	}


	@Override
	public IStatus exportPreferences(IEclipsePreferences node, OutputStream output, String[] excludesList) throws CoreException {
		// TODO investigate refactoring to merge with new #export(IEclipsePreferences, IPreferenceFilter[]) APIs
		if (node == null || output == null)
			throw new IllegalArgumentException();
		SortedProperties properties = null;
		if (excludesList == null)
			excludesList = new String[0];
		try {
			properties = convertToProperties(node, excludesList);
			if (properties.isEmpty())
				return Status.OK_STATUS;
			properties.put(VERSION_KEY, Float.toString(EXPORT_VERSION));
			properties.put(EXPORT_ROOT_PREFIX + node.absolutePath(), EMPTY_STRING);
		} catch (BackingStoreException e) {
			throw new CoreException(createStatusError(e.getMessage(), e));
		}
		try {
			properties.store(output, null);
		} catch (IOException e) {
			throw new CoreException(createStatusError(PrefsMessages.preferences_exportProblems, e));
		}
		return Status.OK_STATUS;
	}

	/*
	 * Give clients a chance to modify the tree before it is applied globally
	 */
	private IEclipsePreferences firePreApplyEvent(IEclipsePreferences tree) {
		if (registryHelper == null)
			return tree;
		final IEclipsePreferences[] result = new IEclipsePreferences[] {tree};
		ListenerList<PreferenceModifyListener> listeners = ((PreferenceServiceRegistryHelper) registryHelper).getModifyListeners();
		for (final PreferenceModifyListener listener : listeners) {
			ISafeRunnable job = new ISafeRunnable() {
				@Override
				public void handleException(Throwable exception) {
					// already logged in Platform#run()
				}

				@Override
				public void run() throws Exception {
					result[0] = listener.preApply(result[0]);
				}
			};
			SafeRunner.run(job);
		}
		return result[0];
	}


	@Override
	public String get(String key, String defaultValue, Preferences[] nodes) {
		if (nodes == null)
			return defaultValue;
		for (int i = 0; i < nodes.length; i++) {
			Preferences node = nodes[i];
			if (node != null) {
				String result = node.get(key, null);
				if (result != null)
					return result;
			}
		}
		return defaultValue;
	}


	@Override
	public boolean getBoolean(String qualifier, String key, boolean defaultValue, IScopeContext[] scopes) {
		String result = get(EclipsePreferences.decodePath(key)[1], null, getNodes(qualifier, key, scopes));
		return result == null ? defaultValue : Boolean.valueOf(result).booleanValue();
	}

	/*
	 * Return the name of the bundle from the given path.
	 * It is assumed that that path is:
	 * - absolute
	 * - in the instance scope
	 */
	String getBundleName(String path) {
		if (path.length() == 0 || path.charAt(0) != IPath.SEPARATOR)
			return null;
		int first = path.indexOf(IPath.SEPARATOR, 1);
		if (first == -1)
			return null;
		int second = path.indexOf(IPath.SEPARATOR, first + 1);
		return second == -1 ? path.substring(first + 1) : path.substring(first + 1, second);
	}

	/*
	 * Return the version for the bundle with the given name. Return null if it
	 * is not known or there is a problem.
	 */
	String getBundleVersion(String bundleName) {
		Bundle bundle = PreferencesOSGiUtils.getDefault().getBundle(bundleName);
		if (bundle != null) {
			Object version = bundle.getHeaders(EMPTY_STRING).get(Constants.BUNDLE_VERSION);
			if (version != null && version instanceof String)
				return (String) version;
		}
		return null;
	}


	@Override
	public byte[] getByteArray(String qualifier, String key, byte[] defaultValue, IScopeContext[] scopes) {
		String result = get(EclipsePreferences.decodePath(key)[1], null, getNodes(qualifier, key, scopes));
		return result == null ? defaultValue : Base64.decode(result.getBytes());
	}


	@Override
	public String[] getDefaultLookupOrder(String qualifier, String key) {
		LookupOrder order = defaultsRegistry.get(getRegistryKey(qualifier, key));
		return order == null ? null : order.getOrder();
	}


	@Override
	public double getDouble(String qualifier, String key, double defaultValue, IScopeContext[] scopes) {
		String value = get(EclipsePreferences.decodePath(key)[1], null, getNodes(qualifier, key, scopes));
		if (value == null)
			return defaultValue;
		try {
			return Double.parseDouble(value);
		} catch (NumberFormatException e) {
			return defaultValue;
		}
	}


	@Override
	public float getFloat(String qualifier, String key, float defaultValue, IScopeContext[] scopes) {
		String value = get(EclipsePreferences.decodePath(key)[1], null, getNodes(qualifier, key, scopes));
		if (value == null)
			return defaultValue;
		try {
			return Float.parseFloat(value);
		} catch (NumberFormatException e) {
			return defaultValue;
		}
	}


	@Override
	public int getInt(String qualifier, String key, int defaultValue, IScopeContext[] scopes) {
		String value = get(EclipsePreferences.decodePath(key)[1], null, getNodes(qualifier, key, scopes));
		if (value == null)
			return defaultValue;
		try {
			return Integer.parseInt(value);
		} catch (NumberFormatException e) {
			return defaultValue;
		}
	}




	@Override
	public long getLong(String qualifier, String key, long defaultValue, IScopeContext[] scopes) {
		String value = get(EclipsePreferences.decodePath(key)[1], null, getNodes(qualifier, key, scopes));
		if (value == null)
			return defaultValue;
		try {
			return Long.parseLong(value);
		} catch (NumberFormatException e) {
			return defaultValue;
		}
	}


	@Override
	public String[] getLookupOrder(String qualifier, String key) {
		String[] order = getDefaultLookupOrder(qualifier, key);
		// if there wasn't an exact match based on both qualifier and simple name
		// then do a lookup based only on the qualifier
		if (order == null && key != null)
			order = getDefaultLookupOrder(qualifier, null);
		if (order == null)
			order = DEFAULT_DEFAULT_LOOKUP_ORDER;
		return order;
	}

	private Preferences[] getNodes(final String qualifier, String key, final IScopeContext[] contexts) {
		String[] order = getLookupOrder(qualifier, key);
		final String childPath = EclipsePreferences.makeRelative(EclipsePreferences.decodePath(key)[0]);
		final ArrayList<Preferences> result = new ArrayList<>();
		for (int i = 0; i < order.length; i++) {
			final String scopeString = order[i];
			AtomicReference<IllegalStateException> error = new AtomicReference<>();
			SafeRunner.run(new ISafeRunnable() {

				private IScopeContext context;

				@Override
				public void run() throws Exception {
					boolean found = false;
					for (int j = 0; contexts != null && j < contexts.length; j++) {
						context = contexts[j];
						if (context != null && context.getName().equals(scopeString)) {
							Preferences node = context.getNode(qualifier);
							if (node != null) {
								found = true;
								if (childPath != null)
									node = node.node(childPath);
								result.add(node);
							}
						}
					}
					if (!found) {
						Preferences node = getRootNode().node(scopeString).node(qualifier);
						if (childPath != null)
							node = node.node(childPath);
						result.add(node);
					}
					found = false;
				}

				@Override
				public void handleException(Throwable exception) {
					// See bug 514333 and org.eclipse.core.internal.runtime.DataArea.assertLocationInitialized()
					// If we see an IllegalStateException flying and the explicit init is required, we should not continue
					if (context instanceof InstanceScope && exception instanceof IllegalStateException && Boolean.getBoolean("osgi.dataAreaRequiresExplicitInit")) { //$NON-NLS-1$
						error.set((IllegalStateException) exception);
					} else {
						log(new Status(IStatus.ERROR, Activator.PI_PREFERENCES, PrefsMessages.preferences_contextError, exception));
					}
				}
			});

			IllegalStateException illegalState = error.get();
			if (illegalState != null) {
				// See bug 514333: don't allow clients to read (empty) instance prefs if the instance area is not initialized yet
				throw illegalState;
			}
		}
		return result.toArray(new Preferences[result.size()]);
	}

	/*
	 * Convert the given qualifier and key into a key to use in the look-up registry.
	 */
	private String getRegistryKey(String qualifier, String key) {
		if (qualifier == null)
			throw new IllegalArgumentException();
		if (key == null)
			return qualifier;
		return qualifier + '/' + key;
	}

	@Override
	public IEclipsePreferences getRootNode() {
		return root;
	}

	/*
	 * Return the string which is the scope for the given path.
	 * Return the empty string if it cannot be determined.
	 */
	String getScope(String path) {
		if (path == null || path.length() == 0)
			return EMPTY_STRING;
		int startIndex = path.indexOf(IPath.SEPARATOR);
		if (startIndex == -1)
			return path;
		if (path.length() == 1)
			return EMPTY_STRING;
		int endIndex = path.indexOf(IPath.SEPARATOR, startIndex + 1);
		if (endIndex == -1)
			endIndex = path.length();
		return path.substring(startIndex + 1, endIndex);
	}


	@Override
	public String getString(String qualifier, String key, String defaultValue, IScopeContext[] scopes) {
		return get(EclipsePreferences.decodePath(key)[1], defaultValue, getNodes(qualifier, key, scopes));
	}


	@Override
	public IStatus importPreferences(InputStream input) throws CoreException {
		if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
			PrefsMessages.message("Importing preferences..."); //$NON-NLS-1$
		return applyPreferences(readPreferences(input));
	}

	/**
	 * Filter the given tree so it only contains values which apply to the specified filters
	 * then apply the resulting tree to the main preference tree.
	 */
	private void internalApply(IEclipsePreferences tree, IPreferenceFilter[] filters) throws BackingStoreException {
		ArrayList<IEclipsePreferences> trees = new ArrayList<>();
		for (int i = 0; i < filters.length; i++)
			trees.add(trimTree(tree, filters[i]));
		// merge the union of the matching filters
		IEclipsePreferences toApply = mergeTrees(trees.toArray(new IEclipsePreferences[trees.size()]));

		// fire an event to give people a chance to modify the tree
		toApply = firePreApplyEvent(toApply);

		// actually apply the settings
		IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() {
			@Override
			public boolean visit(IEclipsePreferences node) throws BackingStoreException {
				String[] keys = node.keys();
				if (keys.length == 0)
					return true;
				copyFromTo(node, getRootNode().node(node.absolutePath()), keys, 0);
				return true;
			}
		};
		toApply.accept(visitor);
	}

	/**
	 * Take the preference tree and trim it so it only holds values applying to the given filters.
	 * Then export the resulting tree to the given output stream.
	 */
	private void internalExport(IEclipsePreferences node, IPreferenceFilter filters[], OutputStream output) throws BackingStoreException, CoreException {
		ArrayList<IEclipsePreferences> trees = new ArrayList<>();
		for (int i = 0; i < filters.length; i++)
			trees.add(trimTree(node, filters[i]));
		IEclipsePreferences toExport = mergeTrees(trees.toArray(new IEclipsePreferences[trees.size()]));
		exportPreferences(toExport, output, (String[]) null);
	}

	/*
	 * Return true if the given tree contains information that the specified filter is interested
	 * in, and false otherwise.
	 */
	private boolean internalMatches(IEclipsePreferences tree, IPreferenceFilter filter) throws BackingStoreException {
		String[] scopes = filter.getScopes();
		if (scopes == null)
			throw new IllegalArgumentException();
		String treePath = tree.absolutePath();
		// see if this node is applicable by going over all our scopes
		for (int i = 0; i < scopes.length; i++) {
			String scope = scopes[i];
			Map<String, PreferenceFilterEntry[]> mapping = filter.getMapping(scope);
			// if the mapping is null then we match everything
			if (mapping == null) {
				// if we are the root check to see if the scope exists
				if (tree.parent() == null && tree.nodeExists(scope)) {
					if (containsKeys((IEclipsePreferences) tree.node(scope)))
						return true;
				}
				// otherwise check to see if we are in the right scope
				if (scopeMatches(scope, tree) && containsKeys(tree))
					return true;
				continue;
			}
			// iterate over the list of declared nodes
			for (Iterator<String> iter = mapping.keySet().iterator(); iter.hasNext();) {
				String nodePath = iter.next();
				String nodeFullPath = '/' + scope + '/' + nodePath;
				// if this subtree isn't in a hierarchy we are interested in, then go to the next one
				if (!nodeFullPath.startsWith(treePath))
					continue;
				// get the child node
				String childPath = nodeFullPath.substring(treePath.length());
				childPath = EclipsePreferences.makeRelative(childPath);
				if (tree.nodeExists(childPath)) {
					PreferenceFilterEntry[] entries;
					// protect against wrong classes since this is user-code
					try {
						entries = mapping.get(nodePath);
					} catch (ClassCastException e) {
						log(createStatusError(PrefsMessages.preferences_classCastFilterEntry, e));
						continue;
					}
					// if there are no entries defined then we return false even if we
					// are supposed to match on the existence of the node as a whole (bug 88820)
					Preferences child = tree.node(childPath);
					if (entries == null) {
						if (child.keys().length != 0 || child.childrenNames().length != 0)
							return true;
					} else {
						// otherwise check to see if we have any applicable keys
						for (int j = 0; j < entries.length; j++) {
							if (entries[j] == null)
								continue;
							if (entries[j].getMatchType() == null) {
								if (child.get(entries[j].getKey(), null) != null)
									return true;
							} else if (internalMatchesWithMatchType(entries[j], child.keys()))
								return true;
						}
					}
				}
			}
		}
		return false;
	}

	/*
	 * Internal method that collects the matching filters for the given tree and returns them.
	 */
	private IPreferenceFilter[] internalMatches(IEclipsePreferences tree, IPreferenceFilter[] filters) throws BackingStoreException {
		ArrayList<IPreferenceFilter> result = new ArrayList<>();
		for (int i = 0; i < filters.length; i++)
			if (internalMatches(tree, filters[i]))
				result.add(filters[i]);
		return result.toArray(new IPreferenceFilter[result.size()]);
	}

	/*
	 * Internal method that check the matching preferences for entry with specific match type.
	 */
	private boolean internalMatchesWithMatchType(PreferenceFilterEntry entry, String[] keys) {
		if (keys == null || keys.length == 0)
			return false;
		String key = entry.getKey();
		String matchType = entry.getMatchType();
		if (!matchType.equalsIgnoreCase(MATCH_TYPE_PREFIX))
			return false;
		for (int i = 0; i < keys.length; i++) {
			if (keys[i].startsWith(key))
				return true;
		}
		return false;
	}

	/*
	 * Returns a boolean value indicating whether or not the given Properties
	 * object is the result of a preference export previous to Eclipse 3.0.
	 *
	 * Check the contents of the file. In Eclipse 3.0 we printed out a file
	 * version key.
	 */
	private boolean isLegacy(Properties properties) {
		return properties.getProperty(VERSION_KEY) == null;
	}


	@Override
	public IPreferenceFilter[] matches(IEclipsePreferences tree, IPreferenceFilter[] filters) throws CoreException {
		if (filters == null || filters.length == 0)
			return new IPreferenceFilter[0];
		try {
			return internalMatches(tree, filters);
		} catch (BackingStoreException e) {
			throw new CoreException(createStatusError(PrefsMessages.preferences_matching, e));
		}
	}

	private IEclipsePreferences mergeTrees(IEclipsePreferences[] trees) throws BackingStoreException {
		if (trees.length == 1)
			return trees[0];
		final IEclipsePreferences result = ExportedPreferences.newRoot();
		if (trees.length == 0)
			return result;
		IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() {
			@Override
			public boolean visit(IEclipsePreferences node) throws BackingStoreException {
				Preferences destination = result.node(node.absolutePath());
				copyFromTo(node, destination, null, 0);
				return true;
			}
		};
		for (int i = 0; i < trees.length; i++)
			trees[i].accept(visitor);
		return result;
	}


	@Override
	public IExportedPreferences readPreferences(InputStream input) throws CoreException {
		if (input == null)
			throw new IllegalArgumentException();

		if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
			PrefsMessages.message("Reading preferences from stream..."); //$NON-NLS-1$

		// read the file into a properties object
		Properties properties = new Properties();
		try {
			properties.load(input);
		} catch (IOException e) {
			throw new CoreException(createStatusError(PrefsMessages.preferences_importProblems, e));
		} catch (IllegalArgumentException e) {
			throw new CoreException(createStatusError(PrefsMessages.preferences_importProblems, e));
		} finally {
			try {
				input.close();
			} catch (IOException e) {
				// ignore
			}
		}

		// an empty file is an invalid file format
		if (properties.isEmpty())
			throw new CoreException(createStatusError(PrefsMessages.preferences_invalidFileFormat, null));

		// manipulate the file if it from a legacy preference export
		if (isLegacy(properties)) {
			if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
				PrefsMessages.message("Read legacy preferences file, converting to 3.0 format..."); //$NON-NLS-1$
			properties = convertFromLegacy(properties);
		} else {
			if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
				PrefsMessages.message("Read preferences file."); //$NON-NLS-1$
			properties.remove(VERSION_KEY);
		}

		// convert the Properties object into an object to return
		return convertFromProperties(properties);
	}

	/**
	 * Return true if the given node is in the specified scope and false otherwise.
	 */
	private boolean scopeMatches(String scope, IEclipsePreferences tree) {
		// the root isn't in any scope
		if (tree.parent() == null)
			return false;
		// fancy math to get the first segment of the path
		String path = tree.absolutePath();
		int index = path.indexOf('/', 1);
		String sub = path.substring(1, index == -1 ? path.length() : index);
		return scope.equals(sub);
	}


	@Override
	public void setDefaultLookupOrder(String qualifier, String key, String[] order) {
		String registryKey = getRegistryKey(qualifier, key);
		if (order == null)
			defaultsRegistry.remove(registryKey);
		else {
			LookupOrder obj = new LookupOrder(order);
			defaultsRegistry.put(registryKey, obj);
		}
	}

	public void setRegistryHelper(Object registryHelper) {
		if (this.registryHelper != null && this.registryHelper != registryHelper)
			((PreferenceServiceRegistryHelper) this.registryHelper).stop();
		this.registryHelper = registryHelper;
	}

	/**
	 * Shares all duplicate equal strings referenced by the preference service.
	 */
	void shareStrings() {
		long now = System.currentTimeMillis();
		if (now - lastStringSharing < STRING_SHARING_INTERVAL)
			return;
		StringPool pool = new StringPool();
		root.shareStrings(pool);
		if (EclipsePreferences.DEBUG_PREFERENCE_GENERAL)
			System.out.println("Preference string sharing saved: " + pool.getSavedStringCount()); //$NON-NLS-1$
		lastStringSharing = now;
	}

	/*
	 * Return a tree which contains only nodes and keys which are applicable to the given filter.
	 */
	private IEclipsePreferences trimTree(IEclipsePreferences tree, IPreferenceFilter filter) throws BackingStoreException {
		IEclipsePreferences result = (IEclipsePreferences) ExportedPreferences.newRoot().node(tree.absolutePath());
		String[] scopes = filter.getScopes();
		if (scopes == null)
			throw new IllegalArgumentException();
		String treePath = tree.absolutePath();
		// see if this node is applicable by going over all our scopes
		for (int i = 0; i < scopes.length; i++) {
			String scope = scopes[i];
			Map<String, PreferenceFilterEntry[]> mapping = filter.getMapping(scope);
			// if the mapping is null then copy everything if the scope matches
			if (mapping == null) {
				// if we are the root node then check our children
				if (tree.parent() == null && tree.nodeExists(scope))
					copyFromTo(tree.node(scope), result.node(scope), null, -1);
				// ensure we are in the correct scope
				else if (scopeMatches(scope, tree))
					copyFromTo(tree, result, null, -1);
				continue;
			}
			// iterate over the list of declared nodes
			for (Iterator<String> iter = mapping.keySet().iterator(); iter.hasNext();) {
				String nodePath = iter.next();
				String nodeFullPath = '/' + scope + '/' + nodePath;
				// if this subtree isn't in a hierarchy we are interested in, then go to the next one
				if (!nodeFullPath.startsWith(treePath))
					continue;
				// get the child node
				String childPath = nodeFullPath.substring(treePath.length());
				childPath = EclipsePreferences.makeRelative(childPath);
				if (tree.nodeExists(childPath)) {
					Preferences child = tree.node(childPath);
					PreferenceFilterEntry[] entries;
					// protect against wrong classes since this is passed in by the user
					try {
						entries = mapping.get(nodePath);
					} catch (ClassCastException e) {
						log(createStatusError(PrefsMessages.preferences_classCastFilterEntry, e));
						continue;
					}
					String[] keys = null;
					if (entries != null) {
						ArrayList<String> list = new ArrayList<>();
						for (int j = 0; j < entries.length; j++) {
							if (entries[j] != null)
								addMatchedKeys(list, entries[j], child.keys());
						}
						keys = list.toArray(new String[list.size()]);
					}
					// do infinite depth if there are no keys specified since the parent matched.
					copyFromTo(tree.node(childPath), result.node(childPath), keys, keys == null ? -1 : 0);
				}
			}
		}
		return result;
	}

	/*
	 * Internal method that adds to the given list the matching preferences for entry with or without specific match type.
	 */
	private void addMatchedKeys(ArrayList<String> list, PreferenceFilterEntry entry, String[] keys) {
		String matchType = entry.getMatchType();
		if (matchType == null) {
			list.add(entry.getKey());
			return;
		}
		if (keys == null)
			return;
		String key = entry.getKey();
		for (int i = 0; i < keys.length; i++) {
			if (matchType.equals(MATCH_TYPE_PREFIX) && keys[i].startsWith(key))
				list.add(keys[i]);
		}
	}

	/**
	 * Compares two plugin version identifiers to see if their preferences
	 * are compatible.  If they are not compatible, a warning message is
	 * added to the given multi-status, according to the following rules:
	 *
	 * - plugins that differ in service number: no status
	 * - plugins that differ in minor version: WARNING status
	 * - plugins that differ in major version:
	 * 	- where installed plugin is newer: WARNING status
	 * 	- where installed plugin is older: ERROR status
	 * @param bundle the name of the bundle
	 * @param pref The version identifier of the preferences to be loaded
	 * @param installed The version identifier of the installed plugin
	 */
	IStatus validatePluginVersions(String bundle, PluginVersionIdentifier pref, PluginVersionIdentifier installed) {
		if (installed.getMajorComponent() == pref.getMajorComponent() && installed.getMinorComponent() == pref.getMinorComponent())
			return null;
		int severity;
		if (installed.getMajorComponent() < pref.getMajorComponent())
			severity = IStatus.ERROR;
		else
			severity = IStatus.WARNING;
		String msg = NLS.bind(PrefsMessages.preferences_incompatible, (new Object[] {pref, bundle, installed}));
		return new Status(severity, PrefsMessages.OWNER_NAME, 1, msg, null);
	}

	public IStatus validateVersions(IPath path) {
		final MultiStatus result = new MultiStatus(PrefsMessages.OWNER_NAME, IStatus.INFO, PrefsMessages.preferences_validate, null);
		IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() {
			@Override
			public boolean visit(IEclipsePreferences node) {
				if (!(node instanceof ExportedPreferences))
					return false;

				// calculate the version in the file
				ExportedPreferences realNode = (ExportedPreferences) node;
				String version = realNode.getVersion();
				if (version == null || !PluginVersionIdentifier.validateVersion(version).isOK())
					return true;
				PluginVersionIdentifier versionInFile = new PluginVersionIdentifier(version);

				// calculate the version of the installed bundle
				String bundleName = getBundleName(node.absolutePath());
				if (bundleName == null)
					return true;
				String stringVersion = getBundleVersion(bundleName);
				if (stringVersion == null || !PluginVersionIdentifier.validateVersion(stringVersion).isOK())
					return true;
				PluginVersionIdentifier versionInMemory = new PluginVersionIdentifier(stringVersion);

				// verify the versions based on the matching rules
				IStatus verification = validatePluginVersions(bundleName, versionInFile, versionInMemory);
				if (verification != null)
					result.add(verification);

				return true;
			}
		};

		InputStream input = null;
		try {
			input = new BufferedInputStream(new FileInputStream(path.toFile()));
			IExportedPreferences prefs = readPreferences(input);
			prefs.accept(visitor);
		} catch (FileNotFoundException e) {
			// ignore...if the file does not exist then all is OK
		} catch (CoreException e) {
			result.add(createStatusError(PrefsMessages.preferences_validationException, e));
		} catch (BackingStoreException e) {
			result.add(createStatusError(PrefsMessages.preferences_validationException, e));
		}
		return result;
	}

	/*
	 * Return the default search lookup order for when nothing is set.
	*/
	public String[] getDefaultDefaultLookupOrder() {
		return DEFAULT_DEFAULT_LOOKUP_ORDER;
	}

	/*
	  * Set the default search order to use when there is nothing else set. Clients should not
	  * call this method because it is in an internal class and has been created solely for use by
	  * the org.eclipse.core.resources bundle in response to this bug:
	  *     https://bugs.eclipse.org/330320
	  */
	public void setDefaultDefaultLookupOrder(String[] order) {
		// shouldn't happen but let's protect against an NPE.
		if (order == null)
			order = new String[0];
		DEFAULT_DEFAULT_LOOKUP_ORDER = order;
	}
}
