Eclipse Project Natures This article describes how project natures can be implemented and how to use a custom project nature.
1. Project Natures in Eclipse
Project Natures are used in the Eclipse IDE in order to configure projects in the workspace.
One project may have several project natures.
The most popular project nature is org.eclipse.jdt.core.javanature
, which is used to indicate that a project is a Java project.
Some examples for project natures are:
Project Nature’s ID | Description |
---|---|
org.eclipse.jdt.core.javanature |
Java Projects |
org.eclipse.buildship.core.gradleprojectnature |
Gradle Projects |
org.eclipse.m2e.core.maven2Nature |
Maven Projects |
org.eclipse.pde.core.org.eclipse.pde.PluginNature |
Eclipse Plugin Projects |
org.eclipse.pde.core.org.eclipse.pde.FeatureNature |
Eclipse Feature Projects |
org.eclipse.pde.core.org.eclipse.pde.UpdateSiteNature |
Eclipse Updatesite Projects |
If your Eclipse installation offers some additional project natures, which can be applied to a project, you can usually convert the project via the context menu.
The Configure menu is only visible, if there are project natures, which can be applied. Otherwise it is not shown at all. |
2. Define a project nature
Project natures are defined with the org.eclipse.core.resources.natures
extension point.
A bare project nature only needs a name, id and a class reference, to a class that implements IProjectNature
.
<extension
id="examplenature"
name="Example nature"
point="org.eclipse.core.resources.natures">
<runtime>
<run
class="com.example.product.ExampleProjectNature">
</run>
</runtime>
</extension>
The implementation of the referenced ExampleProjectNature
can look like
this:
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectNature;
import org.eclipse.core.runtime.CoreException;
public class ExampleProjectNature implements IProjectNature {
// ID of the natures, which consists of Bundle-SymbolicName + ID
public static final String NATURE_ID = "com.example.project.examplenature";
private IProject project;
@Override
public void configure() throws CoreException {
// only called once the nature has been set
// configure the project...
}
@Override
public void deconfigure() throws CoreException {
// only called once the nature has been set
// reset the project configuration...
}
@Override
public IProject getProject() {
return project;
}
@Override
public void setProject(IProject project) {
this.project = project;
}
}
The acutal id of a project nature consists of the Bundle-SymbolicName + id, which is defined for the extension point.
See NATURE_ID in ExampleProjectNature .
|
2.1. Require a certain project nature as precondition
In some cases applying a project nature only makes sense, if the project already has a certain project nature. For example if your custom project nature should only be applicable on a Java project.
<extension
id="examplenature"
name="Example nature"
point="org.eclipse.core.resources.natures">
<runtime>
<run
class="com.example.product.ExampleProjectNature">
</run>
</runtime>
<requires-nature
id="org.eclipse.jdt.core.javanature">
</requires-nature>
</extension>
2.2. Get and set a Project Natures
Every IProject
has an IProjectDescription
, which contains all natureIds.
From the IProjectDescription
a string array of all nature ids can be obtained.
If you want to add a new project nature to a project, you need to add its id to the existing array.
After that the new array (that contains the new project natures id at the end) needs to be validated.
If the validation is successful the newNatures
array can be set on the IProjectDescription
object of the project.
IProject project = // get project...
IProjectDescription description = project.getDescription();
String[] natures = description.getNatureIds();
String[] newNatures = new String[natures.length + 1];
System.arraycopy(natures, 0, newNatures, 0, natures.length);
newNatures[natures.length] = ExampleProjectNature.NATURE_ID;
// validate the natures
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IStatus status = workspace.validateNatureSet(newNatures);
// only apply new nature, if the status is ok
if (status.getCode() == IStatus.OK) {
description.setNatureIds(newNatures);
project.setDescription(description, null);
}
2.3. Using expressions to check for project natures
The existence of a certain project nature can also be checked with a core expression,
which can be defined within the org.eclipse.core.expressions.definitions
extension point.
<extension
point="org.eclipse.core.expressions.definitions">
<definition
id="com.example.project.hasNature">
<adapt
type="org.eclipse.core.resources.IProject">
<test
property="org.eclipse.core.resources.projectNature"
value="com.example.project.examplenature">
</test>
</adapt>
</definition>
</extension>
Here you can see that a PropertyTester
for project natures is already available and you can use the
org.eclipse.core.resources.projectNature property to check for a certain project nature.
3. Exercise: Apply a project nature to a project
This exercise describes how to add a Convert to example project menu item to the Configure menu of a project.
3.1. Define an example project nature
Create a plugin project and add the following dependencies to it:
-
org.eclipse.core.runtime
-
org.eclipse.core.resources
-
org.eclipse.ui.ide
-
org.eclipse.ui
In the plugin.xml you need to add the org.eclipse.core.resources.natures
extension point.
In the ExampleProjectNature (run) we reference the ExampleProjectNature
class:
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectNature;
import org.eclipse.core.runtime.CoreException;
public class ExampleProjectNature implements IProjectNature {
// ID of the natures, which consists of Bundle-SymbolicName + ID
public static final String NATURE_ID = "com.example.project.examplenature";
private IProject project;
@Override
public void configure() throws CoreException {
// only called once the nature has been set
// configure the project...
}
@Override
public void deconfigure() throws CoreException {
// only called once the nature has been set
// reset the project configuration...
}
@Override
public IProject getProject() {
return project;
}
@Override
public void setProject(IProject project) {
this.project = project;
}
}
3.2. Add a convert command
Now use the org.eclipse.ui.commands
extension point and add a command with com.example.product.examplenature.command
as id and Convert to Example Project
as name.
3.3. Add a convert handler
Add the org.eclipse.ui.handlers
extension point and add a handler for the com.example.product.examplenature.command
command.
The class for the handler is ExampleProjectNatureHandler
and looks like this:
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdapterManager;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.handlers.HandlerUtil;
import com.example.product.ExampleProductNature;
public class ExampleProjectNatureHandler extends AbstractHandler {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
ISelection currentSelection = HandlerUtil.getCurrentSelection(event);
if (currentSelection instanceof IStructuredSelection) {
Object firstElement = ((IStructuredSelection) currentSelection).getFirstElement();
// Get an IResource as an adapter from the current selection
IAdapterManager adapterManager = Platform.getAdapterManager();
IResource resourceAdapter = adapterManager.getAdapter(firstElement, IResource.class);
if (resourceAdapter != null) {
IResource resource = resourceAdapter;
IProject project = resource.getProject();
try {
IProjectDescription description = project.getDescription();
String[] natures = description.getNatureIds();
String[] newNatures = new String[natures.length + 1];
System.arraycopy(natures, 0, newNatures, 0, natures.length);
// add our new "com.example.project.examplenature" id
newNatures[natures.length] = ExampleProjectNature.NATURE_ID;
// validate the natures
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IStatus status = workspace.validateNatureSet(newNatures);
// only apply new nature, if the status is ok
if (status.getCode() == IStatus.OK) {
description.setNatureIds(newNatures);
project.setDescription(description, null);
}
return status;
} catch (CoreException e) {
throw new ExecutionException(e.getMessage(), e);
}
}
}
return Status.OK_STATUS;
}
}
3.4. Add the menu contribution for the conversion
The id of the Configure menu in a projects context menu is org.eclipse.ui.projectConfigure
and therefore the locationURI of the menuContribution must be popup:org.eclipse.ui.projectConfigure
.
In this menuContribution we then reference the defined command.
3.5. Optional - Add a core expression
As already mentioned the Configure menu is only visible, if it has elements in it.
Therefore we should only apply the menuContribution to it, if the nature has not already been set.
This can be done using a core expression with the org.eclipse.core.expressions.definitions
extension point.
The id of the definition should be com.example.project.hasNature
, which adapts org.eclipse.core.resources.IProject
as type and reuses a predefined PropertyTester
, which is able to check for certain project natures.
The property of the PropertyTester
is org.eclipse.core.resources.projectNature
.
Now we only need to reference this definition in a visibleWhen definition for the menuContribution.
Do not forget to define (not) and then reference the com.example.project.hasNature
definition.
The (not) is not directly part of the definition itself, because we want to reuse this definition later on, where we want to ensure that the com.example.project.examplenature
is applied to a project.
3.6. Validate
Start your plug-in within the Eclipse IDE and create a new General Project and then right click the project and click on
. If you have done the optional part, the Convert to Example Project menu item should not appear in the Configure menu anymore.4. Provide an image as decorator for the project
You may have noticed the J as decorator for a java project.
In order to provide such an decorator image if your project nature has been applied to a project, you can use the org.eclipse.ui.ide.projectNatureImages
extension point.
So in case the com.example.project.examplenature
project nature is applied to a project, this decorator will also be shown.
The recommended size of these images is 8x8 pixels. Any other size might not look as good. |
When the com.example.project.examplenature
is applied to a general test project it should look like this:
5. Properties of a Project
Each project also has properties, which can be configured. You can access these properties from the last menu item of the context menu of a project, which is called Properties. For a general project called test the properties might look like this:
The org.eclipse.ui.propertyPages
extension point can be used to add new property pages to the project’s properties dialog.
In general a property page extends org.eclipse.ui.dialogs.PropertyPage
class
and also implements the org.eclipse.ui.IWorkbenchPropertyPage
interface.
6. Exercise: Add a new custom property page
This exercise describes how to add a custom property page to the properties dialog of projects, that have the com.example.project.examplenature
project nature.
The project from previous exercises is reused.
6.1. Adding a custom property page
Add the org.eclipse.ui.propertyPages
extension point and configure the page like this:
The referenced ExamplePropertyPage
should extend the org.eclipse.ui.dialogs.PropertyPage
class and implement the
org.eclipse.ui.IWorkbenchPropertyPage
interface.
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.IWorkbenchPropertyPage;
import org.eclipse.ui.dialogs.PropertyPage;
public class ExamplePropertyPage extends PropertyPage implements IWorkbenchPropertyPage {
@Override
protected Control createContents(Composite parent) {
// There will be no default, therefore remove default button
noDefaultButton();
Label label = new Label(parent, SWT.NONE);
label.setText("PropertyPage example.");
return label;
}
}
6.2. Optional - Reuse project nature definition
We only want to add the custom property page, if the com.example.project.examplenature
project nature is applied to the project.
Therefore we need to define an enabledWhen
definition, with the com.example.project.hasNature
expression, which has been created in the previous optional exercise.
6.3. Validate
Start your plug-in within the Eclipse IDE, right click your project and click on the Properties menu item. Then select Example Settings and the result should look like this:
In case you have also done the optional exercises the Example Settings should only be visible, if the
com.example.project.examplenature
project nature is applied to the project.
7. Eclipse Project Natures online resources
7.1. vogella Java example code
If you need more assistance we offer Online Training and Onsite training as well as consulting