Home Tutorials Training Consulting Products Books Company Donate Contact us









NOW Hiring

Quick links

Share

Eclipse Project Natures This article describes how product natures can be implemented and what can be done with 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 consist of several project natures. The most popular project nature is org.eclipse.jdt.core.javanature, which is used to specify the project as Java project. Some examples for project natures are:

Table 1. Examples of Project Natures
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 usually can convert the project via context menu.

configure project popup
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, which implements IProjectNature.

<extension
    id="examplenature"
    name="Example nature"
    point="org.eclipse.core.resources.natures">
    <runtime>
        <run
            class="com.example.product.ExampleProductNature">
        </run>
    </runtime>
</extension>

The implementation of the referenced ExampleProductNature 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 ExampleProductNature.

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 your custom project nature should only apply for Java project.

<extension
    id="examplenature"
    name="Example nature"
    point="org.eclipse.core.resources.natures">
    <runtime>
        <run
            class="com.example.product.ExampleProductNature">
        </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.

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

Add a Convert to example project menu item to the Configure menu of a projects context menu.

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.

exercise project nature extension

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.

exercise convert menucontribution

3.5. Optional - Add a core expression

As already mentioned the Configure menu is only visible, in case it has elements in it, we should only apply the menuContribution to it, if the nature has not already been set. Therefore we want to add a core expression with the org.eclipse.core.expressions.definitions extension point.

exercise core expression

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.

exercise project nature propertytester

Now we only need to reference this definition in a visibleWhen definition for the menuContribution.

exercise visibleWhen expression

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 Configure ▸ Convert to Example Project. In case you have done the optional part, the Convert to Example Project menu item should not appear any more in the Configure menu.

4. Provide an image as decorator for the project

You may have noticed the J as decorator for a java project.

project nature java images

In order to provide such an decorator image in case your project nature has been applied to a project, you can use the org.eclipse.ui.ide.projectNatureImages extension point.

project nature images extension point

So in case the com.example.project.examplenature project nature is applied to a project, this decorator will also be shown.

The size of the image 8x8 is recommended in order to look nice.

When the com.example.project.examplenature is applied to a general test project it should look like this:

project nature image example

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:

minimal project properties

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

In this exercise we want to reuse the project from the previous exercise.

6.1. Target

Add a custom property page to the properties of those projects, which have com.example.project.examplenature as project nature.

6.2. Adding a custom property page

Add the org.eclipse.ui.propertyPages extension point and configure the page like this:

exercise project nature property page

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.3. Optional - Reuse project nature definition

We only want to add the custom property page, in case the com.example.project.examplenature project nature is set. Therefore we define a enabledWhen definition, with the com.example.project.hasNature expression, which has been created in the previous optional exercise. See Optional - Add a core expression

property page enablement

6.4. 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:

exercise project nature property page sample

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. About this website

8. Eclipse Project Natures online resources

8.1. vogella GmbH training and consulting support

TRAINING SERVICE & SUPPORT

The vogella company provides comprehensive training and education services from experts in the areas of Eclipse RCP, Android, Git, Java, Gradle and Spring. We offer both public and inhouse training. Whichever course you decide to take, you are guaranteed to experience what many before you refer to as “The best IT class I have ever attended”.

The vogella company offers expert consulting services, development support and coaching. Our customers range from Fortune 100 corporations to individual developers.

Copyright © 2012-2017 vogella GmbH. Free use of the software examples is granted under the terms of the EPL License. This tutorial is published under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany license.

See Licence.