blob: 56d000733b771ce02d7d5f30b87bb7ce2d2b45a5 [file] [log] [blame]
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<title>User Settings: FAQ</title>
<link rel="stylesheet" href="http://dev.eclipse.org/default_style.css" type="text/css">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<table BORDER=0 CELLSPACING=5 CELLPADDING=2 WIDTH="100%" >
<tr>
<td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica" color="#FFFFFF">User Settings: FAQ</font></b></td>
</tr>
<tr>
<td align="left" colspan="2">
<font size=-1><i>last updated: January 19, 2005</i></font>
</td>
</tr>
<tr>
<td align="left" colspan="2">
General:
<ol>
<li><a href="#whatIs">What is a scope?</a></li>
<li><a href="#platformScopes">What scopes are contributed by the Platform?</a></li>
<li><a href="#tree">This is confusing, how can I picture this in my mind?</a></li>
<li><a href="#basicGet">How do I know if auto-build is turned on? (How do I get a preference value?)</a></li>
<li><a href="#basicSet">How can I set the auto-build preference? (How do I set a preference value?)</a></li>
<li><a href="#backwardsCompatibilityScopes">Why doesn't the backwards compatibility layer check all the scopes for a value?</a></li>
<li><a href="#flush">When are my preference changes saved to disk?</a></li>
<li><a href="#customization">How does the plug-in customization story work?</a></li>
</ol>
Conversion:
<ol>
<li><a href="#convert">What should I do to convert my code to the new mechanism?</a></li>
<li><a href="#convertProject">How do I convert my project property page to use project preferences?</a></li>
<li><a href="#imemento">How do I convert my IMemento values?</a></li>
</ol>
Listeners:
<ol>
<li>How do I know when changes have happened to my preference?</li>
<li>But I want to listen to changes in ALL scopes, not just one.</li>
</ol>
Nodes:
<ol>
<li><a href="#nodes">Why should I use nodes?</a></li>
<li><a href="#illegalStateException">Why am I getting an IllegalStateException when calling APIs?</a></li>
</ol>
Extensions:
<ol>
<li><a href="#extension">How do I extend the preferences and add my own scope?</a></li>
</ol>
</td>
</tr>
<tr>
<td ALIGN=LEFT VALIGN=TOP COLSPAN="2"><hr></td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
<td WIDTH="98%"><b><a name="whatIs"></a>What is a
scope?</b><p></p>
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
(<code>Plugin.getPluginPreferences()</code>) 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.
<p>
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.
</p>
</td>
</tr>
<tr>
<td ALIGN=LEFT VALIGN=TOP COLSPAN="2"><hr></td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
<td WIDTH="98%"><b><a name="platformScopes"></a>What
scopes are contributed by the Platform?</b><p></p>
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 <code>org.eclipse.core.runtime.Platform#getInstanceLocation()</code>.
Preferences stored in this scope will not be available to other running instances
of Eclipse.
<p></p>
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
<code>org.eclipse.core.runtime.Platform#getConfigurationLocation()</code>.
<p></p>
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.
<p></p>
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.
</td>
</tr>
<tr>
<td ALIGN=LEFT VALIGN=TOP COLSPAN="2"><hr></td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
<td WIDTH="98%"><b><a name="tree"></a>This
is confusing, how can I picture this in my mind?</b>
<p></p>
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.
<p>
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.
</p><p>
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:<br>
&nbsp;&nbsp;&nbsp;&nbsp;<code>/instance/org.eclipse.core.resources/description.autobuild</code>
</p><p>
The project scope (as defined by the resources plug-in) defines its path structure to be
<code>/project/&lt;projectName&gt;/&lt;qualifier&gt;/key</code> and therefore the full path for
the resources' plug-in auto-build preference for the project "MyProject" would be:<br>
&nbsp;&nbsp;&nbsp;&nbsp;<code>/project/MyProject/org.eclipse.core.resources/description.autobuild</code>
</p>
</td>
</tr>
<tr>
<td ALIGN=LEFT VALIGN=TOP COLSPAN="2"><hr></td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
<td WIDTH="98%"><b><a name="basicGet"></a>How do I know if
auto-build is turned on? (How do I get a preference value?)</b>
<p></p>
</td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%">1.</td>
<td WIDTH="98%">
Through the backwards compatibility layer.
<p>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.</p>
<p>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.</p>
<p> <code>
String key = ResourcesPlugin.PREF_AUTO_BUILDING;<br>
return ResourcesPlugin.getPluginPreferences().getBoolean(key);<br>
</code> </p>
</td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%">2.</td>
<td WIDTH="98%">
Via navigation from the root node.
<p>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.</p>
<p> <code>
String qualifier = ResourcesPlugin.getDescriptor().getUniqueIdentifier();<br>
String key = ResourcesPlugin.PREF_AUTO_BUILDING;<br>
boolean defaultValue = false;<br>
Preferences node = Platform.getPreferencesService().getRootNode().node(InstanceScope.SCOPE).node(qualifier);<br>
return node.getBoolean(key, defaultValue);</code> </p>
</td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%">3.</td>
<td WIDTH="98%">
Through the context objects.
<p>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.</p>
<p> <code>
String qualifier = ResourcesPlugin.getDescriptor().getUniqueIdentifier();<br>
String key = ResourcesPlugin.PREF_AUTO_BUILDING;<br>
boolean defaultValue = false;<br>
Preferences node = new InstanceScope().getNode(qualifier);<br>
if (node != null)<br>
&nbsp;&nbsp;return node.getBoolean(key, defaultValue);</code> </p>
</td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%">4a.</td>
<td WIDTH="98%">
Search through the preferences service. (manual lookup order)
<p>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.</p>
<p> <code>
IPreferencesService service = Platform.getPreferencesService();<br>
String qualifier = ResourcesPlugin.getDescriptor().getUniqueIdentifier();<br>
String key = ResourcesPlugin.PREF_AUTO_BUILDING;<br>
String defaultValue = "false";<br>
Preferences root = service.getRootNode();<br>
Preferences instanceNode = root.node(InstanceScope.SCOPE).node(qualifier);<br>
Preferences userNode = root.node(UserScope.SCOPE).node(qualifier);<br>
Preferences[] nodes = new Preferences[] {instanceNode, userNode};<br>
return service.get(key, defaultValue, nodes);<br>
</code> </p>
</td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%">4b.</td>
<td WIDTH="98%">
Search through the preferences service. (default lookup order)
<p>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.</p>
<p>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. </p>
<p>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. <em>Note that these are not
necessary for the INSTANCE, CONFIGURATION, USER, and DEFAULT scopes.</em>
</p>
<p>
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.
</p><p>
<code>
IPreferencesService service = Platform.getPreferencesService();<br>
String qualifier = ResourcesPlugin.getDescriptor().getUniqueIdentifier();<br>
String key = ResourcesPlugin.PREF_AUTO_BUILDING;<br>
boolean defaultValue = false;<br>
String[] lookupOrder = new String[] {ProjectScope.SCOPE, InstanceScope.SCOPE};<br>
service.setDefaultLookupOrder(qualifier, key, lookupOrder);<br>
IScopeContext contexts = new IScopeContext[] {new ProjectScope("MyProject")};<br>
return service.getBoolean(qualifier, key, defaultValue, contexts);</code> </p>
</td>
</tr>
<tr>
<td ALIGN=LEFT VALIGN=TOP COLSPAN="2"><hr></td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
<td WIDTH="98%"><b><a name="basicSet"></a>How can I set the
auto-build preference? (How do I set a preference value?)</b></td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%">1.</td>
<td WIDTH="98%">
Through the backwards compatibility layer.
<p>Again, all the old APIs exist and are fully functional.</p>
<p> <code>
String key = ResourcesPlugin.PREF_AUTO_BUILDING;<br>
boolean value = true;<br>
ResourcesPlugin.getPluginPreferences().setValue(key, value);<br>
</code> </p>
</td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%">2.</td>
<td WIDTH="98%">
Via navigation from the root node.
<p>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.</p>
<p> <code>
String qualifier = ResourcesPlugin.getDescriptor().getUniqueIdentifier();<br>
String key = ResourcesPlugin.PREF_AUTO_BUILDING;<br>
boolean value = true;<br>
IEclipsePreferences root = Platform.getPreferencesService().getRootNode();<br>
root.node(InstanceScope.SCOPE).node(qualifier).putBoolean(key, value);<br>
</code> </p>
</td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%">3.</td>
<td WIDTH="98%">
Through the scope context.
<p>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".</p>
<p> <code>
String qualifier = ResourcesPlugin.getDescriptor().getUniqueIdentifier();<br>
String key = ResourcesPlugin.PREF_AUTO_BUILDING;<br>
boolean value = true;<br>
IScopeContext context = new ProjectScope(MyProject);<br>
IEclipsePreferences node = context.getNode(qualifier);<br>
if (node != null)<br>
&nbsp;&nbsp;&nbsp;&nbsp;node.putBoolean(key, value);</code> </p>
</td>
</tr>
<tr>
<td ALIGN=LEFT VALIGN=TOP COLSPAN="2"><hr></td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
<td WIDTH="98%"><b><a name="convert"></a>What
should I do to convert my code to the new mechanism?</b>
<p></p>
Getting a value using the old code only checks the INSTANCE and DEFAULT scopes:<br>
<code>
&nbsp;&nbsp;ResourcesPlugin.getPluginPreferences().getBoolean(key);</br>
</code>
</p><p>
Getting a value using the new code looks in all scopes as defined by the look-up order
set in the preferences service:<br>
<code>
&nbsp;&nbsp;Platform.getPreferencesService().getBoolean(ResourcesPlugin.PI_RESOURCES, key, defaultValue);<br>
</code>
</p><p>
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:<br>
<code>
&nbsp;&nbsp;ResourcesPlugin.getPluginPreferences().setValue(key, value);<br>
</code>
</p><p>
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:<br>
<code>
&nbsp;&nbsp;Preferences node = new InstanceScope().getNode(ResourcesPlugin.PI_RESOURCES);<br>
&nbsp;&nbsp;if (node != null)<br>
&nbsp;&nbsp;&nbsp;&nbsp;node.put(key, value);<br>
</code>
</p>
</td>
</tr>
<tr>
<td ALIGN=LEFT VALIGN=TOP COLSPAN="2"><hr></td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
<td WIDTH="98%"><b><a name="convertProject"></a>How
do I convert my project property page to use project preferences?</b>
<p></p>
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:
<p>
<code>
// setup<br>
IScopeContext context = new ProjectScope(MyProject);<br>
IEclipsePreferences node = context.getNode("org.eclipse.jdt.core");<br>
int defaultValue = JavaCore.SEVERITY_IGNORE;<br>
String key = JavaCore.NON_NLS_SEVERITY;<br>
int value = defaultValue;<br>
</code><p></p>
<code>...</code><p></p>
<code>
// get the value<br>
if (node != null) <br>
&nbsp;&nbsp;value = node.getInt(key, defaultValue);<br>
if (value == defaultValue) {<br>
&nbsp;&nbsp;// value isn't set in the project scope.<br>
&nbsp;&nbsp;// value is "inherited" from another scope.<br>
} else {<br>
&nbsp;&nbsp;// we have a value set in the project scope<br>
}<br>
<p></p>
</code>
<code>...</code><p></p>
<code>
// set the value<br>
if (node != null) {<br>
&nbsp;&nbsp;if (value == defaultValue) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;// value is same as default so no need to store it<br>
&nbsp;&nbsp;&nbsp;&nbsp;node.remove(key);<br>
&nbsp;&nbsp;} else {<br>
&nbsp;&nbsp;&nbsp;&nbsp;// set a project-specific value<br>
&nbsp;&nbsp;&nbsp;&nbsp;node.put(key, value);<br>
}<br>
</code>
<p></p>
<code>...</code><p></p>
<code>
// save the changes<br>
if (node != null) {<br>
&nbsp;&nbsp;// save the project specific values<br>
&nbsp;&nbsp;node.flush();<br>
}<br>
</code>
</p>
</td>
</tr>
<tr>
<td ALIGN=LEFT VALIGN=TOP COLSPAN="2"><hr></td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
<td WIDTH="98%"><b><a name="imemento"></a>How do I convert my IMemento values?</b>
<p></p>
Its easy! IMementos are a method of storing hierarchial data and that's just what the node
hierarchy is.
<p>To set a complex IMemento preference value using Eclipse 2.1 preferences:
</p><p>
<code>
String key = "providers";<br>
XMLMemento root = XMLMemento.createWriteRoot(key);<br>
IMemento dev = root.createChild("dev.eclipse.org");<br>
dev.putString("connnectionType", "pserver");<br>
dev.putString("login", "anonymous");<br>
dev.putString("path", "/home/eclipse");<br>
IMemento example = root.createChild("cvs.example.com");<br>
example.putString("connnectionType", "pserver");<br>
example.putString("login", "anonymous");<br>
example.putString("path", "/home/cvs");<br>
Writer writer = new StringWriter();<br>
try {<br>
&nbsp;&nbsp;root.save(writer);<br>
} finally {<br>
&nbsp;&nbsp;writer.close();<br>
}<br>
MyPlugin.getDefault().getPluginPreferences().setValue(key, writer.toString());<br>
...<br>
MyPlugin.getDefault().savePluginPreferences();<br>
</code>
</p><p>
To set the same complex values using Eclipse 3.0 preferences:
</p><p>
<code>
// Note: can create other context here including Project<br>
IScopeContext context = new InstanceScope();<br>
Preferences root = context.getNode("org.eclipse.team");<br>
// Note: should not be null<br>
if (root != null) {<br>
&nbsp;&nbsp;Preferences dev = root.node("providers/dev.eclipse.org");<br>
&nbsp;&nbsp;dev.put("connectionType", "pserver");<br>
&nbsp;&nbsp;dev.put("login", "anonymous");<br>
&nbsp;&nbsp;dev.put("path", "/home/eclipse");<br>
&nbsp;&nbsp;Preferences example = root.node("providers/cvs.example.com");<br>
&nbsp;&nbsp;example.put("connectionType", "pserver");<br>
&nbsp;&nbsp;example.put("login", "anonymous");<br>
&nbsp;&nbsp;example.put("path", "/home/cvs");<br>
&nbsp;&nbsp;...<br>
&nbsp;&nbsp;root.flush();<br>
}<br>
</code>
</p><p>
To get a value using the Eclipse 2.1 preferences:
</p><p>
<code>
String xmlString = MyPlugin.getDefault().getPluginPreferences().getString("providers");<br>
Reader reader = new StringReader(xmlString);<br>
XMLMemento root = XMLMemento.createReadRoot(reader);<br>
IMemento dev = root.getChild("dev.eclipse.org");<br>
return dev.getString("connnectionType");<br>
</code>
</p><p>
To get the same value using Eclipse 3.0 preferences:
</p><p>
<code>
// Note: can create other context here including Project<br>
IScopeContext context = new InstanceScope();<br>
Preferences root = context.getNode("org.eclipse.team");<br>
// Note: should not be null<br>
if (root != null) {<br>
&nbsp;&nbsp;Preferences node = root.node("providers/dev.eclipse.org");<br>
&nbsp;&nbsp;return node.get("connectionType", null);<br>
}<br>
</code>
</p>
</td>
</tr>
<tr>
<td ALIGN=LEFT VALIGN=TOP COLSPAN="2"><hr></td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
<td WIDTH="98%"><b><a name="backwardsCompatibilityScopes"></a>Why
doesn't the backwards compatibility layer check all the scopes for a value?</b>
<p></p>
The backwards compatibility layer only checks for preference values in the INSTANCE and
DEFAULT scopes for two main reasons.
<p>
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.
</p><p>
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.
</p><p>
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.
</p>
</td>
</tr>
<tr>
<td ALIGN=LEFT VALIGN=TOP COLSPAN="2"><hr></td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
<td WIDTH="98%"><b><a name="flush"></a>When are my preference changes saved to disk?</b>
<p></p>
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 (<code>Plugin.savePluginPreferences()</code>) which clients
were encouraged to call on plug-in shutdown and when they changed their preference values
(like in a preference page).
<p>
It is important to note that this old API now corresponds to saving the preferences for
that plug-in in the INSTANCE scope only.
</p><p>
Now, it is recommended that people save their preference changes to disk by calling the
<code>Preferences.flush()</code> method. For instance, preference page owners would
call this after setting all the preference values when the user hits "OK".
</p>
</td>
</tr>
<tr>
<td ALIGN=LEFT VALIGN=TOP COLSPAN="2"><hr></td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
<td WIDTH="98%"><b><a name="nodes"></a>Why should I use nodes?</b>
<p></p>
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.
</p><p>
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.
</p><p>
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:
<p>
<code>&nbsp;&nbsp;/instance/org.eclipse.team/providers/example.com/path=/home/eclipse</code><br>
<code>&nbsp;&nbsp;/instance/org.eclipse.team/providers/example.com/login=anonymous</code><br>
<code>&nbsp;&nbsp;/instance/org.eclipse.team/providers/example.com/connectionType=pserver</code><br>
<code>&nbsp;&nbsp;/instance/org.eclipse.team/providers/dev.eclipse.org/path=/home/eclipse</code><br>
<code>&nbsp;&nbsp;/instance/org.eclipse.team/providers/dev.eclipse.org/login=anonymous</code><br>
<code>&nbsp;&nbsp;/instance/org.eclipse.team/providers/dev.eclipse.org/connectionType=pserver</code><br>
</p>
In this example the list of providers could be retrieved as children of the
<code>/instance/org.eclipse.team/providers</code> node and then each individual provider's
login information as preferences in children nodes.
</p>
</td>
</tr>
<tr>
<td ALIGN=LEFT VALIGN=TOP COLSPAN="2"><hr></td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
<td WIDTH="98%"><b><a name="illegalStateException"></a>Why am I getting an IllegalStateException when calling APIs?</b>
<p></p>
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
<code>IllegalStateException</code> when calling APIs on that node. The only valid methods
to call on a removed node are: <code>name(), absolutePath()</code> and <code>nodeExists()</code>.
<p>
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.
</p><p>
<code>
if (!node.nodeExists(""))<br>
&nbsp;&nbsp;&nbsp;&nbsp;node = service.getRootNode().node(node.absolutePath());<br>
</code>
</p>
</td>
</tr>
<tr>
<td ALIGN=LEFT VALIGN=TOP COLSPAN="2"><hr></td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
<td WIDTH="98%"><p><b><a name="customization"></a>How does the plug-in customization
story work?</b> </p>
<p>Check out the separate <a href="plugin_customization.html">document</a>
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.</p>
<p></p>
</td>
</tr>
<tr>
<td ALIGN=LEFT VALIGN=TOP COLSPAN="2"><hr></td>
</tr>
<tr>
<td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
<td WIDTH="98%"><p><b><a name="extension">How do I extend the preferences and add my own scope?</a></b> </p>
<p>1. Extend the org.eclipse.core.runtime.preferences extension point.
<code><pre>
&lt;extension point=&quot;org.eclipse.core.runtime.preferences&quot;&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;scope name=&quot;myScope&quot; class=&quot;com.example.preferences.MyScope&quot;/&gt;
&lt;/extension&gt;
</pre></code>
</p>
<p>2. Have your class implement IScope and IEclipsePreferences.
<code><pre>
public class MyScope implements IScope, IEclipsePreferences {
&nbsp;&nbsp;&nbsp;&nbsp;...
}
</pre></code>
</p>
<p>Here is an <a href="example_scope.zip">example</a> plug-in which creates a new scope.</p>
<p></p>
</td>
</tr>
</table>