diff --git a/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/envvar/IEnvironmentVariableManagerTests.java b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/envvar/IEnvironmentVariableManagerTests.java
index 5ec0e518371..a659f351f55 100644
--- a/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/envvar/IEnvironmentVariableManagerTests.java
+++ b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/envvar/IEnvironmentVariableManagerTests.java
@@ -10,6 +10,8 @@
*******************************************************************************/
package org.eclipse.cdt.core.envvar;
+import java.io.ByteArrayInputStream;
+
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
@@ -68,9 +70,14 @@ public class IEnvironmentVariableManagerTests extends TestCase {
IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager();
IContributedEnvironment contribEnv = envManager.getContributedEnvironment();
+ assertFalse(descs[0].isModified());
+ assertFalse(descs[1].isModified());
+
// Try setting an environment variable
final IEnvironmentVariable var = new EnvironmentVariable("FOO", "BAR");
contribEnv.addVariable(var, prjDesc.getConfigurationById(id1));
+ assertTrue(prjDesc.getConfigurationById(id1).isModified());
+ assertFalse(prjDesc.getConfigurationById(id2).isModified());
// Check that the variable exists on the config1 & not in config2:
IEnvironmentVariable var2 = envManager.getVariable(var.getName(), prjDesc.getConfigurationById(id1), true);
@@ -83,13 +90,100 @@ public class IEnvironmentVariableManagerTests extends TestCase {
// Close and reopen, variables should still exist
project.close(null);
project.open(null);
- descs = CoreModel.getDefault().getProjectDescription(project).getConfigurations();
+ prjDesc = CoreModel.getDefault().getProjectDescription(project);
var2 = envManager.getVariable(var.getName(), prjDesc.getConfigurationById(id1), true);
assertEquals(var2, var);
var2 = envManager.getVariable(var.getName(), prjDesc.getConfigurationById(id2), true);
assertNull(var2);
+ assertFalse(prjDesc.getConfigurationById(id1).isModified());
+ assertFalse(prjDesc.getConfigurationById(id2).isModified());
}
+ /**
+ * Tests that we can load the environment stored as a single (old-style) long XML string
+ * Also tests that an an external change to the settings file is correctly picked up.
+ * @throws Exception
+ */
+ public void testOldStyleLoad() throws Exception {
+ final IProject project = ResourceHelper.createCDTProjectWithConfig("envProjectOldStyleLoad");
+
+ // Add another, derived configuration
+ ICProjectDescription prjDesc = CoreModel.getDefault().getProjectDescription(project);
+ ICConfigurationDescription desc = prjDesc.getActiveConfiguration();
+ final String id1 = desc.getId(); // Config 1's ID
+ final String id2 = "712427638"; // Config 2's ID
+ prjDesc.createConfiguration(id2, "config2", desc);
+ CoreModel.getDefault().setProjectDescription(project, prjDesc);
+
+ IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager();
+ IContributedEnvironment contribEnv = envManager.getContributedEnvironment();
+ final IEnvironmentVariable varOrig = new EnvironmentVariable("FOO", "ZOO");
+ contribEnv.addVariable(varOrig, prjDesc.getConfigurationById(id2));
+ CoreModel.getDefault().setProjectDescription(project, prjDesc);
+
+ final String env = "#Mon Nov 16 21:47:46 GMT 2009\n" +
+ "eclipse.preferences.version=1\n" +
+ "environment/project/712427638=\\n" +
+ "\\n" +
+ "\\n" +
+ "\\n" +
+ "\\n\n";
+ project.getFile(".settings/org.eclipse.cdt.core.prefs").setContents(new ByteArrayInputStream(env.getBytes("UTF-8")), true, false, null);
+
+ final IEnvironmentVariable var = new EnvironmentVariable("FOO", "BAR", IEnvironmentVariable.ENVVAR_APPEND, ";");
+ final IEnvironmentVariable var1 = new EnvironmentVariable("FOO1", "BAR1");
+ final IEnvironmentVariable var2 = new EnvironmentVariable("FOO2", "BAR2");
+
+ prjDesc = CoreModel.getDefault().getProjectDescription(project);
+ assertEquals(var, envManager.getVariable(var.getName(), prjDesc.getConfigurationById(id2), true));
+ assertEquals(var1, envManager.getVariable(var1.getName(), prjDesc.getConfigurationById(id2), true));
+ assertEquals(var2, envManager.getVariable(var2.getName(), prjDesc.getConfigurationById(id2), true));
+ }
+
+ /**
+ * Test that an ovewrite of new style preferences is loaded correctly
+ * @throws Exception
+ */
+ public void testNewStyleOverwrite() throws Exception {
+ final IProject project = ResourceHelper.createCDTProjectWithConfig("envProjectNewStyleLoad");
+
+ // Add another, derived configuration
+ ICProjectDescription prjDesc = CoreModel.getDefault().getProjectDescription(project);
+ ICConfigurationDescription desc = prjDesc.getActiveConfiguration();
+ final String id1 = desc.getId(); // Config 1's ID
+ final String id2 = "712427638"; // Config 2's ID
+ prjDesc.createConfiguration(id2, "config2", desc);
+ CoreModel.getDefault().setProjectDescription(project, prjDesc);
+
+ IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager();
+ IContributedEnvironment contribEnv = envManager.getContributedEnvironment();
+ // Variable which will be overwritten
+ final IEnvironmentVariable varOrig = new EnvironmentVariable("FOO", "ZOO");
+ contribEnv.addVariable(varOrig, prjDesc.getConfigurationById(id2));
+ CoreModel.getDefault().setProjectDescription(project, prjDesc);
+
+ final String env = "environment/project/712427638/FOO/delimiter=;\n" +
+ "environment/project/712427638/FOO/operation=append\n" +
+ "environment/project/712427638/FOO/value=BAR\n" +
+ "environment/project/712427638/FOO1/delimiter=\\:\n" +
+ "environment/project/712427638/FOO1/operation=replace\n" +
+ "environment/project/712427638/FOO1/value=BAR1\n" +
+ "environment/project/712427638/FOO2/delimiter=\\:\n" +
+ "environment/project/712427638/FOO2/operation=replace\n" +
+ "environment/project/712427638/FOO2/value=BAR2\n" +
+ "environment/project/712427638/append=true\n" +
+ "environment/project/712427638/appendContributed=true\n";
+ project.getFile(".settings/org.eclipse.cdt.core.prefs").setContents(new ByteArrayInputStream(env.getBytes("UTF-8")), true, false, null);
+
+ final IEnvironmentVariable var = new EnvironmentVariable("FOO", "BAR", IEnvironmentVariable.ENVVAR_APPEND, ";");
+ final IEnvironmentVariable var1 = new EnvironmentVariable("FOO1", "BAR1");
+ final IEnvironmentVariable var2 = new EnvironmentVariable("FOO2", "BAR2");
+
+ prjDesc = CoreModel.getDefault().getProjectDescription(project);
+ assertEquals(var, envManager.getVariable(var.getName(), prjDesc.getConfigurationById(id2), true));
+ assertEquals(var1, envManager.getVariable(var1.getName(), prjDesc.getConfigurationById(id2), true));
+ assertEquals(var2, envManager.getVariable(var2.getName(), prjDesc.getConfigurationById(id2), true));
+ }
public void testNoChangeToOneVariable() throws Exception {
final IProject project = ResourceHelper.createCDTProjectWithConfig("envProject");
@@ -105,7 +199,7 @@ public class IEnvironmentVariableManagerTests extends TestCase {
// Try setting an environment variable
final IEnvironmentVariable var = new EnvironmentVariable("FOO", "BAR");
final IEnvironmentVariable var1 = new EnvironmentVariable("FOO1", "BAR1");
- final IEnvironmentVariable var2 = new EnvironmentVariable("FOO2", "BAR2");
+ final IEnvironmentVariable var2 = new EnvironmentVariable("FOO2", "BAR2");
contribEnv.addVariable(var, prjDesc.getConfigurationById(id1));
contribEnv.addVariable(var1, prjDesc.getConfigurationById(id1));
contribEnv.addVariable(var2, prjDesc.getConfigurationById(id1));
@@ -138,7 +232,7 @@ public class IEnvironmentVariableManagerTests extends TestCase {
project.close(null);
project.open(null);
prjDesc = CoreModel.getDefault().getProjectDescription(project);
-
+
readVar = envManager.getVariable(var3.getName(), prjDesc.getConfigurationById(id1), true);
assertEquals(var3, readVar);
readVar = envManager.getVariable(var1.getName(), prjDesc.getConfigurationById(id1), true);
@@ -146,12 +240,141 @@ public class IEnvironmentVariableManagerTests extends TestCase {
readVar = envManager.getVariable(var2.getName(), prjDesc.getConfigurationById(id1), true);
assertEquals(var2, readVar);
}
-
+
+ /**
+ * tests the get / set append persisting
+ */
+ public void testGetSetAppend() throws Exception {
+ final IProject project = ResourceHelper.createCDTProjectWithConfig("envProject");
+
+ // Add another, derived configuration
+ ICProjectDescription prjDesc = CoreModel.getDefault().getProjectDescription(project);
+ ICConfigurationDescription desc = prjDesc.getActiveConfiguration();
+ final String id1 = desc.getId(); // Config 1's ID
+ final String id2 = CDataUtil.genId(id1); // Config 2's ID
+ prjDesc.createConfiguration(id2, "config2", desc);
+ CoreModel.getDefault().setProjectDescription(project, prjDesc);
+
+ // Get all the configurations
+ prjDesc = CoreModel.getDefault().getProjectDescription(project);
+ ICConfigurationDescription[] descs = prjDesc.getConfigurations();
+ assertEquals(2, descs.length);
+
+ IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager();
+ IContributedEnvironment contribEnv = envManager.getContributedEnvironment();
+
+ assertFalse(descs[0].isModified());
+ assertFalse(descs[1].isModified());
+
+ // Set append & append contributed on the 2 configs respectively
+ final boolean append = contribEnv.appendEnvironment(prjDesc.getConfigurationById(id2));
+ contribEnv.setAppendEnvironment(!append, prjDesc.getConfigurationById(id2));
+ assertEquals(!append, contribEnv.appendEnvironment(prjDesc.getConfigurationById(id2)));
+ assertFalse(prjDesc.getConfigurationById(id1).isModified());
+ assertTrue(prjDesc.getConfigurationById(id2).isModified());
+
+ CoreModel.getDefault().setProjectDescription(project, prjDesc);
+
+ // Close and reopen, variables should still exist
+ project.close(null);
+ project.open(null);
+ prjDesc = CoreModel.getDefault().getProjectDescription(project);
+ assertEquals(!append, contribEnv.appendEnvironment(prjDesc.getConfigurationById(id2)));
+ assertFalse(prjDesc.getConfigurationById(id1).isModified());
+ assertFalse(prjDesc.getConfigurationById(id2).isModified());
+ }
+
+ /**
+ * Tests file system change of the settings file
+ */
+ public void testSettingsOverwrite() throws Exception {
+ final IProject project = ResourceHelper.createCDTProjectWithConfig("envProject");
+
+ // Add another, derived configuration
+ ICProjectDescription prjDesc = CoreModel.getDefault().getProjectDescription(project);
+ ICConfigurationDescription desc = prjDesc.getActiveConfiguration();
+ final String id1 = desc.getId(); // Config 1's ID
+ final String id2 = CDataUtil.genId(id1); // Config 2's ID
+ prjDesc.createConfiguration(id2, "config2", desc);
+ CoreModel.getDefault().setProjectDescription(project, prjDesc);
+
+ // Get all the configurations
+ prjDesc = CoreModel.getDefault().getProjectDescription(project);
+ ICConfigurationDescription[] descs = prjDesc.getConfigurations();
+ assertTrue(descs.length == 2);
+
+ IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager();
+ IContributedEnvironment contribEnv = envManager.getContributedEnvironment();
+
+ assertFalse(descs[0].isModified());
+ assertFalse(descs[1].isModified());
+
+ // Try setting an environment variable
+ final IEnvironmentVariable var = new EnvironmentVariable("FOO", "BAR");
+ contribEnv.addVariable(var, prjDesc.getConfigurationById(id1));
+ assertTrue(prjDesc.getConfigurationById(id1).isModified());
+ assertFalse(prjDesc.getConfigurationById(id2).isModified());
+ CoreModel.getDefault().setProjectDescription(project, prjDesc);
+
+ // Backup the settings file
+ project.getFile(".settings/org.eclipse.cdt.core.prefs.bak").create(
+ project.getFile(".settings/org.eclipse.cdt.core.prefs").getContents(), true, null);
+
+ // Change the environment variable
+ final IEnvironmentVariable var2 = new EnvironmentVariable("FOO", "BOO");
+ contribEnv.addVariable(var2, prjDesc.getConfigurationById(id1));
+ assertEquals(var2, envManager.getVariable(var2.getName(), prjDesc.getConfigurationById(id1), true));
+ CoreModel.getDefault().setProjectDescription(project, prjDesc);
+
+ // Replace the settings with it's backup
+ project.getFile(".settings/org.eclipse.cdt.core.prefs").setContents(
+ project.getFile(".settings/org.eclipse.cdt.core.prefs.bak").getContents(), true, false, null);
+ prjDesc = CoreModel.getDefault().getProjectDescription(project);
+ assertEquals(var, envManager.getVariable(var.getName(), prjDesc.getConfigurationById(id1), true));
+ }
+
+ /**
+ * Test that on deleting and recreating the project variables haven't persisted
+ * @throws Exception
+ */
+ public void testBrokenCaching() throws Exception {
+ final IProject project = ResourceHelper.createCDTProjectWithConfig("envProject");
+
+ // Add another, derived configuration
+ ICProjectDescription prjDesc = CoreModel.getDefault().getProjectDescription(project);
+ ICConfigurationDescription desc = prjDesc.getActiveConfiguration();
+ final String id1 = desc.getId();
+
+ IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager();
+ IContributedEnvironment contribEnv = envManager.getContributedEnvironment();
+ // At the moment 0 variables are set
+ assertEquals(0, contribEnv.getVariables(desc).length);
+
+ // Try setting an environment variable
+ final IEnvironmentVariable var = new EnvironmentVariable("FOO", "BAR");
+ contribEnv.addVariable(var, prjDesc.getConfigurationById(id1));
+ assertEquals(1, contribEnv.getVariables(desc).length);
+ // Check that the variable exists on config1
+ IEnvironmentVariable readVar = envManager.getVariable(var.getName(), prjDesc.getConfigurationById(id1), true);
+ assertEquals(var, readVar);
+
+ // Save the project description
+ CoreModel.getDefault().setProjectDescription(project, prjDesc);
+
+ ResourceHelper.cleanUp();
+ assertFalse(project.exists());
+ ResourceHelper.createCDTProjectWithConfig("envProject");
+ assertTrue(project.exists());
+ // Fetch the current configuration
+ prjDesc = CoreModel.getDefault().getProjectDescription(project);
+ desc = prjDesc.getActiveConfiguration();
+ assertEquals(0, contribEnv.getVariables(desc).length);
+ }
/**
* This bug checks for an environment load race during project open / import.
*
- * This occurs because enviornment is stored using platform Preferences (persisted in
+ * This occurs because environment is stored using platform Preferences (persisted in
* the .settings directory) and, when background refresh is enabled this is loaded
* asynchronously.
*
@@ -172,7 +395,7 @@ public class IEnvironmentVariableManagerTests extends TestCase {
// Try setting an environment variable
final IEnvironmentVariable var = new EnvironmentVariable("FOO", "BAR");
final IEnvironmentVariable var1 = new EnvironmentVariable("FOO1", "BAR1");
- final IEnvironmentVariable var2 = new EnvironmentVariable("FOO2", "BAR2");
+ final IEnvironmentVariable var2 = new EnvironmentVariable("FOO2", "BAR2");
contribEnv.addVariable(var, prjDesc.getConfigurationById(id1));
// Check that the variable exists on config1
@@ -221,7 +444,7 @@ public class IEnvironmentVariableManagerTests extends TestCase {
assertNull(readVar);
readVar = envManager.getVariable(var2.getName(), prjDesc.getConfigurationById(id1), true);
assertEquals(var3, readVar);
-
+
// Get project description should only have the persisted envvar
prjDesc = CoreModel.getDefault().getProjectDescription(project);
readVar = envManager.getVariable(var.getName(), prjDesc.getConfigurationById(id1), true);
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CConfigurationSpecSettings.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CConfigurationSpecSettings.java
index b2d58724b85..7f2692f5e6b 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CConfigurationSpecSettings.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CConfigurationSpecSettings.java
@@ -37,6 +37,7 @@ import org.eclipse.cdt.internal.core.CExtensionInfo;
import org.eclipse.cdt.internal.core.COwner;
import org.eclipse.cdt.internal.core.COwnerConfiguration;
import org.eclipse.cdt.internal.core.cdtvariables.StorableCdtVariables;
+import org.eclipse.cdt.internal.core.envvar.EnvironmentVariableManager;
import org.eclipse.cdt.utils.envvar.StorableEnvironment;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.QualifiedName;
@@ -161,7 +162,7 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
fSessionPropertiesMap = (HashMap)base.fSessionPropertiesMap.clone();
if(base.fEnvironment != null)
- fEnvironment = new StorableEnvironment(base.fEnvironment, des.isReadOnly());
+ fEnvironment = EnvironmentVariableManager.fUserSupplier.cloneEnvironmentWithContext(fCfg, base.fEnvironment, des.isReadOnly());
fOwnerId = base.fOwnerId;
fOwner = base.fOwner;
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/envvar/PrefsStorableEnvironment.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/envvar/PrefsStorableEnvironment.java
new file mode 100644
index 00000000000..21b98e57ec2
--- /dev/null
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/envvar/PrefsStorableEnvironment.java
@@ -0,0 +1,507 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Broadcom Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * James Blackburn (Broadcom Corp.)
+ *******************************************************************************/
+package org.eclipse.cdt.utils.envvar;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
+import org.eclipse.cdt.core.settings.model.ICStorageElement;
+import org.eclipse.cdt.utils.envvar.StorableEnvironmentLoader.ISerializeInfo;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.INodeChangeListener;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.NodeChangeEvent;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
+import org.osgi.service.prefs.BackingStoreException;
+import org.osgi.service.prefs.Preferences;
+
+/**
+ * This class represents the set of environment variables that could be loaded
+ * and stored from a IEclipsePreferences store. It acts like an OverlayStore caching
+ * outstanding changes while not yet serialized, as well as responding to change
+ * in the Preference store itself.
+ *
+ * fCachedSerialEnv is a cache of the contents of the preference store
+ * fVariables (in parent) contains runtime added / changed variables
+ * fDeleteVaraibles contains delete variable names
+ * When serialize is called, all changes in Variables / Delete are serialized to the
+ * ISerializeInfo store, Cached is updated, and fVariables and fDeletedVariables cleared.
+ *
+ * StorableEnvironment stores the Preferences in a single XML encoded String in
+ * ISerializeInfo.getNode().get(ISerializeInfo.getName())
+ * This class defaults to storing the environment as 'Raw' items in the Preferences
+ * under:
+ * ISerializeInfo.getNode().node(ISerializeInfo.getName())
+ *
+ * @since 5.2
+ * @noextend This class is not intended to be subclassed by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class PrefsStorableEnvironment extends StorableEnvironment {
+
+ /** Handle on the storage */
+ private ISerializeInfo fSerialEnv;
+
+ /** Set of 'deleted' variables (to be removed from the backing store) */
+ protected Set fDeletedVariables;
+
+ // State to manage and handle external changes to the environment
+
+ /** Cache of Environment as loaded from the {@link ISerializeInfo}
+ * contains no non-persisted changes */
+ private Map fCachedSerialEnv = new HashMap();
+
+ // State to track whether API users have changed these boolean values
+ private boolean fAppendChanged = false;
+ private boolean fAppendContributedChanged = false;
+
+ /** A listener for changes in the backing store */
+ private static class PrefListener implements IPreferenceChangeListener, INodeChangeListener {
+
+ /** boolean indicating whether preferences have changed */
+ private volatile boolean prefsChanged = true;
+
+ /** The node we're registered on */
+ volatile IEclipsePreferences prefs;
+
+ public PrefListener(ISerializeInfo info) {
+ register (info);
+ }
+
+ /**
+ * Remove the listener
+ */
+ public void remove() {
+ if (prefs != null) {
+ try {
+ prefs.removePreferenceChangeListener(this);
+ prefs.removeNodeChangeListener(this);
+ } catch (Exception e) {
+ // Catch all exceptions, this is called during parent finalization which we don't want to prevent...
+ // e.g. IllegalStateException may occur during de-register
+ }
+ prefs = null;
+ }
+ }
+
+ /**
+ * Register the Prefs change listener
+ */
+ private void register(ISerializeInfo info) {
+ if (prefs != null)
+ return;
+ prefs = (IEclipsePreferences)info.getNode();
+ if (prefs != null) {
+ prefs.addPreferenceChangeListener(this);
+ prefs.addNodeChangeListener(this);
+ }
+ prefsChanged = true;
+ }
+
+ /**
+ * Return & unset flag indicating if there has been a change in the backing store
+ * @return whether there's been a change in the backing store
+ */
+ public boolean preferencesChanged(ISerializeInfo info) {
+ if (prefs == null)
+ register(info);
+
+ boolean retVal = prefsChanged;
+ // If we're registered for change, then unset
+ if (prefs != null)
+ prefsChanged = false;
+ return retVal;
+ }
+
+ public void preferenceChange(PreferenceChangeEvent event) {
+ prefsChanged = true;
+ }
+ public void added(NodeChangeEvent event) {
+ prefsChanged = true;
+ }
+ public void removed(NodeChangeEvent event) {
+ prefsChanged = true;
+ }
+ }
+ private PrefListener fPrefsChangedListener;
+
+ /**
+ * The set of variables which have been 'deleted' by the user.
+ * @return the live removed {@link IEnvironmentVariable} map
+ */
+ private Set getDeletedSet(){
+ if(fDeletedVariables == null)
+ fDeletedVariables = new HashSet();
+ return fDeletedVariables;
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * Creates a new StorableEnvironment from an existing StorableEnvironment. Settings
+ * are copied wholesale from the previous enviornment.
+ *
+ * Note that the previous environment's {@link ISerializeInfo} isn't copied
+ * over, as it's expected this environment's settings will be stored elsewhere
+ *
+ * @param env
+ * @param isReadOnly
+ */
+ PrefsStorableEnvironment(StorableEnvironment env, ISerializeInfo serializeInfo, boolean isReadOnly) {
+ super(isReadOnly);
+
+ // Copy shared mutable state
+ fAppend = env.fAppend;
+ fAppendContributedEnv = env.fAppendContributedEnv;
+
+ // If base is a PrefsStorableEnv, add other internal data
+ if (env instanceof PrefsStorableEnvironment) {
+ PrefsStorableEnvironment other = (PrefsStorableEnvironment)env;
+ fAppendChanged = other.fAppendChanged;
+ fAppendContributedChanged = other.fAppendContributedChanged;
+
+ // If this environemnt is a *copy* of another environment
+ // then copy over *all* variables into our live variable map
+ if (serializeInfo == null || other.fSerialEnv == null ||
+ !serializeInfo.getPrefName().equals(other.fSerialEnv.getPrefName()))
+ fVariables = env.getAllVariablesMap();
+ else {
+ // Just a runtime copy using existing ISerializeInfo Store, just clone runtime
+ // runtime changed state
+ if (other.fVariables != null)
+ getMap().putAll(other.fVariables);
+ if (other.fDeletedVariables != null)
+ getDeletedSet().addAll(other.fDeletedVariables);
+ }
+ } else {
+ // add all variables
+ if(env.fVariables != null)
+ fVariables = env.getAllVariablesMap();
+ // Assume the append & appendContributed are changed
+ fAppendChanged = true;
+ fAppendContributedChanged = true;
+ }
+ // Set the serializeInfo on this env
+ setSerializeInfo(serializeInfo);
+ }
+
+ /**
+ * Create a StorableEnvironment backed by this ISerializeInfo.
+ *
+ * This StorabelEnvironment will respond to changes in the backing store
+ *
+ * @param serializeInfo
+ * @since 5.2
+ */
+ PrefsStorableEnvironment(ISerializeInfo serializeInfo, boolean isReadOnly) {
+ super(isReadOnly);
+ setSerializeInfo(serializeInfo);
+ }
+
+ /**
+ * Set the {@link ISerializeInfo} which persists this environment
+ * @param serializeInfo
+ */
+ private void setSerializeInfo(ISerializeInfo serializeInfo) {
+ if (fPrefsChangedListener != null)
+ fPrefsChangedListener.remove();
+ fSerialEnv = serializeInfo;
+ fPrefsChangedListener = new PrefListener(fSerialEnv);
+
+ // Update the cached state
+ checkBackingSerializeInfo();
+ }
+
+ /**
+ * Check and update the state of the backing {@link ISerializeInfo} cache
+ * Acts as a reconciler, keeping the environment up to date as it's updated externally
+ */
+ private void checkBackingSerializeInfo() {
+ // Any change?
+ if (!fPrefsChangedListener.preferencesChanged(fSerialEnv))
+ return;
+
+ Preferences topNode = fSerialEnv.getNode();
+ if (topNode == null)
+ return;
+
+ try {
+ if (topNode.get(fSerialEnv.getPrefName(), "").length() != 0) //$NON-NLS-1$
+ migrateOldStylePrefs();
+
+ // Does our storage node exist?
+ if (topNode.nodeExists(fSerialEnv.getPrefName())) {
+ // Clear the cache
+ fCachedSerialEnv.clear();
+ // new style preferences are stored individually in the node
+ Preferences prefs = topNode.node(fSerialEnv.getPrefName());
+ try {
+ for (String child : prefs.childrenNames()) {
+ String name = getNameForMap(child);
+ IEnvironmentVariable env = new StorableEnvVar(child, prefs.node(child));
+ addVariable(fCachedSerialEnv, env);
+ if (env.equals(getMap().get(name)))
+ getMap().remove(name);
+ }
+ } catch (BackingStoreException e) {
+ CCorePlugin.log(e);
+ }
+ // Remove deleted items no longer in the map
+ if (fDeletedVariables != null) {
+ Iterator it = fDeletedVariables.iterator();
+ while(it.hasNext()) {
+ String name = it.next();
+ if (!fCachedSerialEnv.containsKey(name))
+ it.remove();
+ }
+ if (fDeletedVariables.isEmpty())
+ fDeletedVariables = null;
+ }
+ // Update flag variables
+ boolean append = prefs.getBoolean(ATTRIBUTE_APPEND, DEFAULT_APPEND);
+ if (!fAppendChanged || fAppend == append) {
+ fAppend = append;
+ fAppendChanged = false;
+ }
+ append = prefs.getBoolean(ATTRIBUTE_APPEND_CONTRIBUTED, DEFAULT_APPEND);
+ if (!fAppendContributedChanged || fAppendContributedEnv == append) {
+ fAppendContributedEnv = append;
+ fAppendContributedChanged = false;
+ }
+ }
+ } catch (BackingStoreException e) {
+ // Unexpected...
+ CCorePlugin.log(e);
+ }
+ }
+
+ /**
+ * Migrates an old style preference storage.
+ * - Previously preferences were encoded in an ICStorageElement XML string in a text element under key {@link ISerializeInfo#getPrefName()}
+ * in {@link ISerializeInfo#getNode()}
+ * - Now they're stored directly in the preference Node ISerializeInfo#getNode()#node(ISerializeInfo#getPrefName())
+ */
+ private void migrateOldStylePrefs() {
+ // Fall-back to loading Preferences from the old style encoded XML String
+ // topNode.get(fSerialEnv.getPrefName(), def)
+ String envString = StorableEnvironmentLoader.loadPreferenceNode(fSerialEnv);
+ ICStorageElement element = StorableEnvironmentLoader.environmentStorageFromString(envString);
+ try {
+ if (element != null) {
+ Preferences oldNode = fSerialEnv.getNode();
+ oldNode.put(fSerialEnv.getPrefName(), ""); //$NON-NLS-1$
+ oldNode.flush();
+
+ // New Preferences node
+ Preferences newNode = fSerialEnv.getNode().node(fSerialEnv.getPrefName());
+ StorableEnvironment oldEnv = new StorableEnvironment(element, false);
+ for (Map.Entry e : oldEnv.getMap().entrySet())
+ ((StorableEnvVar)e.getValue()).serialize(newNode.node(e.getKey()));
+ fCachedSerialEnv.putAll(oldEnv.getMap());
+ if (!fAppendChanged)
+ fAppend = oldEnv.fAppend;
+ newNode.putBoolean(ATTRIBUTE_APPEND, fAppend);
+ if (!fAppendContributedChanged)
+ fAppendContributedEnv = oldEnv.fAppendContributedEnv;
+ newNode.putBoolean(ATTRIBUTE_APPEND_CONTRIBUTED, fAppendContributedEnv);
+ // flush
+ fSerialEnv.getNode().flush();
+ }
+ } catch (BackingStoreException e) {
+ CCorePlugin.log(e);
+ }
+ }
+
+ /**
+ * Serialize the Storable environment into the ICStorageElement
+ *
+ * NB assumes that any variables part of the ISerializeInfo will continue to be serialized
+ * Use #serialize instead for persisting into the Preference store
+ * @param element
+ * @deprecated
+ */
+ @Deprecated
+ @Override
+ public void serialize(ICStorageElement element){
+ checkBackingSerializeInfo();
+ Map map = getAllVariablesMap();
+
+ element.setAttribute(ATTRIBUTE_APPEND, Boolean.valueOf(fAppend).toString());
+ element.setAttribute(ATTRIBUTE_APPEND_CONTRIBUTED, Boolean.valueOf(fAppendContributedEnv).toString());
+ if(!map.isEmpty()){
+ Iterator iter = map.values().iterator();
+ while(iter.hasNext()){
+ StorableEnvVar var = (StorableEnvVar)iter.next();
+ ICStorageElement varEl = element.createChild(StorableEnvVar.VARIABLE_ELEMENT_NAME);
+ var.serialize(varEl);
+ }
+ }
+ }
+
+ /**
+ * Serialize the element into the current Preference node
+ *
+ * At the end of this fCacheSerialEnv represents the state of the world
+ * and the runtime state {@link #fDeletedVariables} && {@link #fVariables}
+ * are empty
+ */
+ void serialize() {
+ if (!isDirty())
+ return;
+ Preferences element = fSerialEnv.getNode().node(fSerialEnv.getPrefName());
+ element.putBoolean(ATTRIBUTE_APPEND, fAppend);
+ fAppendChanged = false;
+ element.putBoolean(ATTRIBUTE_APPEND_CONTRIBUTED, fAppendContributedEnv);
+ fAppendContributedChanged = false;
+ // Need to remove the delete elements
+ try {
+ if (fDeletedVariables != null) {
+ for (String delete : fDeletedVariables) {
+ element.node(delete).removeNode();
+ fCachedSerialEnv.remove(delete);
+ }
+ fDeletedVariables.clear();
+ }
+ } catch (BackingStoreException e) {
+ CCorePlugin.log(e);
+ }
+ // Only need to serialize the 'changed' elements
+ if(fVariables != null) {
+ for (Map.Entry e : fVariables.entrySet())
+ ((StorableEnvVar)e.getValue()).serialize(element.node(e.getKey()));
+ fCachedSerialEnv.putAll(fVariables);
+ fVariables.clear();
+ }
+ try {
+ element.flush();
+ } catch (BackingStoreException e) {
+ CCorePlugin.log(e);
+ }
+ }
+
+ @Override
+ public IEnvironmentVariable createVariable(String name, String value, int op, String delimiter){
+ IEnvironmentVariable var = super.createVariable(name, value, op, delimiter);
+ if (var != null) {
+ if (fDeletedVariables != null)
+ fDeletedVariables.remove(getNameForMap(name));
+ // If this variable is identical to one in the map, then no change...
+ if (var.equals(fCachedSerialEnv.get(getNameForMap(name))))
+ getMap().remove(getNameForMap(name));
+ }
+ return var;
+ }
+
+ /**
+ * @param name
+ * @return the environment variable with the given name, or null
+ */
+ @Override
+ public IEnvironmentVariable getVariable(String name){
+ name = getNameForMap(name);
+ IEnvironmentVariable var = super.getVariable(name);
+ if (var != null)
+ return var;
+
+ if (fDeletedVariables != null && fDeletedVariables.contains(name))
+ return null;
+
+ checkBackingSerializeInfo();
+ return fCachedSerialEnv.get(name);
+ }
+
+ /**
+ * @return cloned map of all variables set on this storable environment runtime variables + backing store vars
+ */
+ @Override
+ Map getAllVariablesMap() {
+ checkBackingSerializeInfo();
+ // Get all the environment from the backing store first
+ Map vars = new HashMap();
+ if (fCachedSerialEnv != null)
+ vars.putAll(fCachedSerialEnv);
+ if (fDeletedVariables != null)
+ for (String name : fDeletedVariables)
+ vars.remove(name);
+
+ // Now overwrite with the live variables set, and return
+ vars.putAll(getMap());
+ return vars;
+ }
+
+ @Override
+ public IEnvironmentVariable deleteVariable(String name) {
+ name = getNameForMap(name);
+ IEnvironmentVariable var = super.deleteVariable(name);
+ if (name == null)
+ return null;
+ getDeletedSet().add(name);
+ return var;
+ }
+
+ @Override
+ public boolean deleteAll(){
+ boolean change = super.deleteAll();
+
+ // Change should include any cached variables we're overwriting
+ change = change || !getDeletedSet().equals(fCachedSerialEnv.keySet());
+ getDeletedSet().addAll(fCachedSerialEnv.keySet());
+ if (change) {
+ fIsChanged = true;
+ }
+ return change;
+ }
+
+ @Override
+ public void setAppendEnvironment(boolean append){
+ boolean prevVal = fAppend;
+ super.setAppendEnvironment(append);
+ if (prevVal != fAppend)
+ fAppendChanged = true;
+ }
+
+ @Override
+ public void setAppendContributedEnvironment(boolean append){
+ boolean prevVal = fAppendContributedEnv;
+ super.setAppendContributedEnvironment(append);
+ if (prevVal != fAppendContributedEnv)
+ fAppendContributedChanged = true;
+ }
+
+ @Override
+ public void restoreDefaults(){
+ super.restoreDefaults();
+ fAppendChanged = false;
+ fAppendContributedChanged = false;
+ }
+
+ @Override
+ public boolean isDirty() {
+ return fAppendChanged || fAppendContributedChanged ||
+ (fVariables != null && !fVariables.isEmpty()) ||
+ (fDeletedVariables != null && !fDeletedVariables.isEmpty());
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+ // Remove the preference change listener when this Storable Environment
+ // is no longer referenced...
+ if (fPrefsChangedListener != null)
+ fPrefsChangedListener.remove();
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/envvar/StorableEnvVar.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/envvar/StorableEnvVar.java
index 0dc747cb989..bb1cbac3491 100644
--- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/envvar/StorableEnvVar.java
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/envvar/StorableEnvVar.java
@@ -1,24 +1,25 @@
/*******************************************************************************
- * Copyright (c) 2005, 2007 Intel Corporation and others.
+ * Copyright (c) 2005, 2009 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Intel Corporation - Initial API and implementation
+ * Intel Corporation - Initial API and implementation
+ * James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.utils.envvar;
import org.eclipse.cdt.core.envvar.EnvironmentVariable;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
+import org.osgi.service.prefs.Preferences;
/**
* This class represents the Environment variable that could be loaded
* and stored in XML
*
* @since 3.0
- *
*/
public class StorableEnvVar extends EnvironmentVariable {
public static final String VARIABLE_ELEMENT_NAME = "variable"; //$NON-NLS-1$
@@ -47,12 +48,12 @@ public class StorableEnvVar extends EnvironmentVariable {
public StorableEnvVar(String name, String value, String delimiter){
this(name,value,ENVVAR_REPLACE,delimiter);
}
-
+
+ /**
+ * Load the environment variable from the ICStorageElement
+ * @param element
+ */
public StorableEnvVar(ICStorageElement element){
- load(element);
- }
-
- private void load(ICStorageElement element){
fName = element.getAttribute(NAME);
fValue = element.getAttribute(VALUE);
@@ -63,6 +64,20 @@ public class StorableEnvVar extends EnvironmentVariable {
if("".equals(fDelimiter)) //$NON-NLS-1$
fDelimiter = null;
}
+
+ /**
+ * Load the Environment Variable directly from a Preference element
+ * @param name
+ * @param element
+ * @since 5.2
+ */
+ public StorableEnvVar(String name, Preferences element){
+ fName = name;
+ fValue = element.get(VALUE, null);
+ fOperation = opStringToInt(element.get(OPERATION, null));
+ fDelimiter = element.get(DELIMITER, null);
+ }
+
private int opStringToInt(String op){
int operation;
@@ -106,4 +121,20 @@ public class StorableEnvVar extends EnvironmentVariable {
if(fDelimiter != null)
element.setAttribute(DELIMITER,fDelimiter);
}
+
+ /**
+ * Serialize this Preference straight into the Preferences element.
+ * It's assumed that the Preference node represents this StorableEnvVar's name
+ * @param element
+ * @since 5.2
+ */
+ public void serialize(Preferences element) {
+ if(fValue != null)
+ element.put(VALUE, fValue);
+
+ element.put(OPERATION, opIntToString(fOperation));
+
+ if(fDelimiter != null)
+ element.put(DELIMITER, fDelimiter);
+ }
}
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/envvar/StorableEnvironment.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/envvar/StorableEnvironment.java
index 32b009b4e10..69d360d44a1 100644
--- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/envvar/StorableEnvironment.java
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/envvar/StorableEnvironment.java
@@ -16,7 +16,6 @@ import java.util.Iterator;
import java.util.Map;
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
-import org.eclipse.cdt.core.envvar.IEnvironmentVariableManager;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.internal.core.envvar.EnvironmentVariableManager;
import org.eclipse.cdt.internal.core.settings.model.ExceptionFactory;
@@ -28,136 +27,81 @@ import org.eclipse.cdt.utils.envvar.StorableEnvironmentLoader.ISerializeInfo;
*
* @since 3.0
*/
-public class StorableEnvironment /*implements Cloneable*/{
+public class StorableEnvironment {
public static final String ENVIRONMENT_ELEMENT_NAME = "environment"; //$NON-NLS-1$
- private static final String ATTRIBUTE_APPEND = "append"; //$NON-NLS-1$
- private static final String ATTRIBUTE_APPEND_CONTRIBUTED = "appendContributed"; //$NON-NLS-1$
- private static final boolean DEFAULT_APPEND = true;
+ static final String ATTRIBUTE_APPEND = "append"; //$NON-NLS-1$
+ static final String ATTRIBUTE_APPEND_CONTRIBUTED = "appendContributed"; //$NON-NLS-1$
+ static final boolean DEFAULT_APPEND = true;
/** The map of in-flight environment variables */
- private HashMap fVariables;
- /** Map of 'deleted' variables (which shouldn't be updated by a backing store change) */
- private HashMap fDeletedVariables;
+ Map fVariables;
private boolean fIsDirty = false;
- private boolean fIsChanged = false;
- private final boolean fIsReadOnly;
- private boolean fAppend = DEFAULT_APPEND;
- private boolean fAppendContributedEnv = DEFAULT_APPEND;
-
-
- // State to manage and handle external changes to the environment
-
- /** A cache copy of the environment as stored in the {@link ISerializeInfo}
- * used to work-out whether the cachedStorableEnvironment map needs refreshing */
- private String fCachedSerialEnvString;
- /** Map of Environment as loaded from the {@link ISerializeInfo} */
- private HashMap fCachedSerialEnv;
- private ISerializeInfo fSerialEnv;
- // State to track whether API users have changed these boolean values
- private boolean fAppendChanged = false;
- private boolean fAppendContributedChanged = false;
-
+ boolean fIsChanged = false;
+ final boolean fIsReadOnly;
+ boolean fAppend = DEFAULT_APPEND;
+ boolean fAppendContributedEnv = DEFAULT_APPEND;
/**
* @return the live {@link IEnvironmentVariable} map
*/
- private Map getMap(){
+ Map getMap(){
if(fVariables == null)
fVariables = new HashMap();
return fVariables;
}
- /**
- * @return the live removed {@link IEnvironmentVariable} map
- */
- private Map getDeletedMap(){
- if(fDeletedVariables == null)
- fDeletedVariables = new HashMap();
- return fDeletedVariables;
- }
+ /**
+ *
+ * @param variables
+ * @param isReadOnly
+ */
public StorableEnvironment(IEnvironmentVariable variables[], boolean isReadOnly) {
setVariales(variables);
fIsReadOnly = isReadOnly;
}
+ /**
+ * Create new empty StorableEnvironment
+ * @param isReadOnly
+ */
public StorableEnvironment(boolean isReadOnly) {
fIsReadOnly = isReadOnly;
}
+ /**
+ * Copy constructor.
+ *
+ * Creates a new StorableEnvironment from an existing StorableEnvironment. Settings
+ * are copied wholesale from the previous enviornment.
+ *
+ * Note that the previous environment's {@link ISerializeInfo} isn't copied
+ * over, as it's expected this environment's settings will be stored elsewhere
+ *
+ * @param env
+ * @param isReadOnly
+ */
public StorableEnvironment(StorableEnvironment env, boolean isReadOnly) {
- if(env.fVariables != null) {
- @SuppressWarnings("unchecked")
- final HashMap clone = (HashMap)env.fVariables.clone();
- fVariables = clone;
- }
- if(env.fDeletedVariables != null) {
- @SuppressWarnings("unchecked")
- final HashMap clone = (HashMap)env.fDeletedVariables.clone();
- fDeletedVariables = clone;
- }
- fSerialEnv = env.fSerialEnv;
+ if(env.fVariables != null)
+ fVariables = env.getAllVariablesMap();
fAppend = env.fAppend;
- fAppendChanged = env.fAppendChanged;
fAppendContributedEnv = env.fAppendContributedEnv;
- fAppendContributedChanged = env.fAppendContributedChanged;
fIsReadOnly = isReadOnly;
fIsDirty = env.isDirty();
}
+ /**
+ * Initialize the StorableEnvironment from an ICStorageElement tree
+ * @param element
+ * @param isReadOnly
+ */
public StorableEnvironment(ICStorageElement element, boolean isReadOnly) {
load(element);
fIsReadOnly = isReadOnly;
}
/**
- * Create a StorableEnvironment backed by this ISerializeInfo.
- *
- * @param serializeInfo
- * @since 5.2
+ * Load the preferences from an {@link ICStorageElement}
+ * @param element
*/
- StorableEnvironment(ISerializeInfo serializeInfo, boolean isReadOnly) {
- fIsReadOnly = isReadOnly;
- fSerialEnv = serializeInfo;
-
- // Update the cached state
- checkBackingSerializeInfo();
- }
-
- /**
- * Check and update the state of the backing {@link ISerializeInfo} cache
- */
- private void checkBackingSerializeInfo() {
- String envString = StorableEnvironmentLoader.loadPreferenceNode(fSerialEnv);
-
- // Has anything changed?
- if (envString == null || envString.equals(fCachedSerialEnvString))
- return;
- fCachedSerialEnvString = envString;
-
- ICStorageElement element = StorableEnvironmentLoader.environmentStorageFromString(fCachedSerialEnvString);
- if (element == null)
- return;
-
- // Now update the cached environment
- if (fCachedSerialEnv == null)
- fCachedSerialEnv = new HashMap();
- else
- fCachedSerialEnv.clear();
-
- for (ICStorageElement child : element.getChildren())
- if (child.getName().equals(StorableEnvVar.VARIABLE_ELEMENT_NAME))
- addVariable(fCachedSerialEnv, new StorableEnvVar(child));
-
- // If user hasn't changed fAppend or fAppend Contributed, then update
- if (!fAppendChanged) {
- String append = element.getAttribute(ATTRIBUTE_APPEND);
- fAppend = append != null ? Boolean.valueOf(append).booleanValue() : DEFAULT_APPEND;
- }
- if (!fAppendContributedChanged) {
- String append = element.getAttribute(ATTRIBUTE_APPEND_CONTRIBUTED);
- fAppendContributedEnv = append != null ? Boolean.valueOf(append).booleanValue() : DEFAULT_APPEND;
- }
- }
-
private void load(ICStorageElement element){
ICStorageElement children[] = element.getChildren();
for (int i = 0; i < children.length; ++i) {
@@ -186,22 +130,10 @@ public class StorableEnvironment /*implements Cloneable*/{
* @param element
*/
public void serialize(ICStorageElement element){
- checkBackingSerializeInfo();
- Map map = new HashMap();
- if (fCachedSerialEnv != null)
- map.putAll(fCachedSerialEnv);
- if (fDeletedVariables != null) {
- for (String rem : fDeletedVariables.keySet())
- map.remove(rem);
- fDeletedVariables.clear();
- }
- if (fVariables != null)
- map.putAll(fVariables);
-
element.setAttribute(ATTRIBUTE_APPEND, Boolean.valueOf(fAppend).toString());
element.setAttribute(ATTRIBUTE_APPEND_CONTRIBUTED, Boolean.valueOf(fAppendContributedEnv).toString());
- if(!map.isEmpty()){
- Iterator iter = map.values().iterator();
+ if(fVariables != null){
+ Iterator iter = fVariables.values().iterator();
while(iter.hasNext()){
StorableEnvVar var = (StorableEnvVar)iter.next();
ICStorageElement varEl = element.createChild(StorableEnvVar.VARIABLE_ELEMENT_NAME);
@@ -217,14 +149,10 @@ public class StorableEnvironment /*implements Cloneable*/{
* @param map
* @param var
*/
- private void addVariable(Map map, IEnvironmentVariable var){
- String name = var.getName();
- if(name == null)
+ void addVariable(Map map, IEnvironmentVariable var){
+ String name = getNameForMap(var.getName());
+ if (name == null)
return;
- IEnvironmentVariableManager provider = EnvironmentVariableManager.getDefault();
- if(!provider.isVariableCaseSensitive())
- name = name.toUpperCase();
-
map.put(name,var);
}
@@ -239,9 +167,6 @@ public class StorableEnvironment /*implements Cloneable*/{
if(var == null){
var = new StorableEnvVar(name, value, op, delimiter);
addVariable(getMap(), var);
- // Variable added, ensure it's not in the removed set
- if (fDeletedVariables != null)
- fDeletedVariables.remove(EnvironmentVariableManager.getDefault().isVariableCaseSensitive() ? name : name.toUpperCase());
fIsDirty = true;
fIsChanged = true;
}
@@ -327,23 +252,10 @@ public class StorableEnvironment /*implements Cloneable*/{
* @return the environment variable with the given name, or null
*/
public IEnvironmentVariable getVariable(String name){
- if(name == null || "".equals(name = name.trim())) //$NON-NLS-1$
+ name = getNameForMap(name);
+ if (name == null)
return null;
- IEnvironmentVariableManager provider = EnvironmentVariableManager.getDefault();
- if(!provider.isVariableCaseSensitive())
- name = name.toUpperCase();
-
- IEnvironmentVariable var = getMap().get(name);
- if (var != null)
- return var;
-
- if (fDeletedVariables != null && fDeletedVariables.containsKey(name))
- return null;
-
- checkBackingSerializeInfo();
- if (fCachedSerialEnv != null)
- return fCachedSerialEnv.get(name);
- return null;
+ return getMap().get(name);
}
/**
@@ -383,33 +295,44 @@ public class StorableEnvironment /*implements Cloneable*/{
vars[i].getDelimiter());
}
- public IEnvironmentVariable[] getVariables(){
- checkBackingSerializeInfo();
- // Get all the environment from the backing store first
+ /**
+ * @return cloned map of all variables set on this storable environment runtime variables + backing store vars
+ */
+ Map getAllVariablesMap() {
Map vars = new HashMap();
- if (fCachedSerialEnv != null)
- vars.putAll(fCachedSerialEnv);
- if (fDeletedVariables != null)
- for (String name : fDeletedVariables.keySet())
- vars.remove(name);
-
- // Now overwrite with the live variables set, and return
vars.putAll(getMap());
+ return vars;
+ }
+ public IEnvironmentVariable[] getVariables(){
+ Map vars = getAllVariablesMap();
return vars.values().toArray(new IEnvironmentVariable[vars.size()]);
}
+ /**
+ * Returns the unique canonical form of the variable name for storage in the Maps.
+ *
+ * The name will be trimmed, and, if the var manager isn't case sensitive, made upper case
+ *
+ * @param name
+ * @return canonical name, or null
+ */
+ String getNameForMap(String name) {
+ if (name == null || (name = name.trim()).length() == 0)
+ return null;
+ if (!EnvironmentVariableManager.getDefault().isVariableCaseSensitive())
+ return name.toUpperCase();
+ return name;
+ }
+
public IEnvironmentVariable deleteVariable(String name){
if(fIsReadOnly)
throw ExceptionFactory.createIsReadOnlyException();
- if(name == null || "".equals(name = name.trim())) //$NON-NLS-1$
+ name = getNameForMap(name);
+ if(name == null)
return null;
- IEnvironmentVariableManager provider = EnvironmentVariableManager.getDefault();
- if(!provider.isVariableCaseSensitive())
- name = name.toUpperCase();
IEnvironmentVariable var = getMap().remove(name);
- getDeletedMap().put(name, var);
if(var != null){
fIsDirty = true;
fIsChanged = true;
@@ -422,10 +345,9 @@ public class StorableEnvironment /*implements Cloneable*/{
if(fIsReadOnly)
throw ExceptionFactory.createIsReadOnlyException();
Map map = getMap();
- if(map.size() > 0){
+ if(map.size() > 0) {
fIsDirty = true;
fIsChanged = true;
- getDeletedMap().putAll(map);
map.clear();
return true;
}
@@ -449,7 +371,6 @@ public class StorableEnvironment /*implements Cloneable*/{
throw ExceptionFactory.createIsReadOnlyException();
fAppend = append;
- fAppendChanged = true;
fIsDirty = true;
}
@@ -465,7 +386,6 @@ public class StorableEnvironment /*implements Cloneable*/{
throw ExceptionFactory.createIsReadOnlyException();
fAppendContributedEnv = append;
- fAppendContributedChanged = true;
fIsDirty = true;
}
@@ -475,13 +395,4 @@ public class StorableEnvironment /*implements Cloneable*/{
fAppendContributedEnv = DEFAULT_APPEND;
}
-/* public Object clone(){
- try {
- StorableEnvironment env = (StorableEnvironment)super.clone();
- env.fVariables = (HashMap)fVariables.clone();
- } catch (CloneNotSupportedException e) {
- }
- return null;
- }
-*/
}
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/envvar/StorableEnvironmentLoader.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/envvar/StorableEnvironmentLoader.java
index 3c3b8724b9b..16a4e86738f 100644
--- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/envvar/StorableEnvironmentLoader.java
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/envvar/StorableEnvironmentLoader.java
@@ -33,6 +33,7 @@ import org.eclipse.cdt.internal.core.settings.model.xml.XmlStorageElement;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
import org.w3c.dom.Document;
@@ -45,7 +46,6 @@ import org.xml.sax.SAXException;
* storing and loading environment variable settings from eclipse properties
*
* @since 3.0
- *
*/
public abstract class StorableEnvironmentLoader {
@@ -56,17 +56,34 @@ public abstract class StorableEnvironmentLoader {
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface ISerializeInfo{
+
/**
+ * {@link IEclipsePreferences} root node in the Preference store
* @return the Preferences Node into which environment should be (de) serialized
*/
Preferences getNode();
/**
+ * Name in the preference store
* @return the key in the preference node to use for loading preferences
*/
String getPrefName();
}
+ /**
+ * Creates the StorableEnvironment clone for a new configuration, say,
+ * based on an existing configuration
+ *
+ * @param context the configuration / workspace context the configuration is to be cloned for
+ * @param base the base environment to copy
+ * @return a StorableEnvironment clone of the configuration's environment
+ * @since 5.2
+ */
+ public StorableEnvironment cloneEnvironmentWithContext(Object context, StorableEnvironment base, boolean isReadOnly) {
+ PrefsStorableEnvironment env = new PrefsStorableEnvironment(base, getSerializeInfo(context), isReadOnly);
+ return env;
+ }
+
/**
* this method should return the ISerializeInfo representing the information
* of where the variable should be stored and loaded
@@ -85,12 +102,12 @@ public abstract class StorableEnvironmentLoader {
* @param readOnly
* @return StorableEnvironment
*/
- protected StorableEnvironment loadEnvironment(Object context, boolean readOnly){
+ protected StorableEnvironment loadEnvironment(Object context, boolean readOnly) {
ISerializeInfo serializeInfo = getSerializeInfo(context);
if(serializeInfo == null)
return null;
- return new StorableEnvironment(serializeInfo, readOnly);
+ return new PrefsStorableEnvironment(serializeInfo, readOnly);
}
/*
@@ -103,13 +120,18 @@ public abstract class StorableEnvironmentLoader {
ISerializeInfo serializeInfo = getSerializeInfo(context);
if(serializeInfo == null)
return;
-
- ByteArrayOutputStream stream = storeEnvironmentToStream(env);
- if(stream == null)
- return;
- storeOutputStream(stream,serializeInfo.getNode(), serializeInfo.getPrefName(), flush);
-
- env.setDirty(false);
+
+ if (env instanceof PrefsStorableEnvironment) {
+ ((PrefsStorableEnvironment)env).serialize();
+ } else {
+ // Backwards compatibility
+ ByteArrayOutputStream stream = storeEnvironmentToStream(env);
+ if(stream == null)
+ return;
+ storeOutputStream(stream,serializeInfo.getNode(), serializeInfo.getPrefName(), flush);
+
+ env.setDirty(false);
+ }
}
/**
@@ -189,6 +211,7 @@ public abstract class StorableEnvironmentLoader {
}
/**
+ * Preferences can be encoded as a single long ICStorageElement String
* @return String value stored in the node or null if no such value exists.
*/
static String loadPreferenceNode(ISerializeInfo serializeInfo) {