User Settings: FAQ | |
last updated: January 19, 2005 | |
General:
|
|
What is a
scope?
In Eclipse 2.1 there was only one place to store preferences via the Runtime APIs.
Users would ask a particular plug-in for its preferences
(Plugin.getPluginPreferences() ) and the preferences would be store per plug-in,
per workspace. This allowed some conveniences but it was obvious that
the new preference mechanism needed to be extensible and allow settings to be
stored in different places...users want to share their preferences between
workspaces, configurations, and even share them with other users. This is the
main reason that we created "scopes" for the preference store.
A scope basically refers to where the preferences are stored. Different preference scopes can be contributed by plug-ins so the number of scopes available to clients is not limited to those defined by the platform. |
|
What
scopes are contributed by the Platform?
INSTANCE -
The instance scope can also be thought of as "workspace". That is, the
preferences which are stored in this scope are stored per workspace, or
per running instance of Eclipse. This scope corresponds to the default
location of preferences in Eclipse 2.1. The instance area is derived from
the location returned by org.eclipse.core.runtime.Platform#getInstanceLocation() .
Preferences stored in this scope will not be available to other running instances
of Eclipse.
CONFIGURATION - The configuration scope is used to store preferences on a per
configuration level. Being able store preferences per configuration means
that all workspaces share the same preferences. For instance, if you are an
Eclipse developer and you have a single Eclipse install but you have multiple
workspaces for different projects/branches that you are working on, the
preferences stored in the configuration scope will be shared between these
workspaces. The configuration area is derived from the location returned by
org.eclipse.core.runtime.Platform#getConfigurationLocation() .
DEFAULT - The default preference scope was initially created to provide a backwards
compatibility story for the plug-in customization code in Eclipse 2.1. Preferences
stored in the default scope are not persisted to disk and are a part of the plug-in
customization story.
PROJECT - There was a request for per project preferences so the project scope
handles this. Preferences which are stored in this scope are shared stored in the
project content area and are therefore automatically shared with the repository.
This enables items like java compiler settings to be shared between team members
working on the same project.
|
|
This
is confusing, how can I picture this in my mind?
The preferences can be thought of as a tree with each node
having a name and children. The "path" of a node is the names of it and
all its ancestors separated by a path separator.
Start at the root node. The root node's name is empty and has a path of "/". The root node's children are the names of the scopes which are defined. (e.g. instance, configuration, user, default, project, etc) Therefore their paths are: /instance, /configuration, /user, /default, and /project.
The path structure under the scope name is defined by the scope itself. The scopes
contributed by the Platform Runtime (instance, configuration, user, default) define
the next segement to be a qualifier. (like a plug-in or bundle id)
An example of the full path for the autobuild preference for the resources plug-in
in the instance scope would be:
The project scope (as defined by the resources plug-in) defines its path structure to be
|
|
How do I know if auto-build is turned on? (How do I get a preference value?) | |
1. |
Through the backwards compatibility layer.
All the plug-in preference APIs which existed in Eclipse 2.1 still exist and are fully supported through a backwards compatibility layer. All the client has to do is ask the org.eclipse.core.resources plug-in for its preferences. The downside to this is that not all of the preference scopes are checked for a value. In this case first the INSTANCE scope is checked, and then the DEFAULT scope. If a value doesn't exist in either scope, then the default-default value for that type is returned. |
2. |
Via navigation from the root node.
The new Eclipse preference mechanism is structured in a hierarchial means and therefore the user is able to retrieve the root of the hierarchy and navigate to the particular preference node that they desire. This is, of course, assuming the know the path structure of the node they are trying to retrieve. The example below retrives the value from the INSTANCE scope. |
3. |
Through the context objects.
If the user knows which preference scope their preference is in but they don't know the hierarchy structure of the scope (or don't want to have to deal with it), then they are able to use the scope context API to retrieve the correct node for their preferences. |
4a. |
Search through the preferences service. (manual lookup order)
Having preferences stored in a single location, although useful, is uninteresting compared to being able to store preferences in multiple scopes. If a user has a collection of multiple preference nodes that they would like to check for a particular preference value, then they are able to use the API on IPreferencesService to check the multiple nodes and return the first found value, or the specified default if it is not found. The example below first checks the INSTANCE scope and then checks the USER scope. |
4b. |
Search through the preferences service. (default lookup order)
Navigation from the root node to other nodes in the preference hierarchy can be cumbersome so we expect most preference users to take advantage of this second API. It is a convenience method to the above method. First they (in most cases the plug-in developer who is contributing the preference) set the scope lookup order (if none is specified then the default-default {project, instance, configuration, user, default} is used. Some scopes require extra context to determine which preference nodes are the right ones to look at. So if necessary, callers are able to create IScopeContext instances to aid in lookup. Note that these are not necessary for the INSTANCE, CONFIGURATION, USER, and DEFAULT scopes. In the example below, we first look to see if the preference has been set on the project preferences for "MyProject" and then we check the INSTANCE preferences.
|
How can I set the auto-build preference? (How do I set a preference value?) | |
1. |
Through the backwards compatibility layer.
Again, all the old APIs exist and are fully functional. |
2. |
Via navigation from the root node.
If the user knows which scope they wish to store the preference in and knows the path structure for the hierarchy of that scope, then they are able to navigate directly to that preference node and set their preference value. In the example below we are setting the auto-build setting in the INSTANCE scope. |
3. |
Through the scope context.
If the user knows which scope they wish to set the preference value in but doesn't know the path structure for that scope, (or prefers not to navigate it themselves) then they can use the convenience methods in IScopeContext to determine the correct preference node. This is the method in which we envision most clients setting preference values. In the example below we are storing the preference in the project preferences for "MyProject". |
What
should I do to convert my code to the new mechanism?
Getting a value using the old code only checks the INSTANCE and DEFAULT scopes:
ResourcesPlugin.getPluginPreferences().getBoolean(key);
Getting a value using the new code looks in all scopes as defined by the look-up order
set in the preferences service:
Setting a value using the old code either puts the value in the INSTANCE scope or clears
it if it is the same as the value in the DEFAULT scope:
Setting a value using the new code is a bit more complicated. Clients must know which
scope they wish to store their value in. For instance: |
|
How
do I convert my project property page to use project preferences?
Rather than use the generalized look-up mechanism to find out your project-specific
values, I would create a project context and do the lookup from there. This ensures
that you either get the value that is defined in the project scope or nothing. (the
default value that you specify) For example:
...
// get the value
...
// set the value
...
// save the changes
|
|
How do I convert my IMemento values?
Its easy! IMementos are a method of storing hierarchial data and that's just what the node
hierarchy is.
To set a complex IMemento preference value using Eclipse 2.1 preferences:
To set the same complex values using Eclipse 3.0 preferences:
To get a value using the Eclipse 2.1 preferences:
To get the same value using Eclipse 3.0 preferences:
|
|
Why
doesn't the backwards compatibility layer check all the scopes for a value?
The backwards compatibility layer only checks for preference values in the INSTANCE and
DEFAULT scopes for two main reasons.
Firstly. we wanted to maintain true backwards compatibility. If the "get" methods checked for preference values in scopes other than INSTANCE and DEFAULT, then the behaviour would not be the same as was in Eclipse 2.1. That is, if there was a value set for another scope it would be returned. The second reason is that it confuses the current UI story. People have created many preference pages which show the current preference values. This maps on to the preferences stored in the INSTANCE scope. If we changed the backwards compatibility story to look in the other scopes for preference values, then the values presented to the user would be mixed...some would be from the INSTANCE scope, some from the USER scope, etc etc. The short story is that we have to try to develop a UI which presents preferences and their scopes to the user in a simple and managable way. |
|
When are my preference changes saved to disk?
The short answer is "whenever you change them you need to save them". In Eclipse 2.1 there
was API to save plug-in preferences (Plugin.savePluginPreferences() ) which clients
were encouraged to call on plug-in shutdown and when they changed their preference values
(like in a preference page).
It is important to note that this old API now corresponds to saving the preferences for that plug-in in the INSTANCE scope only.
Now, it is recommended that people save their preference changes to disk by calling the
|
|
Why should I use nodes?
For most plug-ins, simple key/value pairs are well suited for their preference
values and they will never have to take advantage of the node hierarchy other than
the basic traversal. The interesting use case is for those clients who previously used
mark-up (like XML)
to encode their preference values. XML and its elements are essentially containers...a
way to group together similar values in a hierarchical manner. The use of nodes can
simplify this for clients.
Each node in the hierarchy has a name and its path is represented by its name and all its parents' names separated by the path separator. This allows preference keys at arbitrary depths in the tree so a node's children nodes could be used in a "contains" relationship. Think, for instance, of the list of Team provider connections in Eclipse. Rather than having a single preference key and the value being wrapped in a wad of XML, it could be split across multiple nodes and be more accessible. For instance consider the following:
/instance/org.eclipse.team/providers node and then each individual provider's
login information as preferences in children nodes.
|
|
Why am I getting an IllegalStateException when calling APIs?
Since the Preferences APIs include the ability to add nodes to the hierarchy, they
also include methods to remove nodes from the hierarchy. If a node has been removed and
a client still has a reference to it, the client will get an
IllegalStateException when calling APIs on that node. The only valid methods
to call on a removed node are: name(), absolutePath() and nodeExists() .
If clients aren't sure whether or not their node may have been removed since the last time they accessed it, they are encouraged to re-retrieve the node from the hierarchy.
|
|
How does the plug-in customization story work? Check out the separate document on plug-in customization. It explains the order that preference defaults are applied and compares this to the way it worked in Eclipse 2.1. |
|
How do I extend the preferences and add my own scope? 1. Extend the org.eclipse.core.runtime.preferences extension point.
2. Have your class implement IScope and IEclipsePreferences.
Here is an example plug-in which creates a new scope. |