package org.eclipse.ui.internal.registry;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */
import java.io.*;
import java.text.Collator;
import java.util.*;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.*;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.ListenerList;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.*;
import org.eclipse.ui.internal.*;
import org.eclipse.ui.internal.misc.*;

/**
 * Provides access to the collection of defined editors for
 * resource types.
 */
public class EditorRegistry implements IEditorRegistry {

	/* Cached images - these include images from registered editors (via plugins) and others
	 * hence this table is not one to one with the mappings table. It is in fact a superset
	 * of the keys one would find in typeEditorMappings
	 */
	private Map extensionImages = new HashMap();
	
	/* Vector of EditorDescriptor - all the editors loaded from plugin files.
	 * The list is kept in order to be able to show in the editor selection dialog of the resource associations page.
	 */
	private List sortedEditorsFromPlugins = new ArrayList();

	// Map of EditorDescriptor - map editor id to editor.
	private Map mapIDtoEditor = initialIdToEditorMap(10);

	// Map of FileEditorMapping (extension to FileEditorMapping)
	private EditorMap typeEditorMappings;

	// List for prop changed listeners.
	private ListenerList propChangeListeners = new ListenerList();

	// Key for the EditorID save as a IFile persistent property
	private static final QualifiedName EDITOR_KEY = new QualifiedName("org.eclipse.ui.internal.registry.ResourceEditorRegistry","EditorProperty");//$NON-NLS-2$//$NON-NLS-1$
/**
 * Return an instance of the receiver.
 */
public EditorRegistry() {
	super();
	initializeFromStorage();
}
/**
 * Add an editor for the given extensions with the specified (possibly null)
 * extended type. The editor is being registered from a plugin
 *
 * @param editor        The description of the editor (as obtained 
 *                      from the plugin file and built by the registry reader)
 * @param extensions    Collection of file extensions the editor applies to
 * @param filenames     Collection of filenames the editor applies to
 * @param bDefault      Indicates whether the editor should be made the default editor
 *                      and hence appear first inside a FileEditorMapping
 *
 * This method is not API and should not be called outside the workbench code.
 */
public void addEditorFromPlugin(EditorDescriptor editor, 
	List extensions, List filenames, boolean bDefault) {

	// record it in our quick reference list
	sortedEditorsFromPlugins.add(editor);

	// add it to the table of mappings
	Iterator enum = extensions.iterator();
	while(enum.hasNext()) {
		String fileExtension = (String)enum.next();
		
		if (fileExtension != null && fileExtension.length()>0) {
			FileEditorMapping mapping = getMappingFor("*." + fileExtension);//$NON-NLS-1$
			if (mapping == null) {  // no mapping for that extension
				mapping = new FileEditorMapping(fileExtension);
				typeEditorMappings.putDefault(mappingKeyFor(mapping), mapping);
			}
			mapping.addEditor(editor);
			if (bDefault)
				mapping.setDefaultEditor(editor);
		}
	}

	// add it to the table of mappings
	enum = filenames.iterator();
	while(enum.hasNext()) {
		String filename = (String)enum.next();
		
		if (filename != null && filename.length() > 0) {
			FileEditorMapping mapping = getMappingFor(filename);
			if (mapping == null) {  // no mapping for that extension
				String name;
				String extension;
				int index = filename.indexOf('.');
				if (index < 0) {
					name = filename;
					extension = "";//$NON-NLS-1$
				}
				else {
					name = filename.substring(0, index);
					extension = filename.substring(index + 1);
				}
				mapping = new FileEditorMapping(name, extension);
				typeEditorMappings.putDefault(mappingKeyFor(mapping), mapping);
			}
			mapping.addEditor(editor);
			if (bDefault)
				mapping.setDefaultEditor(editor);
		}
	}

	// Update editor map.
	mapIDtoEditor.put(editor.getId(), editor);
}
/**
 * Add external editors to the editor mapping.
 */
private void addExternalEditorsToEditorMap() {
	IEditorDescriptor desc = null;
	
	// Add registered editors (may include external editors).
	FileEditorMapping maps[] = typeEditorMappings.allMappings();
	for (int i = 0; i < maps.length; i++) {
		FileEditorMapping map = maps[i];
		IEditorDescriptor [] descArray = map.getEditors();
		for (int n = 0; n < descArray.length; n++) {
			desc = descArray[n];
			mapIDtoEditor.put(desc.getId(), desc);
		}
	}
}
/* (non-Javadoc)
 * Method declared on IEditorRegistry.
 */
public void addPropertyListener(IPropertyListener l) {
	propChangeListeners.add(l);
}
/* (non-Javadoc)
 * Method declared on IEditorRegistry.
 */
public IEditorDescriptor findEditor(String id) {
	return (IEditorDescriptor)mapIDtoEditor.get(id);
}
/**
 * Fires a property changed event.
 */
private void firePropertyChange(final int type) {
	Object [] array = propChangeListeners.getListeners();
	for (int nX = 0; nX < array.length; nX ++) {
		final IPropertyListener l = (IPropertyListener)array[nX];
		Platform.run(new SafeRunnable() {
			public void run() {
				l.propertyChanged(EditorRegistry.this, type);
			}
			public void handleException(Throwable e) {
				super.handleException(e);
				//If and unexpected exception happens, remove it
				//to make sure the workbench keeps running.
				propChangeListeners.remove(l);
			}
		});
	}
}
/* (non-Javadoc)
 * Method declared on IEditorRegistry.
 */
public IEditorDescriptor getDefaultEditor() {
	// Find the default editor descriptor and return it.
	IEditorDescriptor desc = findEditor(IWorkbenchConstants.DEFAULT_EDITOR_ID);
	if (desc != null)
		return desc;

	// Panic: the default editor cannot be found.
	MessageDialog.openError((Shell)null, 
		"Editor Problems", //$NON-NLS-1$
		"Unable to find default editor.");//$NON-NLS-1$
	return null;
}
/* (non-Javadoc)
 * Method declared on IEditorRegistry.
 */
public IEditorDescriptor getDefaultEditor(String filename) {
	FileEditorMapping[] mapping = getMappingForFilename(filename);
	IEditorDescriptor desc = null;
	if (mapping[0] != null)
		desc = mapping[0].getDefaultEditor();
	if (desc == null && mapping[1] != null)
		desc = mapping[1].getDefaultEditor();
	return desc;
}
/* (non-Javadoc)
 * Method declared on IEditorRegistry.
 */
public IEditorDescriptor getDefaultEditor(IFile file) {
	// Try file specific editor.
	try {
		String editorID = file.getPersistentProperty(EDITOR_KEY);
		if (editorID != null) {
			IEditorDescriptor desc = findEditor(editorID);
			if (desc != null)
				return desc;
		}
	} catch (CoreException e) {
	}
	
	// Try lookup with filename
	return getDefaultEditor(file.getName());
}
/**
 * Returns the default file image.
 */
private ImageDescriptor getDefaultImage() {
	return WorkbenchImages.getImageDescriptor(ISharedImages.IMG_OBJ_FILE);
}
/* (non-Javadoc)
 * Method declared on IEditorRegistry.
 */
public IEditorDescriptor[] getEditors(String filename) {
	IEditorDescriptor[] editors = new IEditorDescriptor[0];
	IEditorDescriptor[] filenameEditors = editors;
	IEditorDescriptor[] extensionEditors = editors;

	FileEditorMapping mapping[] = getMappingForFilename(filename);
	if (mapping[0] != null) {
		editors = mapping[0].getEditors();
		if (editors != null)
			filenameEditors = editors;
	}
	if (mapping[1] != null) {
		editors = mapping[1].getEditors();
		if (editors != null)
			extensionEditors = editors;
	}

	editors = new IEditorDescriptor[filenameEditors.length + extensionEditors.length];
	System.arraycopy(filenameEditors, 0, editors, 0, filenameEditors.length);
	System.arraycopy(extensionEditors, 0, editors, filenameEditors.length, extensionEditors.length);
	return editors;
}
/* (non-Javadoc)
 * Method declared on IEditorRegistry.
 */
public IEditorDescriptor[] getEditors(IFile element) {
	return getEditors(element.getName());
}
/* (non-Javadoc)
 * Method declared on IEditorRegistry.
 */
public IFileEditorMapping[] getFileEditorMappings() {
	FileEditorMapping[] array = typeEditorMappings.allMappings();
	final Collator collator = Collator.getInstance();
	Arrays.sort(array,new Comparator() {
		public int compare(Object o1, Object o2) {
			String s1 = ((FileEditorMapping)o1).getLabel();
			String s2 = ((FileEditorMapping)o2).getLabel();
			return collator.compare(s1, s2);
		}
	});
	return array;
}
/* (non-Javadoc)
 * Method declared on IEditorRegistry.
 */
public ImageDescriptor getImageDescriptor(String filename) {
	if (filename == null)
		return getDefaultImage();

	// Lookup in the cache first... 
	String key = mappingKeyFor(filename);
	ImageDescriptor anImage = (ImageDescriptor)extensionImages.get(key);
	if (anImage != null)
		return anImage;

	// See if we have a mapping for the filename or extension
	FileEditorMapping[] mapping = getMappingForFilename(filename);
	for (int i = 0; i < 2; i++) {
		if (mapping[i] != null) {
			// Lookup in the cache first...
			String mappingKey = mappingKeyFor(mapping[i]);
			ImageDescriptor mappingImage = (ImageDescriptor)extensionImages.get(key);
			if (mappingImage != null)
				return mappingImage;
			// Create it and cache it
			IEditorDescriptor editor = mapping[i].getDefaultEditor();
			if (editor != null) {
				mappingImage = editor.getImageDescriptor();
				extensionImages.put(mappingKey, mappingImage);
				return mappingImage;
			}
		}
	}   

	// Nothing - time to look externally for the icon
	anImage = getSystemEditorImageDescriptor(filename);
	if (anImage == null)
		anImage = getDefaultImage();
	extensionImages.put(key, anImage);
	return anImage;
}
/* (non-Javadoc)
 * Method declared on IEditorRegistry.
 */
public ImageDescriptor getImageDescriptor(IFile element) {
	return getImageDescriptor(element.getName());
}
/**
 * Find the file editor mapping for the type. Returns
 * null if not found.
 */
private FileEditorMapping getMappingFor(String type) {
	if (type == null)
		return null;
	String key = mappingKeyFor(type);
	return (FileEditorMapping) typeEditorMappings.get(key);
}
/**
 * Find the file editor mappings for the given filename.
 *
 * Return an array of two FileEditorMapping items, where
 * the first mapping is for the entire filename, and the
 * second mapping is for the filename's extension only.
 * These items can be null if no mapping exist on the
 * filename and/or filename's extension.
 */
private FileEditorMapping[] getMappingForFilename(String filename) {
	FileEditorMapping[] mapping = new FileEditorMapping[2];
	
	// Lookup on entire filename
	mapping[0] = getMappingFor(filename);
	
	// Lookup on filename's extension
	int index = filename.lastIndexOf('.');
	if (index > -1) {
		String extension = filename.substring(index);
		mapping[1] = getMappingFor("*" + extension);//$NON-NLS-1$
	}
	
	return mapping;
}
/* 
 * WARNING!
 * The image described by each editor descriptor is *not* known by
 * the workbench's graphic registry.
 * Therefore clients must take care to ensure that if they access
 * any of the images held by these editors that they also dispose them
 */
 
public IEditorDescriptor[] getSortedEditorsFromOS() {
	List externalEditors = new ArrayList();
	Program [] programs = Program.getPrograms();

	for (int i = 0; i < programs.length; i++){
		//1FPLRL2: ITPUI:WINNT - NOTEPAD editor cannot be launched
		//Some entries start with %SystemRoot%
		//For such cases just use the file name as they are generally
		//in directories which are on the path
		/*if (fileName.charAt(0) == '%') {
			fileName = name + ".exe";
		}   */
		
		EditorDescriptor editor = new EditorDescriptor();
		editor.setProgram(programs[i]);

		// determine the program icon this editor would need (do not let it be cached in the workbench registry)
		ImageDescriptor desc = new ExternalProgramImageDescriptor(programs[i]);
		editor.setImageDescriptor(desc);
		externalEditors.add(editor);
	}

	Object[] tempArray = sortEditors(externalEditors);
	IEditorDescriptor[] array = new IEditorDescriptor[externalEditors.size()];
	for (int i = 0; i < tempArray.length; i++){
		array[i] = (IEditorDescriptor)tempArray[i];
	}
	return array;
}
/**
 *
 */
public IEditorDescriptor[] getSortedEditorsFromPlugins() {
	IEditorDescriptor[] array = new IEditorDescriptor[sortedEditorsFromPlugins.size()];
	sortedEditorsFromPlugins.toArray(array);
	return array;   
		
}
/*
 * Return the image descriptor of the system editor
 * that is registered with the OS to edit files of
 * this type. Null if none can be found.
 */
public ImageDescriptor getSystemEditorImageDescriptor(String filename) {
	Program externalProgram = null;
	int extensionIndex = filename.lastIndexOf('.');
	if (extensionIndex >= 0)
		externalProgram = Program.findProgram(filename.substring(extensionIndex));
	if (externalProgram == null)
		return null;
	else
		return new ExternalProgramImageDescriptor(externalProgram);
}
/*
 * Return the image descriptor of the system editor
 * that is registered with the OS to edit files of
 * this type. Null if none can be found.
 */
public ImageDescriptor getSystemEditorImageDescriptor(IFile element) {
	return getSystemEditorImageDescriptor(element.getName());
}
/**
 * Answer an intial id to editor map.
 */
private HashMap initialIdToEditorMap(int initialSize) {
	HashMap map = new HashMap(initialSize);
	map.put(IWorkbenchConstants.SYSTEM_EDITOR_ID, EditorDescriptor.getSystemEditorDescriptor());
	return map;
}
private void initializeFromStorage () {
	typeEditorMappings = new EditorMap();
	extensionImages = new HashMap();
	
	//Get editors from the registry
	EditorRegistryReader registryReader = new EditorRegistryReader();
	registryReader.addEditors(true, this);
	sortInternalEditors();
	rebuildInternalEditorMap();

	IWorkbench workbench = PlatformUI.getWorkbench();
	IPreferenceStore store = workbench.getPreferenceStore();
	String defaultEditors = store.getString(IPreferenceConstants.DEFAULT_EDITORS);
	String chachedDefaultEditors = store.getString(IPreferenceConstants.DEFAULT_EDITORS_CACHE);
		
	//If defaults has changed load it afterwards so it overrides the users associations.
	if(defaultEditors == null || defaultEditors.equals(chachedDefaultEditors)) {
		setProductDefaults(defaultEditors);
		loadAssociations(); //get saved earlier state
	} else {
		loadAssociations(); //get saved earlier state
		setProductDefaults(defaultEditors);
		store.putValue(IPreferenceConstants.DEFAULT_EDITORS_CACHE,defaultEditors);
	}
	addExternalEditorsToEditorMap();
}
/**
 * Set the default editors according to the preference store which
 * can be overwritten in the file properties.ini.
 */
private void setProductDefaults(String defaultEditors) {
	if(defaultEditors == null || defaultEditors.length() == 0)
		return;
		
	StringTokenizer extEditors = new StringTokenizer(defaultEditors,new Character(IPreferenceConstants.SEPARATOR).toString());
	while(extEditors.hasMoreTokens()) {
		String extEditor = extEditors.nextToken().trim();
		int index = extEditor.indexOf(':');
		if(extEditor.length() < 3 || index <= 0 || index >= (extEditor.length() - 1)) { 
			//Extension and id must have at least one char.
			WorkbenchPlugin.log("Error setting default editor. Could not parse '" + extEditor + "'. Default editors should be specified as '*.ext1:editorId1;*.ext2:editorId2'"); //$NON-NLS-1$
			return;
		}
		String ext = extEditor.substring(0,index).trim();
		String editorId = extEditor.substring(index + 1).trim();
		FileEditorMapping mapping = getMappingFor(ext);
		if(mapping == null) {
			WorkbenchPlugin.log("Error setting default editor. Could not find mapping for '" + ext + "'."); //$NON-NLS-1$
			continue;
		}
		EditorDescriptor editor = (EditorDescriptor)findEditor(editorId);
		if(editor == null) {
			WorkbenchPlugin.log("Error setting default editor. Could not find editor: '" + editorId + "'."); //$NON-NLS-1$
			continue;
		}
		mapping.setDefaultEditor(editor);
	}	
}
/**
 * Load the serialized resource associations
 * Return true if the operation was successful, false otherwise
 */
private boolean loadAssociations() {

	//Get the workbench plugin's working directory
	WorkbenchPlugin workbenchPlugin = WorkbenchPlugin.getDefault();
	IPath workbenchStatePath = workbenchPlugin.getStateLocation();

	//Get the editors and validate each one
	Map editorTable = new HashMap();
	Reader reader = null;
	IPreferenceStore store = WorkbenchPlugin.getDefault().getPreferenceStore();

	try {
		String xmlString = store.getString(IPreferenceConstants.EDITORS);
		if(xmlString == null || xmlString.length() == 0) {
			FileInputStream stream = new FileInputStream(workbenchStatePath.append(IWorkbenchConstants.EDITOR_FILE_NAME).toOSString());
			reader = new BufferedReader(new InputStreamReader(stream, "utf-8")); //$NON-NLS-1$
		} else {
			reader = new StringReader(xmlString);
		}
		XMLMemento memento = XMLMemento.createReadRoot(reader);
		EditorDescriptor editor;
		IMemento[] edMementos = memento.getChildren(IWorkbenchConstants.TAG_DESCRIPTOR);
		for (int i = 0; i < edMementos.length; i++) {
			editor = new EditorDescriptor();
			editor.loadValues(edMementos[i]);

			if (editor.getPluginID() != null) {
				//If the editor is from a plugin we use its ID to look it up in the mapping of editors we
				//have obtained from plugins. This allows us to verify that the editor is still valid
				//and allows us to get the editor description from the mapping table which has
				//a valid config element field.
				EditorDescriptor validEditorDescritor =
					(EditorDescriptor) mapIDtoEditor.get(editor.getId());
				if (validEditorDescritor != null) {
					editorTable.put(validEditorDescritor.getId(), validEditorDescritor);
				}
			} else { //This is either from a program or a user defined editor
				ImageDescriptor descriptor;
				if (editor.getProgram() == null)
					descriptor = new ProgramImageDescriptor(editor.getFileName(), 0);
				else
					descriptor = new ExternalProgramImageDescriptor(editor.getProgram());
				editor.setImageDescriptor(descriptor);
				editorTable.put(editor.getId(), editor);
			}
		}
	} catch (IOException e) {
		try {
			if (reader != null)
				reader.close();
		} catch (IOException ex) {
		}
		//Ignore this as the workbench may not yet have saved any state
		return false;
	} catch (WorkbenchException e) {
		ErrorDialog.openError(
			(Shell) null, 
			WorkbenchMessages.getString("EditorRegistry.errorTitle"),//$NON-NLS-1$
			WorkbenchMessages.getString("EditorRegistry.errorMessage"), //$NON-NLS-1$
			e.getStatus());
		return false;
	}

	//Get the resource types
	reader = null;
	try {
		String xmlString = store.getString(IPreferenceConstants.RESOURCES);
		if(xmlString == null || xmlString.length() == 0) {
			FileInputStream stream = new FileInputStream(
				workbenchStatePath
					.append(IWorkbenchConstants.RESOURCE_TYPE_FILE_NAME)
					.toOSString());
		 	reader = new BufferedReader(new InputStreamReader(stream, "utf-8")); //$NON-NLS-1$
		} else {
			reader = new StringReader(xmlString);
		}
		XMLMemento memento = XMLMemento.createReadRoot(reader);
		IMemento[] extMementos = memento.getChildren(IWorkbenchConstants.TAG_INFO);
		for (int i = 0; i < extMementos.length; i++) {
			String name = extMementos[i].getString(IWorkbenchConstants.TAG_NAME);
			if (name == null)
				name = "*";//$NON-NLS-1$
			String extension = extMementos[i].getString(IWorkbenchConstants.TAG_EXTENSION);
			IMemento[] idMementos =
				extMementos[i].getChildren(IWorkbenchConstants.TAG_EDITOR);
			String[] editorIDs = new String[idMementos.length];
			for (int j = 0; j < idMementos.length; j++) {
				editorIDs[j] = idMementos[j].getString(IWorkbenchConstants.TAG_ID);
			}
			idMementos =
				extMementos[i].getChildren(IWorkbenchConstants.TAG_DELETED_EDITOR);
			String[] deletedEditorIDs = new String[idMementos.length];
			for (int j = 0; j < idMementos.length; j++) {
				deletedEditorIDs[j] = idMementos[j].getString(IWorkbenchConstants.TAG_ID);
			}
			FileEditorMapping mapping = getMappingFor(name + "." + extension);//$NON-NLS-1$
			if (mapping == null) {
				mapping = new FileEditorMapping(name, extension);
			}
			List editors = new ArrayList();
			for (int j = 0; j < editorIDs.length; j++) {
				if (editorIDs[j] != null) {
					EditorDescriptor editor = (EditorDescriptor) editorTable.get(editorIDs[j]);
					if (editor != null) {
						editors.add(editor);
					}
				}
			}
			List deletedEditors = new ArrayList();
			for (int j = 0; j < deletedEditorIDs.length; j++) {
				if (deletedEditorIDs[j] != null) {
					EditorDescriptor editor = (EditorDescriptor) editorTable.get(deletedEditorIDs[j]);
					if (editor != null) {
						deletedEditors.add(editor);
					}
				}
			}

			// Add any new editors that have already been read from the registry
			// which were not deleted.
			IEditorDescriptor[] editorsArray = mapping.getEditors();
			for (int j = 0; j < editorsArray.length; j++) {
				if (!editors.contains(editorsArray[j]) && !deletedEditors.contains(editorsArray[j])) {
					editors.add(editorsArray[j]);
				}
			}

			mapping.setEditorsList(editors);
			mapping.setDeletedEditorsList(deletedEditors);
			typeEditorMappings.put(mappingKeyFor(mapping), mapping);
		}
	} catch (IOException e) {
		try {
			if (reader != null)
				reader.close();
		} catch (IOException ex) {
		}
		MessageDialog.openError(
			(Shell) null,
			WorkbenchMessages.getString("EditorRegistry.errorTitle"),//$NON-NLS-1$
			WorkbenchMessages.getString("EditorRegistry.errorMessage")); //$NON-NLS-1$
		return false;
	} catch (WorkbenchException e) {
		ErrorDialog.openError(
			(Shell) null, 
			WorkbenchMessages.getString("EditorRegistry.errorTitle"),//$NON-NLS-1$
			WorkbenchMessages.getString("EditorRegistry.errorMessage"), //$NON-NLS-1$
			e.getStatus());
		return false;
	}
	return true;
}
/*
 * 
 */
private String mappingKeyFor(String type) {
	//Unix issue
	return type.toLowerCase();
}
/**
 * Return a key that combines the file's name and extension
 * of the given mapping
 */
private String mappingKeyFor(FileEditorMapping mapping) {
	return mappingKeyFor(mapping.getName() + 
		(mapping.getExtension().length() == 0 ? "" : "." + mapping.getExtension()));//$NON-NLS-1$ //$NON-NLS-2$
}
/**
 * Rebuild the editor map
 */
private void rebuildEditorMap() {
	rebuildInternalEditorMap();
	addExternalEditorsToEditorMap();
}
/**
 * Rebuild the internal editor mapping.
 */
private void rebuildInternalEditorMap() 
{
	Iterator enum = null;
	IEditorDescriptor desc = null;
	
	// Allocate a new map.
	mapIDtoEditor = initialIdToEditorMap(mapIDtoEditor.size());

	// Add plugin editors.
	enum = sortedEditorsFromPlugins.iterator();
	while (enum.hasNext()) {
		desc = (IEditorDescriptor)enum.next();
		mapIDtoEditor.put(desc.getId(), desc);
	}
}
/* (non-Javadoc)
 * Method declared on IEditorRegistry.
 */
public void removePropertyListener(IPropertyListener l) {
	propChangeListeners.remove(l);
}
/**
 * Save the registry to the filesystem by serializing
 * the current resource associations.
 */
public void saveAssociations () {
	//Save the resource type descriptions
	List editors = new ArrayList();
	IPreferenceStore store = WorkbenchPlugin.getDefault().getPreferenceStore();
	
	XMLMemento memento = XMLMemento.createWriteRoot(IWorkbenchConstants.TAG_EDITORS);
	FileEditorMapping maps[] = typeEditorMappings.userMappings();
	for (int mapsIndex = 0; mapsIndex < maps.length; mapsIndex++) {
		FileEditorMapping type = (FileEditorMapping)maps[mapsIndex];
		IMemento editorMemento = memento.createChild(IWorkbenchConstants.TAG_INFO);
		editorMemento.putString(IWorkbenchConstants.TAG_NAME,type.getName());
		editorMemento.putString(IWorkbenchConstants.TAG_EXTENSION,type.getExtension());
		IEditorDescriptor[] editorArray = type.getEditors();
		for (int i = 0; i < editorArray.length; i++){
			EditorDescriptor editor = (EditorDescriptor)editorArray[i];
			if (!editors.contains(editor)) {
				editors.add(editor); 
			}
			IMemento idMemento = editorMemento.createChild(IWorkbenchConstants.TAG_EDITOR);
			idMemento.putString(IWorkbenchConstants.TAG_ID,editorArray[i].getId());
		}
		editorArray = type.getDeletedEditors();
		for (int i = 0; i < editorArray.length; i++){
			EditorDescriptor editor = (EditorDescriptor)editorArray[i];
			if (!editors.contains(editor)) {
				editors.add(editor); 
			}
			IMemento idMemento = editorMemento.createChild(IWorkbenchConstants.TAG_DELETED_EDITOR);
			idMemento.putString(IWorkbenchConstants.TAG_ID,editorArray[i].getId());
		}
	}
	Writer writer = null;
	try {
		writer = new StringWriter();
		memento.save(writer);
		writer.close();
		store.setValue(IPreferenceConstants.RESOURCES,writer.toString());
	} catch(IOException e) {
		try{
			if(writer != null) writer.close();
		} catch(IOException ex) {}
		MessageDialog.openError((Shell)null, 
			"Saving Problems", //$NON-NLS-1$
			"Unable to save resource associations.");//$NON-NLS-1$
		return;
	}   
	

	memento = XMLMemento.createWriteRoot(IWorkbenchConstants.TAG_EDITORS);
	Iterator enum = editors.iterator();
	while (enum.hasNext()) {
		EditorDescriptor editor = (EditorDescriptor)enum.next();
		IMemento editorMemento = memento.createChild(IWorkbenchConstants.TAG_DESCRIPTOR);
		editor.saveValues(editorMemento);
	}
	writer = null;
	try {
		writer = new StringWriter();
		memento.save(writer);
		writer.close();
		store.setValue(IPreferenceConstants.EDITORS,writer.toString());	
	} catch(IOException e) {
		try{
			if(writer != null) writer.close();
		} catch(IOException ex) {}
		MessageDialog.openError((Shell)null,
			"Error",//$NON-NLS-1$
			"Unable to save resource associations.");//$NON-NLS-1$
		return;
	}       
}
/* (non-Javadoc)
 * Method declared on IEditorRegistry.
 */
public void setDefaultEditor(IFile file, String editorID) {
	try {
		file.setPersistentProperty(EDITOR_KEY,editorID);
	} catch (CoreException e) {}
}
/**
 * Set the collection of FileEditorMappings. 
 * The given collection is converted into the internal hash table for faster lookup
 * Each mapping goes from an extension to the collection of editors that work on it.
 */
public void setFileEditorMappings(FileEditorMapping[] newResourceTypes) {
	typeEditorMappings = new EditorMap();
	for (int i = 0;i < newResourceTypes.length;i++) {
		FileEditorMapping mapping = newResourceTypes[i];
		typeEditorMappings.put(mappingKeyFor(mapping), mapping);
	}
	extensionImages = new HashMap();
	rebuildEditorMap();
	firePropertyChange(PROP_CONTENTS);
}
/* (non-Javadoc)
 * Method declared on IEditorRegistry.
 */
public void setDefaultEditor(String fileName, String editorId) {
	EditorDescriptor desc = (EditorDescriptor)findEditor(editorId);
	FileEditorMapping[] mapping = getMappingForFilename(fileName);
	if (mapping[0] != null)
		mapping[0].setDefaultEditor(desc);
	if (mapping[1] != null)
		mapping[1].setDefaultEditor(desc);		
}
/**
 * Alphabetically sort the internal editors
 */
private Object[] sortEditors(List unsortedList) {
	Object[] array = new Object[unsortedList.size()];
	unsortedList.toArray(array);
	
	Sorter s = new Sorter() {
		private Collator collator = Collator.getInstance();
		
		public boolean compare(Object o1, Object o2) {
			String s1 = ((IEditorDescriptor)o1).getLabel();
			String s2 = ((IEditorDescriptor)o2).getLabel();
			//Return true if elementTwo is 'greater than' elementOne
			return collator.compare(s2, s1) > 0;
		}
	};
	return s.sort(array);

}
/**
 * Alphabetically sort the internal editors
 */
private void sortInternalEditors() {
	Object[] array = sortEditors(sortedEditorsFromPlugins);
	sortedEditorsFromPlugins = new ArrayList();
	for (int i = 0; i < array.length; i++) {
		sortedEditorsFromPlugins.add(array[i]);
	}
}

/*
 * Map of FileEditorMapping (extension to FileEditorMapping)
 * Uses two java.util.HashMap: one keeps the
 * default which are set by the plugins and the other keeps the
 * changes made by the user through the preference page.
 */
private static class EditorMap {
	HashMap defaultMap = new HashMap();
	HashMap map = new HashMap();
	
	public void putDefault(String key, FileEditorMapping value) {
		defaultMap.put(key,value);
	}
	public void put(String key, FileEditorMapping value) {
		Object result = defaultMap.get(key);
		if(value.equals(result))
			map.remove(key);
		else
			map.put(key,value);
	}
	public FileEditorMapping get(String key) {
		Object result = map.get(key);
		if(result == null)
			result = defaultMap.get(key);
		return (FileEditorMapping)result;
	}
	public FileEditorMapping[] allMappings() {
		HashMap merge = (HashMap)defaultMap.clone();
		merge.putAll(map);
		Collection values = merge.values();
		FileEditorMapping result[] = new FileEditorMapping[values.size()];
		return (FileEditorMapping[])values.toArray(result);
	}
	public FileEditorMapping[] userMappings() {
		Collection values = map.values();
		FileEditorMapping result[] = new FileEditorMapping[values.size()];
		return (FileEditorMapping[])values.toArray(result);
	}	
}

}
