Merge branch 'master' of ssh://git.eclipse.org/gitroot/orion/org.eclipse.orion.client
diff --git a/bundles/org.eclipse.orion.client.core/web/js-tests/config/testcase.js b/bundles/org.eclipse.orion.client.core/web/js-tests/config/testcase.js
index d4a2dc3..897f33b 100644
--- a/bundles/org.eclipse.orion.client.core/web/js-tests/config/testcase.js
+++ b/bundles/org.eclipse.orion.client.core/web/js-tests/config/testcase.js
@@ -12,6 +12,7 @@
 define(['orion/assert', 'orion/Deferred', 'orion/testHelpers', 'orion/config', 'orion/serviceregistry', 'orion/pluginregistry'],
 		function(assert, Deferred, testHelpers, config, mServiceRegistry, mPluginRegistry) {
 	var ConfigAdminFactory = config.ConfigurationAdminFactory;
+	var Plugin = mPluginRegistry.Plugin;
 	var MANAGED_SERVICE = 'orion.cm.managedservice';
 
 	function MockPrefsService() {
@@ -49,15 +50,25 @@
 		};
 	}
 
-	var serviceRegistry, pluginRegistry, pluginStorage, configAdmin;
-	var setUp = function(storage) {
+	var serviceRegistry, preferences, pluginRegistry, pluginStorage, configAdmin;
+	var setUp = function(storage, omitConfigAdmin) {
 		serviceRegistry = new mServiceRegistry.ServiceRegistry();
-		configAdmin = new ConfigAdminFactory(serviceRegistry, new MockPrefsService()).getConfigurationAdmin();
+		preferences = new MockPrefsService();
 		pluginStorage = arguments.length ? storage : {};
 		pluginRegistry = new mPluginRegistry.PluginRegistry(serviceRegistry, pluginStorage);
+		if (typeof omitConfigAdmin === 'undefined' || !omitConfigAdmin) {
+			return new ConfigAdminFactory(serviceRegistry, pluginRegistry, preferences).getConfigurationAdmin().then(
+				function(createdConfigAdmin) {
+					configAdmin = createdConfigAdmin;
+				});
+		}
+		var d = new Deferred();
+		d.resolve();
+		return d;
 	},
 	tearDown = function() {
 		serviceRegistry = null;
+		preferences = null;
 		pluginRegistry = null;
 		pluginStorage = null;
 		configAdmin = null;
@@ -69,108 +80,98 @@
 	var tests = {};
 	tests['test ConfigurationAdmin.getConfiguration()'] = makeTest(function() {
 		var pid = 'test.pid';
-		return configAdmin.getConfiguration(pid).then(function(configuration) {
-			assert.strictEqual(configuration.getPid(), pid);
-		});
+		var configuration = configAdmin.getConfiguration(pid);
+		assert.strictEqual(configuration.getPid(), pid);
 	});
 
 	tests['test ConfigurationAdmin.listConfigurations()'] = makeTest(function() {
-		// create some configs
-		var configPromises = [];
+		var createdConfigs = [];
 		for (var i=0; i < 5; i++) {
-			configPromises.push( configAdmin.getConfiguration('orion.test.pid' + (i+1)) );
+			var config = configAdmin.getConfiguration('orion.test.pid' + (i+1));
+			config.update({foo: (i+1)});
+			createdConfigs.push(config);
 		}
-		return Deferred.all(configPromises).then(function(createdConfigs) {
-			createdConfigs.forEach(function(config, i) {
-				config.update({foo: i});
-			});
-			return configAdmin.listConfigurations().then(function(listedConfigs) {
-				assert.equal(createdConfigs.length, 5);
-				assert.equal(listedConfigs.length, 5);
-				assert.ok(createdConfigs.every(function(config) {
-					assert.ok(listedConfigs.some(function(config2) {
-						return config2.getPid() === config.getPid();
-					}), 'Configuration with pid ' + config.getPid() + ' was found');
-					return true;
-				}));
-			});
-		});
+		var listedConfigs = configAdmin.listConfigurations();
+		assert.equal(createdConfigs.length, 5);
+		assert.equal(listedConfigs.length, 5);
+		assert.ok(createdConfigs.every(function(config) {
+			assert.ok(listedConfigs.some(function(config2) {
+				return config2.getPid() === config.getPid();
+			}), 'Configuration with pid ' + config.getPid() + ' was found');
+			return true;
+		}));
 	});
 
 	tests['test Configuration.update(), .getProperties()'] = makeTest(function() {
 		var pid = 'test.pid';
-		return configAdmin.getConfiguration(pid).then(function(configuration) {
-			var properties = configuration.getProperties();
-			assert.strictEqual(configuration.getPid(), pid);
-			assert.strictEqual(properties, null);
-			configuration.update({
-				str: 'blort',
-				num: 42,
-				nil: null
-			});
-			properties = configuration.getProperties();
-			assert.ok(properties);
-			assert.strictEqual(properties.pid, pid);
-			assert.strictEqual(properties.str, 'blort');
-			assert.strictEqual(properties.num, 42);
-			assert.strictEqual(properties.nil, null);
+		var configuration = configAdmin.getConfiguration(pid);
+		var properties = configuration.getProperties();
+		assert.strictEqual(configuration.getPid(), pid);
+		assert.strictEqual(properties, null);
+		configuration.update({
+			str: 'blort',
+			num: 42,
+			nil: null
 		});
+		properties = configuration.getProperties();
+		assert.ok(properties);
+		assert.strictEqual(properties.pid, pid);
+		assert.strictEqual(properties.str, 'blort');
+		assert.strictEqual(properties.num, 42);
+		assert.strictEqual(properties.nil, null);
 	});
 
 	tests['test Configuration.remove()'] = makeTest(function() {
 		var pid = 'test.pid';
-		return configAdmin.getConfiguration(pid).then(function(configuration) {
-			configuration.update({
-				str: 'blort'
-			});
-			var properties = configuration.getProperties();
-			assert.ok(properties);
-			assert.strictEqual(properties.pid, pid);
-			assert.strictEqual(properties.str, 'blort');
-			return configuration.remove()
-				.then(configAdmin.listConfigurations.bind(configAdmin))
-				.then(function(listedConfigs) {
-					assert.ok(listedConfigs.every(function(config) {
-						return config !== null;
-					}), 'No null configuration in list');
-					assert.ok(listedConfigs.every(function(config) {
-						return config && pid !== config.getPid();
-					}), 'Removed configuration is not in list');
-				}).then(function() {
-					return configAdmin.getConfiguration(pid).then(function(configuration) {
-						assert.strictEqual(configuration.getProperties(), null);
-					});
-				});
+		var configuration = configAdmin.getConfiguration(pid);
+		configuration.update({
+			str: 'blort'
 		});
+		var properties = configuration.getProperties();
+		assert.ok(properties);
+		assert.strictEqual(properties.pid, pid);
+		assert.strictEqual(properties.str, 'blort');
+		configuration.remove();
+
+		var listedConfigs = configAdmin.listConfigurations();
+		assert.ok(listedConfigs.every(function(config) {
+				return config !== null;
+			}), 'No null configuration in list');
+		assert.ok(listedConfigs.every(function(config) {
+			return config && pid !== config.getPid();
+		}), 'Removed configuration is not in list');
+
+		configuration = configAdmin.getConfiguration(pid);
+		assert.strictEqual(configuration.getProperties(), null);
 	});
 
 	tests['test ManagedService.updated() called after registering ManagedService'] = makeTest(function() {
 		var pid = 'test.pid';
-		return configAdmin.getConfiguration(pid).then(function(configuration) {
-			var d = new Deferred();
-			configuration.update({
-				str: 'zot',
-				num: 42,
-				nil: null
-			});
-			// this registration should cause a call to updated(props)
-			serviceRegistry.registerService(MANAGED_SERVICE, 
-				{	updated: function(properties) {
-						try {
-							assert.strictEqual(properties.pid, pid);
-							assert.strictEqual(properties.str, 'zot');
-							assert.strictEqual(properties.num, 42);
-							assert.strictEqual(properties.nil, null);
-							d.resolve();
-						} catch (e) {
-							d.reject(e);
-						}
-					}
-				},
-				{	pid: pid
-				});
-			return d;
+		var configuration = configAdmin.getConfiguration(pid);
+		var d = new Deferred();
+		configuration.update({
+			str: 'zot',
+			num: 42,
+			nil: null
 		});
+		// this registration should cause a call to updated(props)
+		serviceRegistry.registerService(MANAGED_SERVICE, 
+			{	updated: function(properties) {
+					try {
+						assert.ok(!!properties);
+						assert.strictEqual(properties.pid, pid);
+						assert.strictEqual(properties.str, 'zot');
+						assert.strictEqual(properties.num, 42);
+						assert.strictEqual(properties.nil, null);
+						d.resolve();
+					} catch (e) {
+						d.reject(e);
+					}
+				}
+			},
+			{	pid: pid
+			});
+		return d;
 	});
 
 	tests['test ManagedService.updated(null) called for nonexistent config'] = makeTest(function() {
@@ -208,11 +209,10 @@
 			},
 			{	pid: pid
 			});
-		configAdmin.getConfiguration(pid).then(function(config) {
-			// 2nd call happens after this:
-			config.update({
-				'test': 'whee'
-			});
+		var config = configAdmin.getConfiguration(pid);
+		// 2nd call happens after this:
+		config.update({
+			'test': 'whee'
 		});
 		return d;
 	});
@@ -236,37 +236,66 @@
 			},
 			{	pid: pid
 			});
-		configAdmin.getConfiguration(pid).then(function(config) {
-			// 2nd call updated(..) happens after this:
-			config.update({
-				'test': 'whee'
-			});
-			// 3rd call happens after this
-			config.remove();
+		var config = configAdmin.getConfiguration(pid);
+		// 2nd call updated(..) happens after this:
+		config.update({
+			'test': 'whee'
 		});
+		// 3rd call happens after this
+		config.remove();
 		return d;
 	});
 
-	tests['test plugin load calls its ManagedServices\' updated() first'] = makeTest(function() {
+	tests['test plugin load updated() call ordering'] = makeTest(function() {
 		return pluginRegistry.installPlugin('testManagedServicePlugin.html').then(function(plugin) {
 			// Destroy the plugin's iframe
 			pluginRegistry.shutdown();
-			// Create a new PluginRegistry (using the same storage as the old one so it gets our plugin data),
-			// and new ServiceRegistry, ConfigAdmin, etc.
-			setUp(pluginStorage);
-			// This loads the plugin's data from the storage
-			return pluginRegistry.startup(['testManagedServicePlugin.html']).then(function() {
-				// At this point our plugin's data is in the registry, but the plugin is not loaded.
-				// Lazy-load it by invoking a service method
-				var testService = serviceRegistry.getService('test.bogus');
-				return testService.test().then(function() {
-					return testService.getCallOrder().then(function(callOrder) {
-						assert.deepEqual(callOrder, ['orion.cm.managedservice', 'test.bogus']);
+			// Create a new PluginRegistry (using the same storage as the old one so it gets our plugin data)
+			return setUp(pluginStorage).then(function() {
+				// This loads the plugin's data from the storage
+				return pluginRegistry.startup(['testManagedServicePlugin.html']).then(function() {
+					// At this point our plugin's data is in the registry, but the plugin is not loaded.
+					var plugin = pluginRegistry.getPlugin('testManagedServicePlugin.html');
+					assert.ok(plugin);
+					assert.strictEqual(plugin.getState(), Plugin.INSTALLED);
+					// Lazy-load it by invoking a service method
+					var testService = serviceRegistry.getService('test.bogus');
+					return testService.test().then(function() {
+						return testService.getCallOrder().then(function(callOrder) {
+							assert.deepEqual(callOrder, ['orion.cm.managedservice', 'test.bogus']);
+						});
 					});
 				});
 			});
 		});
 	});
 
+	// Similar to previous test, but ConfigAdmin is registered after PluginRegistry has started up.
+	tests['test plugin load updated() call ordering -- late registration'] = (function() {
+		return testHelpers.makeTest(setUp.bind(null, {} /*no storage*/, true /*no config admin*/), tearDown, function() {
+			return pluginRegistry.installPlugin('testManagedServicePlugin.html').then(function(plugin) {
+				pluginRegistry.shutdown();
+				setUp(pluginStorage, true /*don't create config admin*/);
+				assert.ok(!configAdmin, 'no config admin yet');
+				return pluginRegistry.startup(['testManagedServicePlugin.html']).then(function() {
+					var plugin = pluginRegistry.getPlugin('testManagedServicePlugin.html');
+					assert.ok(plugin);
+					assert.strictEqual(plugin.getState(), Plugin.INSTALLED);
+					// Finally register ConfigAdmin
+					return new ConfigAdminFactory(serviceRegistry, pluginRegistry, preferences).getConfigurationAdmin().then(
+						function(createdConfigAdmin) {
+							configAdmin = createdConfigAdmin;
+							var testService = serviceRegistry.getService('test.bogus');
+							return testService.test().then(function() {
+								return testService.getCallOrder().then(function(callOrder) {
+									assert.deepEqual(callOrder, ['orion.cm.managedservice', 'test.bogus']);
+								});
+							});
+						});
+				});
+			});
+		});
+	}());
+
 return tests;
 });
\ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/bootstrap.js b/bundles/org.eclipse.orion.client.core/web/orion/bootstrap.js
index bee4085..fd3c603 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/bootstrap.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/bootstrap.js
@@ -50,8 +50,9 @@
 				});

 			}

 		}).then(function() {

-			var configAdmin = new mConfig.ConfigurationAdminFactory(serviceRegistry, preferences).getConfigurationAdmin();

-			serviceRegistry.registerService("orion.cm.configadmin", configAdmin); //$NON-NLS-0$

+			return new mConfig.ConfigurationAdminFactory(serviceRegistry, pluginRegistry, preferences).getConfigurationAdmin().then(

+				serviceRegistry.registerService.bind(serviceRegistry, "orion.cm.configadmin") //$NON-NLS-0$

+			);

 		}).then(function() {

 			var auth = serviceRegistry.getService("orion.core.auth"); //$NON-NLS-0$

 			if (auth) {

diff --git a/bundles/org.eclipse.orion.client.core/web/orion/config.js b/bundles/org.eclipse.orion.client.core/web/orion/config.js
index 0e5a512..235fc28 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/config.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/config.js
@@ -9,8 +9,9 @@
  * Contributors: IBM Corporation - initial API and implementation
  ******************************************************************************/
 /*global console define setTimeout*/
-define(['orion/textview/eventTarget', 'orion/Deferred', 'orion/serviceTracker'],
-	function(mEventTarget, Deferred, ServiceTracker) {
+define(['orion/textview/eventTarget', 'orion/Deferred', 'orion/serviceTracker', 'orion/pluginregistry'],
+	function(mEventTarget, Deferred, ServiceTracker, mPluginRegistry) {
+var Plugin = mPluginRegistry.Plugin;
 var ManagedServiceTracker, ConfigAdminFactory, ConfigStore, ConfigAdminImpl, ConfigImpl;
 
 var PROPERTY_PID = 'pid'; //$NON-NLS-0$
@@ -19,13 +20,31 @@
 /**
  * @name orion.cm.impl.ManagedServiceTracker
  * @class Tracks ManagedServices in a ServiceRegistry. Delivers updated() notifications to tracked ManagedServices.
+ * This class also tracks the loading of {@link orion.pluginregistry.Plugin}s in a PluginRegistry, and provides 
+ * the following guarantee: if a Plugin is being loaded and it provides a ManagedService, its updated() method
+ * will be called prior to any other service method.
  * @private
  */
-ManagedServiceTracker = /** @ignore */ function(serviceRegistry, store) {
+ManagedServiceTracker = /** @ignore */ function(serviceRegistry, pluginRegistry, store) {
 	ServiceTracker.call(this, serviceRegistry, MANAGED_SERVICE); //$NON-NLS-0$
 
 	var managedServiceRefs = {};
 	var managedServices = {};
+	var pluginLoadedListener = function(event) {
+		var managedServiceUpdates = [];
+		event.plugin.getServiceReferences().forEach(function(serviceRef) {
+			if (serviceRef.getProperty('service.names').indexOf(MANAGED_SERVICE) !== -1) { //$NON-NLS-0$
+				var pid = serviceRef.getProperty(PROPERTY_PID);
+				var managedService = serviceRegistry.getService(serviceRef);
+				if (pid && managedService) {
+					var configuration = store._find(pid);
+					var properties = configuration && configuration.getProperties();
+					managedServiceUpdates.push(managedService.updated(properties));
+				}
+			}
+		});
+		return Deferred.all(managedServiceUpdates);
+	};
 
 	function add(pid, serviceRef, service) {
 		if (!managedServiceRefs[pid]) {
@@ -57,11 +76,16 @@
 	function getManagedServices(pid) {
 		return managedServices[pid] || [];
 	}
-	function asyncUpdated(managedServiceRef, managedService, properties) {
-		function arr(v) { return Array.isArray(v) ? v : [v]; }
-		arr(managedService).forEach(function(service) {
+	function asyncUpdated(serviceRefs, services, properties) {
+		services.forEach(function(service, i) {
 			try {
-				service.updated(properties);
+				// Plugin load is expensive, so don't trigger it just to call updated() on a Managed Service.
+				// pluginLoadedListener will catch the plugin when (if) it loads.
+				var pluginUrl = serviceRefs[i].getProperty('__plugin__'); //$NON-NLS-0$
+				var plugin = pluginUrl && pluginRegistry.getPlugin(pluginUrl);
+				if (!pluginUrl || (plugin && plugin.getState() === Plugin.LOADED)) {
+					services[i].updated(properties);
+				}
 			} catch(e) {
 				if (typeof console !== 'undefined') { //$NON-NLS-0$
 					console.log(e);
@@ -78,14 +102,16 @@
 		add(pid, serviceRef, managedService);
 		return managedService;
 	};
-	/**
-	 * @returns {Deferred} A deferred that resolves once the managed service's updated() method has been called
-	 */
 	this.onServiceAdded = function(serviceRef, service) {
 		var pid = serviceRef.getProperty(PROPERTY_PID);
-		return store.get(pid).then(function(configuration) {
-			asyncUpdated(serviceRef, service, (configuration && configuration.getProperties()));
-		});
+		var configuration = store._find(pid);
+		asyncUpdated([serviceRef], [service], (configuration && configuration.getProperties()));
+	};
+	this.onOpen = function() {
+		pluginRegistry.addEventListener('pluginLoaded', pluginLoadedListener); //$NON-NLS-0$
+	};
+	this.onClose = function() {
+		pluginRegistry.removeEventListener('pluginLoaded', pluginLoadedListener); //$NON-NLS-0$
 	};
 	this.notifyUpdated = function(configuration) {
 		var pid = configuration.getPid();
@@ -100,7 +126,6 @@
 		remove(pid, serviceRef, service);
 	};
 };
-
 /**
  * @name orion.cm.impl.ConfigAdminFactory
  * @class
@@ -108,15 +133,19 @@
  */
 ConfigAdminFactory = /** @ignore */ (function() {
 	/** @private */
-	function ConfigAdminFactory(serviceRegistry, prefsService) {
+	function ConfigAdminFactory(serviceRegistry, pluginRegistry, prefsService) {
 		this.store = new ConfigStore(this, prefsService);
 		this.configAdmin = new ConfigAdminImpl(this, this.store);
-		this.tracker = new ManagedServiceTracker(serviceRegistry, this.store);
-		this.tracker.open();
+		this.tracker = new ManagedServiceTracker(serviceRegistry, pluginRegistry, this.store);
 	}
 	ConfigAdminFactory.prototype = {
+		// TODO this should be synchronous but requires sync Prefs API
 		getConfigurationAdmin: function() {
-			return this.configAdmin;
+			var self = this;
+			return this.configAdmin._init().then(function(configAdmin) {
+				self.tracker.open();
+				return configAdmin;
+			});
 		},
 		notifyDeleted: function(configuration) {
 			this.tracker.notifyDeleted(configuration);
@@ -139,6 +168,12 @@
 		this.store = store;
 	}
 	ConfigAdminImpl.prototype = {
+		_init: function() {
+			var self = this;
+			return this.store._init().then(function() {
+				return self;
+			});
+		},
 		getConfiguration: function(pid) {
 			return this.store.get(pid);
 		},
@@ -160,83 +195,56 @@
 		this.factory = factory;
 		this.prefsService = prefsService;
 		this.configs = Object.create(null); // PID -> Configuration
-		this.prefs = Object.create(null); // PID -> Deferred Preferences node
-		this.prefRoot = null; // Deferred Preferences node
+		this.pref = null; // Preferences node. Pref keys are PIDs, pref values are properties objects.
+		var self = this;
+		this.initPromise = this.prefsService.getPreferences(CONFIG_PREF_NODE).then(function(pref) {	
+			self.pref = pref;
+			pref.keys().forEach(function(pid) {
+				if (!self.configs[pid]) {
+					var properties = pref.get(pid);
+					if (typeof properties === 'object' && properties !== null && Object.keys(properties).length > 0) { //$NON-NLS-0$
+						properties[PROPERTY_PID] = pid;
+						self.configs[pid] = new ConfigImpl(self.factory, self, properties);
+					}
+				}
+			});
+		});
 	}
 	ConfigStore.prototype = {
+		_init: function() {
+			return this.initPromise;
+		},
 		_find: function(pid) {
 			return this.configs[pid] || null;
 		},
-		loadRoot: function() {
-			this.prefRoot = this.prefRoot || this.prefsService.getPreferences(CONFIG_PREF_NODE);
-			return this.prefRoot;
-		},
-		loadNode: function(pid) {
-			if (typeof pid !== 'string') { //$NON-NLS-0$
-				throw new Error('Invalid pid: ' + pid); //$NON-NLS-0$
-			}
-			this.prefs[pid] = this.prefs[pid] || this.prefsService.getPreferences(CONFIG_PREF_NODE + '/' + pid); //$NON-NLS-0$
-			var self = this;
-			return Deferred.all([this.loadRoot(), this.prefs[pid]]).then(function(result) {
-				var prefRoot = result[0], prefNode = result[1];
-				if (!prefRoot.get(pid)) {
-					prefRoot.put(pid, true);
-				}
-				if (!self.configs[pid]) {
-					var props = prefNode.get('properties'); //$NON-NLS-0$
-					if (typeof props === 'object' && props !== null && Object.keys(props).length > 0) { //$NON-NLS-0$
-						props[PROPERTY_PID] = pid;
-						self.configs[pid] = new ConfigImpl(self.factory, self, props);
-					}
-				}
-				return prefNode;
-			});
-		},
 		get: function(pid) {
-			var self = this;
-			return this.loadNode(pid).then(function(prefNode) {
-				var configuration = self._find(pid);
-				if (!configuration) {
-					configuration = new ConfigImpl(self.factory, self, pid);
-					self.configs[pid] = configuration;
-					// only pid is in the properties here
-					prefNode.put('properties', configuration.getProperties(true) || {}); //$NON-NLS-0$
-				}
-				return configuration;
-			});
+			var configuration = this._find(pid);
+			if (!configuration) {
+				// only pid is in the properties here
+				configuration = new ConfigImpl(this.factory, this, pid);
+				this.configs[pid] = configuration;
+				this.pref.put(pid, configuration.getProperties(true) || {}); //$NON-NLS-0$
+			}
+			return configuration;
 		},
 		list: function() {
 			var self = this;
-			return this.loadRoot().then(function(prefRoot) {
-				var pids = prefRoot.keys();
-				return Deferred.all(pids.map(self.loadNode.bind(self))).then(function() {
-					var currentConfigs = [];
-					for (var i=0; i < pids.length; i++) {
-						var config = self._find(pids[i]);
-						if (config && config.getProperties() !== null) {
-							currentConfigs.push(config);
-						}
-					}
-					return currentConfigs;
-				});
+			var currentConfigs = [];
+			this.pref.keys().forEach(function(pid) {
+				var config = self._find(pid);
+				if (config && config.getProperties() !== null) {
+					currentConfigs.push(config);
+				}
 			});
+			return currentConfigs;
 		},
 		remove: function(pid) {
-			var self = this;
-			return Deferred.all([this.loadRoot(), this.loadNode(pid)]).then(function(result) {
-				var prefRoot = result[0], prefNode = result[1];
-				// TODO want to remove the whole prefNode here, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=386582
-				prefNode.clear();
-				delete self.configs[pid];
-				prefRoot.remove(pid);
-				delete self.prefs[pid];
-			});
+			this.pref.remove(pid);
+			delete this.configs[pid];
 		},
 		save: function(pid, configuration) {
 			var properties = configuration.getProperties(true);
-			this.loadNode(pid).then(function(prefNode) {
-				prefNode.put('properties', properties || {}); //$NON-NLS-0$
-			});
+			this.pref.put(pid, properties || {});
 		}
 	};
 	return ConfigStore;
@@ -298,18 +306,15 @@
 		},
 		remove: function() {
 			this._checkRemoved();
-			var self = this;
-			self.factory.notifyDeleted(self);
-			var promise = this.store.remove(this.pid);
+			this.factory.notifyDeleted(this);
+			this.store.remove(this.pid);
 			this._removed = true;
-			return promise;
 		},
 		update: function(props) {
 			this._checkRemoved();
 			setProperties(this, props);
-			var self = this;
 			this.store.save(this.pid, this);
-			self.factory.notifyUpdated(self);
+			this.factory.notifyUpdated(this);
 		},
 		toString: function() {
 			return '[ConfigImpl pid: ' + this.pid + ', properties: ' + JSON.stringify(this.properties) + ']';
@@ -361,13 +366,13 @@
 	 * @description Gets the configuration having the given PID, creating a new one if necessary. Newly created configurations
 	 * have <code>null</code> properties.
 	 * @param {String} pid
-	 * @returns {orion.cm.Configuration} A deferred resolving to the {@link orion.cm.Configuration}.
+	 * @returns {orion.cm.Configuration} The configuration.
 	 */
 	/**
 	 * @name listConfigurations
 	 * @methodOf orion.cm.ConfigurationAdmin.prototype
 	 * @description Returns all Configurations having non-<code>null</code> properties.
-	 * @returns {orion.cm.Configuration[]} A deferred resolving to an array of configurations.
+	 * @returns {orion.cm.Configuration[]} An array of configurations.
 	 */
 
 /**
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/testHelpers.js b/bundles/org.eclipse.orion.client.core/web/orion/testHelpers.js
index 46e99bf..72ad361 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/testHelpers.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/testHelpers.js
@@ -35,6 +35,7 @@
 								d.reject(e);
 							});
 					} else {
+						tearDown();
 						d.resolve(result);
 					}
 				} catch(e) {
diff --git a/bundles/org.eclipse.orion.client.users/web/orion/profile/UsersList.js b/bundles/org.eclipse.orion.client.users/web/orion/profile/UsersList.js
index 97507d0..1075e8b 100644
--- a/bundles/org.eclipse.orion.client.users/web/orion/profile/UsersList.js
+++ b/bundles/org.eclipse.orion.client.users/web/orion/profile/UsersList.js
@@ -1,6 +1,6 @@
 /*******************************************************************************
  * @license
- * Copyright (c) 2009, 2011 IBM Corporation and others.
+ * Copyright (c) 2009, 2012 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 
  * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
@@ -8,6 +8,9 @@
  * 
  * Contributors: IBM Corporation - initial API and implementation
  ******************************************************************************/
+ 
+ /*jslint browser:true devel:true sub:true*/
+ /*global define window*/
 
 define(['i18n!profile/nls/messages', 'require', 'dojo', 'orion/explorer', 'orion/profile/usersUtil', 'orion/navigationUtils'], function(messages, require, dojo, mExplorer, mUsersUtil, mNavUtils) {
 
@@ -27,11 +30,33 @@
 		this.model = null;
 		this.myTree = null;
 		this.renderer = new eclipse.UsersRenderer({actionScopeId: this.actionScopeId, checkbox: false, cachePrefix: "UsersNavigator"}, this); //$NON-NLS-0$
-	};
+	}
+	
 	UsersList.prototype = new mExplorer.Explorer();
 	
-	UsersList.prototype.loadUsers = function(){
+	UsersList.prototype.queryObject = { start: 0, rows:100, length: 0};
+	
+	UsersList.prototype.calculateQuery = function(locationHash, queryObj) {
+		var startQuery = locationHash.indexOf("?"); //$NON-NLS-0$
+		if (startQuery !== -1) {
+			var queryStr = locationHash.substring(startQuery + 1);
+			var splitQ = queryStr.split("&"); //$NON-NLS-0$
+			for(var i=0; i < splitQ.length; i++){
+				var splitparameters = splitQ[i].split("="); //$NON-NLS-0$
+				if(splitparameters.length === 2){
+					if(splitparameters[0] === "rows"){  //$NON-NLS-0$
+						queryObj.rows = parseInt(splitparameters[1], 10);
+					} else if(splitparameters[0] === "start"){ //$NON-NLS-0$
+						queryObj.start = parseInt(splitparameters[1], 10);
+					}
+				}
+			}
+		}
+	};
+
+	UsersList.prototype.createModel = function() {
 		var parent = dojo.byId(this.parentId);
+		var queryObj = UsersList.prototype.queryObject;
 
 		// Progress indicator
 		var progress = dojo.byId("progress");  //$NON-NLS-0$
@@ -39,20 +64,55 @@
 			progress = dojo.create("div", {id: "progress"}, parent, "only"); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
 		}
 		dojo.empty(progress);
-		b = dojo.create("b"); //$NON-NLS-0$
-		dojo.place(document.createTextNode(messages["Loading users..."]), progress, "last"); //$NON-NLS-1$
-
-		mUsersUtil.updateNavTools(this.registry, this, this.toolbarId, this.selectionToolsId, {});
-					
+		dojo.create("b"); //$NON-NLS-0$
+		dojo.place(document.createTextNode(messages["Loading users..."]), progress, "last"); //$NON-NLS-0$
+		
 		var service = this.registry.getService("orion.core.user"); //$NON-NLS-0$
-		this.createTree(this.parentId, new mExplorer.ExplorerFlatModel("/users", service.getUsersList), {setFocus: true}); //$NON-NLS-0$
+		UsersList.prototype.registry = this.registry;
+		
+		var locationHash = window.location.hash;
+		UsersList.prototype.calculateQuery(locationHash, queryObj);
+		var flatModel = new mExplorer.ExplorerFlatModel("../users", UsersList.prototype.getUsersListSubset.bind(this)); //$NON-NLS-0$
+		flatModel.service = service;
+		flatModel.queryObject = queryObj;
+		this.queryObject = queryObj;
+		this.createTree(this.parentId, flatModel, {setFocus: true}); //$NON-NLS-0$
+		mUsersUtil.updateNavTools(this.registry, this, this.toolbarId, this.selectionToolsId, {});
+	};
+	
+	UsersList.prototype.loadUsers = function(refreshTree){
+		var that = this;
+		var queryObj = UsersList.prototype.queryObject;
+		var locationHash = window.location.hash;
+		UsersList.prototype.calculateQuery(locationHash, queryObj);
+		if (refreshTree) {
+			UsersList.prototype.getUsersListSubset().then( function(newChildren) {
+				that.myTree.refresh("userslist", newChildren); //$NON-NLS-0$
+				mUsersUtil.updateNavTools(that.registry, that, that.toolbarId, that.selectionToolsId, {});
+			}.bind(this));
+		}
 	};
 	
 	UsersList.prototype.reloadUsers = function() {
-		dojo.empty(this.parentId);
-		this.loadUsers();
+		this.loadUsers(true);
 	};
-	
+
+	UsersList.prototype.getUsersListSubset = function(root) {
+	    var aService;
+	    if (this.service) {
+	        aService = this.service;
+	    } else {
+	        aService = this.registry.getService("orion.core.user"); //$NON-NLS-0$
+	    }
+		return aService.getUsersListSubset(this.queryObject.start, this.queryObject.rows).then(
+			function(result) {
+				this.queryObject.start = parseInt(result.users_start, 10);
+				this.queryObject.rows = parseInt(result.users_rows, 10);
+				this.queryObject.length = parseInt(result.users_length, 10);
+				return result.users;
+			}.bind(this));
+	};
+
 	return UsersList;
 }());
 
@@ -68,18 +128,14 @@
 		
 		switch(col_no){
 		case 0: 
-			return dojo.create("th", {innerHTML: "<h2>"+messages["Login"]+"</h2>"}); //$NON-NLS-3$ //$NON-NLS-1$ //$NON-NLS-0$
-			break;
+			return dojo.create("th", {innerHTML: "<h2>"+messages["Login"]+"</h2>"}); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
 		case 1:
-			return dojo.create("th", {innerHTML: "<h2>"+messages["Actions"]+"</h2>"}); //$NON-NLS-3$ //$NON-NLS-1$ //$NON-NLS-0$
-			break;
+			return dojo.create("th", {innerHTML: "<h2>"+messages["Actions"]+"</h2>"}); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
 		case 2:
-			return dojo.create("th", {innerHTML: "<h2>"+messages["Name"]+"</h2>"}); //$NON-NLS-3$ //$NON-NLS-1$ //$NON-NLS-0$
-			break;
+			return dojo.create("th", {innerHTML: "<h2>"+messages["Name"]+"</h2>"}); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
 		case 3:
-			return dojo.create("th", {innerHTML: "<h2>"+messages["Last Login"]+"</h2>"}); //$NON-NLS-3$ //$NON-NLS-1$ //$NON-NLS-0$
-			break;
-		};
+			return dojo.create("th", {innerHTML: "<h2>"+messages["Last Login"]+"</h2>"}); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+		}
 		
 	};
 	
@@ -96,17 +152,13 @@
 			dojo.place(document.createTextNode(item.login), link, "only");			 //$NON-NLS-0$
 			mNavUtils.addNavGrid(this.explorer.getNavDict(), item, link);
 			return col;
-			break;
 		case 1:
 			return this.getActionsColumn(item, tableRow, null, null, true);
-			break;
 		case 2:
 			return dojo.create("td", {innerHTML: item.Name ? item.Name : "&nbsp;"}); //$NON-NLS-1$ //$NON-NLS-0$
-			break;
 		case 3:
-			return dojo.create("td", {innerHTML: item.LastLogInTimestamp ? dojo.date.locale.format(new Date(parseInt(item.LastLogInTimestamp)), {formatLength: "short"}) : '&nbsp;'}); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
-			break;
-		};
+			return dojo.create("td", {innerHTML: item.LastLogInTimestamp ? dojo.date.locale.format(new Date(parseInt(item.LastLogInTimestamp, 10)), {formatLength: "short"}) : '&nbsp;'}); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+		}
 		
 	};
 	
@@ -136,19 +188,19 @@
 				var titleRow = dojo.create("tr", {"class": "domCommandBackground"}, thead); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
 
 				dojo.create("td", { //$NON-NLS-0$
-					innerHTML : "<h2>"+messages['Login']+"</h2>", //$NON-NLS-2$ //$NON-NLS-0$
+					innerHTML : "<h2>"+messages['Login']+"</h2>", //$NON-NLS-1$ //$NON-NLS-0$
 					className : "usersTable" //$NON-NLS-0$
 				}, titleRow);
 				dojo.create("td", { //$NON-NLS-0$
-					innerHTML : "<h2>"+messages['Actions']+"</h2>", //$NON-NLS-2$ //$NON-NLS-0$
+					innerHTML : "<h2>"+messages['Actions']+"</h2>", //$NON-NLS-1$ //$NON-NLS-0$
 					className : "usersTable" //$NON-NLS-0$
 				}, titleRow);
 				dojo.create("td", { //$NON-NLS-0$
-					innerHTML : "<h2>"+messages['Name']+"</h2>", //$NON-NLS-2$ //$NON-NLS-0$
+					innerHTML : "<h2>"+messages['Name']+"</h2>", //$NON-NLS-1$ //$NON-NLS-0$
 					className : "usersTable" //$NON-NLS-0$
 				}, titleRow);
 				dojo.create("td", { //$NON-NLS-0$
-					innerHTML : "<h2>"+messages['Last Login']+"</h2>", //$NON-NLS-2$ //$NON-NLS-0$
+					innerHTML : "<h2>"+messages['Last Login']+"</h2>", //$NON-NLS-1$ //$NON-NLS-0$
 					className : "usersTable" //$NON-NLS-0$
 				}, titleRow);
 
@@ -159,7 +211,7 @@
 				var tbody = dojo.create("tbody", null, table); //$NON-NLS-0$
 
 				for ( var i in jsonData.users) {
-					var userRow = dojo.create("tr", {"class": i%2==0 ? "treeTableRow lightTreeTableRow" : "treeTableRow darkTreeTableRow"}); //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+					var userRow = dojo.create("tr", {"class": i%2===0 ? "treeTableRow lightTreeTableRow" : "treeTableRow darkTreeTableRow"}); //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
 					dojo.connect(userRow, "onmouseover", dojo.hitch(this, function(i){document.getElementById("usersActions"+i).style.visibility="";}, i)); //$NON-NLS-1$ //$NON-NLS-0$
 					dojo.connect(userRow, "onmouseout", dojo.hitch(this, function(i){document.getElementById("usersActions"+i).style.visibility="hidden";}, i)); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
 					dojo.create("td", { //$NON-NLS-0$
@@ -189,7 +241,7 @@
 						className: "usersTable secondaryColumn" //$NON-NLS-0$
 					}, userRow);
 					dojo.create("td", { //$NON-NLS-0$
-						innerHTML : jsonData.users[i].LastLogInTimestamp ? dojo.date.locale.format(new Date(parseInt(jsonData.users[i].LastLogInTimestamp)), {formatLength: "short"}) : '&nbsp;', //$NON-NLS-1$ //$NON-NLS-0$
+						innerHTML : jsonData.users[i].LastLogInTimestamp ? dojo.date.locale.format(new Date(parseInt(jsonData.users[i].LastLogInTimestamp, 10)), {formatLength: "short"}) : '&nbsp;', //$NON-NLS-1$ //$NON-NLS-0$
 						className: "usersTable secondaryColumn" //$NON-NLS-0$
 					}, userRow);
 					dojo.place(userRow, tbody);
@@ -197,7 +249,7 @@
 			}));
 		},
 		getUserTab : function(userName, userLocation) {
-			return tab = "<a class=\"navlinkonpage\" href=\"" + require.toUrl("profile/user-profile.html") + "#" + userLocation //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+			return "<a class=\"navlinkonpage\" href=\"" + require.toUrl("profile/user-profile.html") + "#" + userLocation //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
 					+ "\">" + userName + "</a>"; //$NON-NLS-1$ //$NON-NLS-0$
 		},
 		reloadUsers : function() {
diff --git a/bundles/org.eclipse.orion.client.users/web/orion/profile/profile.js b/bundles/org.eclipse.orion.client.users/web/orion/profile/profile.js
index 64f1343..4d5be5b 100644
--- a/bundles/org.eclipse.orion.client.users/web/orion/profile/profile.js
+++ b/bundles/org.eclipse.orion.client.users/web/orion/profile/profile.js
@@ -306,7 +306,7 @@
 				var breadcrumbTarget = 	{};
 				breadcrumbTarget.Parents = [];
 				breadcrumbTarget.Name = profile.lastJSON.Name && profile.lastJSON.Name.replace(/^\s+|\s+$/g,"")!=="" ? profile.lastJSON.Name : profile.lastJSON.login; //$NON-NLS-0$
-				mGlobalCommands.setPageTarget({task: "User Profile", breadcrumbTarget: breadcrumbTarget});
+				mGlobalCommands.setPageTarget({task: "User Profile", breadcrumbTarget: breadcrumbTarget}); //$NON-NLS-0$
 			
 				this.commandService.destroy(this.pageActionsPlaceholder);
 				this.commandService.addCommandGroup(this.pageActionsPlaceholder.id, "eclipse.profileActionsGroup", 100); //$NON-NLS-0$
diff --git a/bundles/org.eclipse.orion.client.users/web/orion/profile/usersClient.js b/bundles/org.eclipse.orion.client.users/web/orion/profile/usersClient.js
index a401447..eff8fb0 100644
--- a/bundles/org.eclipse.orion.client.users/web/orion/profile/usersClient.js
+++ b/bundles/org.eclipse.orion.client.users/web/orion/profile/usersClient.js
@@ -29,6 +29,9 @@
 		getUserInfo: function(userURI, onLoad){
 			return this._doServiceCall("getUserInfo", arguments); //$NON-NLS-0$
 		},
+		getUsersListSubset : function(start, rows, onLoad) {
+			return this._doServiceCall("getUsersListSubset", arguments); //$NON-NLS-0$
+		},
 		getUsersList : function(onLoad) {
 			return this._doServiceCall("getUsersList", arguments); //$NON-NLS-0$
 		},
diff --git a/bundles/org.eclipse.orion.client.users/web/profile/UsersService.js b/bundles/org.eclipse.orion.client.users/web/profile/UsersService.js
index 4d11fdc..dc0099a 100644
--- a/bundles/org.eclipse.orion.client.users/web/profile/UsersService.js
+++ b/bundles/org.eclipse.orion.client.users/web/profile/UsersService.js
@@ -49,6 +49,33 @@
 
 	UsersService.prototype = /** @lends eclipse.FileService.prototype */
 	{
+		getUsersListSubset : function(start, rows, onLoad) {
+			var service = this;
+			var uri = "../users?start=" + start + "&rows=" + rows;
+			return xhr("GET", uri, { //$NON-NLS-1$ 
+				headers : {
+					"Orion-Version" : "1" //$NON-NLS-1$ //$NON-NLS-0$
+				},
+				timeout: 15000
+			}).then(function(result) {
+				var jsonData = getJSON(result.response);
+				if (onLoad){
+					if(typeof onLoad === "function") //$NON-NLS-0$
+						onLoad(jsonData);
+					else
+						service.dispatchEvent(onLoad, jsonData);
+				}
+				return jsonData;
+			}, function(result) {
+				var error = getError(result);
+				if(!service.info) {
+					handleAuthenticationError(error, function(){
+						service.getUsersListSubset(start, rows, onLoad); // retry GET
+					});
+				}
+				return error;
+			});
+		},
 		getUsersList : function(onLoad) {
 			var service = this;
 			return xhr("GET", "../users", { //$NON-NLS-1$ //$NON-NLS-0$
diff --git a/bundles/org.eclipse.orion.client.users/web/profile/nls/root/messages.js b/bundles/org.eclipse.orion.client.users/web/profile/nls/root/messages.js
index 429d43e..fccd6ae 100644
--- a/bundles/org.eclipse.orion.client.users/web/profile/nls/root/messages.js
+++ b/bundles/org.eclipse.orion.client.users/web/profile/nls/root/messages.js
@@ -40,5 +40,9 @@
 	"Are you sure you want to delete user ${0}?": "Are you sure you want to delete user ${0}?",
 	"Change Password": "Change Password",
 	"More": "More",
-	"Passwords do not match!": "Passwords do not match!"
+	"Passwords do not match!": "Passwords do not match!",
+	"< Previous Page": "< Previous Page",
+	"Show previous page of Users names": "Show previous page of Users names",
+	"Next Page >": "Next Page >",
+	"Show next page of User names": "Show next page of User names"
 });
\ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.users/web/profile/user-list.js b/bundles/org.eclipse.orion.client.users/web/profile/user-list.js
index 642653a..0e0ff9e 100644
--- a/bundles/org.eclipse.orion.client.users/web/profile/user-list.js
+++ b/bundles/org.eclipse.orion.client.users/web/profile/user-list.js
@@ -1,6 +1,6 @@
 /*******************************************************************************
  * @license
- * Copyright (c) 2009, 2011 IBM Corporation and others.
+ * Copyright (c) 2009, 2012 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 
  * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
@@ -8,6 +8,9 @@
  * 
  * Contributors: IBM Corporation - initial API and implementation
  ******************************************************************************/
+ 
+ /*jslint browser:true devel:true sub:true */
+ /*global define window orion */
 
 define(['i18n!profile/nls/messages', 'require', 'dojo', 'orion/bootstrap', 'orion/status', 'orion/progress', 'orion/operationsClient', 'orion/commands', 'orion/selection',
 	        'orion/searchClient', 'orion/fileClient', 'orion/globalCommands', 'orion/profile/UsersList', 'orion/profile/usersUtil',
@@ -33,6 +36,37 @@
 
 			mGlobalCommands.generateBanner("orion-userList", serviceRegistry, commandService, preferences, searcher, usersList); //$NON-NLS-0$	
 			
+			var previousPage = new mCommands.Command({
+				name : messages["< Previous Page"],
+				tooltip: messages["Show previous page of Users names"],
+				id : "orion.userlist.prevPage", //$NON-NLS-0$
+				hrefCallback : function() {
+					var start = usersList.queryObject.start - usersList.queryObject.rows;
+					if (start < 0) {
+						start = 0;
+					}
+					return window.location.pathname + "#?start=" + start + "&rows=" + usersList.queryObject.rows; //$NON-NLS-1$ //$NON-NLS-0$
+				},
+				visibleWhen : function(item) {
+					return usersList.queryObject.start > 0;
+				}
+			});
+			commandService.addCommand(previousPage);
+
+			var nextPage = new mCommands.Command({
+				name : messages["Next Page >"],
+				tooltip: messages["Show next page of User names"],
+				id : "orion.userlist.nextPage", //$NON-NLS-0$
+				hrefCallback : function() {
+					return window.location.pathname + "#?start=" + (usersList.queryObject.start + usersList.queryObject.rows) + "&rows=" + usersList.queryObject.rows; //$NON-NLS-1$ //$NON-NLS-0$
+				},
+				visibleWhen : function(item) {
+					return usersList.queryObject.length === 0 ? true : (usersList.queryObject.start + usersList.queryObject.rows) < usersList.queryObject.length;
+				}
+			});
+			commandService.addCommand(nextPage);
+
+
 			var createUserCommand = new mCommands.Command({
 				name: messages["Create User"],
 				id: "eclipse.createUser", //$NON-NLS-0$
@@ -77,9 +111,10 @@
 							var usersProcessed = 0;
 							for(var i=0; i<item.length; i++){
 								userService.deleteUser(item[i].Location).then( dojo.hitch(usersList, function(jsonData) {
-									  usersProcessed++;
-									  if(usersProcessed==item.length)
-										  this.reloadUsers();
+									usersProcessed++;
+									if(usersProcessed===item.length) {
+										this.reloadUsers();
+									}
 								  }));	
 							}
 						}
@@ -119,14 +154,22 @@
 			commandService.addCommandGroup("pageActions", "eclipse.usersGroup", 100); //$NON-NLS-1$ //$NON-NLS-0$
 			commandService.addCommandGroup("selectionTools", "eclipse.selectionGroup", 500, messages["More"]); //$NON-NLS-1$ //$NON-NLS-0$
 			
+			commandService.registerCommandContribution("pageActions", "orion.userlist.prevPage", 2, "eclipse.usersGroup");  //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+			commandService.registerCommandContribution("pageActions", "orion.userlist.nextPage", 3, "eclipse.usersGroup");  //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+
 			commandService.registerCommandContribution("pageActions", "eclipse.createUser", 1, "eclipse.usersGroup"); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
 			
 			commandService.registerCommandContribution("userCommands", "eclipse.deleteUser", 1); //$NON-NLS-1$ //$NON-NLS-0$
 			commandService.registerCommandContribution("userCommands", "eclipse.changePassword", 2); //$NON-NLS-1$ //$NON-NLS-0$
 			commandService.registerCommandContribution("selectionTools", "eclipse.deleteUser", 1, "eclipse.selectionGroup"); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+
+			//every time the user manually changes the hash, we need to load the user list again
+			dojo.subscribe("/dojo/hashchange", usersList, function() { //$NON-NLS-0$
+				usersList.reloadUsers();
+			});
 			
-			usersList.loadUsers();
-			mUsersUtil.updateNavTools(serviceRegistry, usersList, "pageActions", "selectionTools", {});	 //$NON-NLS-1$ //$NON-NLS-0$
+			usersList.createModel();
+			usersList.loadUsers(true);
 		});
 	});
 });
\ No newline at end of file