Home > Eclipse development, Software Development, Testing > Writing an Eclipse Plug-in (Part 4): Create a Custom Project in Eclipse – New Project Wizard: the Behavior

Writing an Eclipse Plug-in (Part 4): Create a Custom Project in Eclipse – New Project Wizard: the Behavior


In a previous post I showed how to get the GUI aspect of a New Wizard for the creation of a new project type up and running rather quickly. Even I was surprised; so surprised that I did it 2 more times just to make sure I wasn’t cheating somehow.

One of my side goals was to write the least amount of code and to let the plug-in extensions handle most of the integration of the various components.

With the GUI displaying the minimum expected GUI behavior it is now time to add minimum project-creation behavior.

The GUI counts as the platform so I won’t test it unless there is some strange behavior that I can’t explain. The creation of the project itself needs to be tested as I am adding a folder structure and a nature and I want to make sure that works. The test will also make it easier to extend my project structure in a controlled way.

Here are the steps:

  1. Create a new plug-in project, I have named it customplugin.test.
  2. plugin.xml –> Dependencies: Add org.junit4. This is required by the runtime workbench. If you see the dreaded No Runnable Methods message then you forgot to do this.
  3. Download dom4j from http://sourceforge.net/project/showfiles.php?group_id=16035&package_id=14121&release_id=328664. Extract the zip someplace safe; you will need two of the jar files in the next step.
  4. Create a folder named lib directly under customplugin.test and copy dom4j-1.6.1.jar and jaxen-1.1-beta-6.jar into customplugin.test/lib. One of the tests will open the .project file and check that the nature has been added. Using dom4j will make that much easier.
  5. In the customplugin.test plugin.xml file:
    • Runtime –> Classpath: Add the two jar files in the lib folder.
  6. Open the project Properties dialog. In the Project References element put a check mark next to the customplugin project (if you have been downloading the zip files then put a check mark next to customplugin_1.0.0.3).

Now the fun part: what should I test? Well, to create the simplest project within Eclipse involves only two things:

  • The name of the project
  • The location of the project

Truth be told you only need the project name. If null is given as the location name Eclipse uses the default workspace as the project destination.

I came up with only 4 tests:

  • Good project name, default location (null)
  • Good project name, different location
  • Null project name
  • Empty project name

The good test, regardless of workspace location, has to check that:

  • The project returned is non-null
  • The Custom nature was added
  • The .project file was created properly
  • The custom folder structure was created

The concept of a custom nature has finally appeared. Though a nature is typically used to tie a builder together to a project type, natures are also flags. If you get an IProject object looking at its nature or natures is a great way to determine what kind of project you are dealing with.

Add a nature by:

  • Opening your plugin.xml file
  • Going to the Extensions tab
  • Clicking Add
  • Finding and selecting the org.eclipse.core.resources.natures
  • Clicking Finish

First, select org.eclipse.core.resources.natures and enter in the ID field customplugin.projectNature. Next, open the (runtime) node, select the (run) node and enter a class name of customplugin.natures.ProjectNature. Click on the class link and click Finish on the New Java Class dialog.

I added the nature id as a string constant to make it easier to use in various parts of the code that will be implemented.

package customplugin.natures;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectNature;

import org.eclipse.core.runtime.CoreException;

public class ProjectNature implements IProjectNature {

    public static final String NATURE_ID = "customplugin.projectNature"; //$NON-NLS-1$

    @Override
    public void configure() throws CoreException {
        // TODO Auto-generated method stub
    }

    @Override
    public void deconfigure() throws CoreException {
        // TODO Auto-generated method stub
    }

    @Override
    public IProject getProject() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setProject(IProject project) {
        // TODO Auto-generated method stub
    }

}

For now, you don’t need more than that so feel free to close the Java editor on ProjectNature after you take a quick look at the generated code.

The following code went through a few iterations before it came to look like this, but it didn’t take that long; it took longer to strategize how I wanted to do it. It would take a long time to work through the mental steps I went through to create the CustomProjectSupport and CustomProjectSupportTest class. The code for the test is first, followed by the code that was slowly pulled together.

I decided that I was going to implement the code to create the project, add the nature and create my folder structure in a separate class to make it easier to test and insert into the wizard’s performFinish() method. It will be named CustomProjectSupport. The test class will be named CustomProjectSupportTest.

Add org.eclipse.core.resources to plugin.xml (well, really MANIFEST.MF) –> Dependencies or else the code won’t compile.
Here is the test code:

package customplugin.projects;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.runtime.AssertionFailedException;
import org.eclipse.core.runtime.CoreException;
import org.junit.Assert;
import org.junit.Test;

import customplugin.natures.ProjectNature;

public class CustomProjectSupportTest {
    @SuppressWarnings("nls")
    @Test
    public void testCreateProjectWithDifferentLocationArg() throws URISyntaxException, DocumentException, CoreException {
        String workspaceFilePath = "/media/disk/home/carlos/Projects/junit-workspace2";
        File workspace = createTempWorkspace(workspaceFilePath);

        String projectName = "delete-me"; //$NON-NLS-1$
        String projectPath = workspaceFilePath + "/" + projectName;
        URI location = new URI("file:/" + projectPath);

        assertProjectDotFileAndStructureAndNatureExist(projectPath, projectName, location);

        deleteTempWorkspace(workspace);
    }

    @Test
    public void testCreateProjectWithEmptyNameArg() {
        String projectName = " "; //$NON-NLS-1$
        assertCreateProjectWithBadNameArg(projectName);
    }

    @Test
    public void testCreateProjectWithNullNameArg() {
        String projectName = null;
        assertCreateProjectWithBadNameArg(projectName);
    }

    @SuppressWarnings("nls")
    @Test
    public void testCreateProjectWithGoodArgs() throws DocumentException, CoreException {
        // This is the default workspace for this plug-in
        String workspaceFilePath = "/media/disk/home/carlos/Projects/junit-workspace";
        String projectName = "delete-me";
        String projectPath = workspaceFilePath + "/" + projectName;

        URI location = null;
        assertProjectDotFileAndStructureAndNatureExist(projectPath, projectName, location);
    }

    @SuppressWarnings("nls")
    private void assertProjectDotFileAndStructureAndNatureExist(String projectPath, String name, URI location) throws DocumentException,
            CoreException {
        IProject project = CustomProjectSupport.createProject(name, location);

        String projectFilePath = projectPath + "/" + ".project";
        String[] emptyNodes = { "/projectDescription/comment", "/projectDescription/projects", "/projectDescription/buildSpec" };
        String[] nonEmptyNodes = { "/projectDescription/name", "/projectDescription/natures/nature" };

        Assert.assertNotNull(project);
        assertFileExists(projectFilePath);
        assertAllElementsEmptyExcept(projectFilePath, emptyNodes, nonEmptyNodes);
        assertNatureIn(project);
        assertFolderStructureIn(projectPath);

        project.delete(true, null);
    }

    @SuppressWarnings("nls")
    private void assertFolderStructureIn(String projectPath) {
        String[] paths = { "parent/child1-1/child2", "parent/child1-2/child2/child3" };
        for (String path : paths) {
            File file = new File(projectPath + "/" + path);
            if (!file.exists()) {
                Assert.fail("Folder structure " + path + " does not exist.");
            }
        }
    }

    private void assertNatureIn(IProject project) throws CoreException {
        IProjectDescription descriptions = project.getDescription();
        String[] natureIds = descriptions.getNatureIds();
        if (natureIds.length != 1) {
            Assert.fail("No natures found in project."); //$NON-NLS-1$
        }

        if (!natureIds[0].equals(ProjectNature.NATURE_ID)) {
            Assert.fail("CustomProject natures not found in project."); //$NON-NLS-1$
        }
    }

    private void assertAllElementsEmptyExcept(String projectFilePath, String[] emptyNodes, String[] nonEmptyNodes) throws DocumentException {
        SAXReader reader = new SAXReader();
        Document document = reader.read(projectFilePath);
        int strLength;
        for (String emptyNode : emptyNodes) {
            strLength = document.selectSingleNode(emptyNode).getText().trim().length();
            if (strLength != 0) {
                Assert.fail("Node " + emptyNode + " was non-empty!"); //$NON-NLS-1$ //$NON-NLS-2$
            }
        }

        for (String nonEmptyNode : nonEmptyNodes) {
            strLength = document.selectSingleNode(nonEmptyNode).getText().trim().length();
            if (strLength == 0) {
                Assert.fail("Node " + nonEmptyNode + " was empty!"); //$NON-NLS-1$//$NON-NLS-2$
            }
        }
    }

    private void assertFileExists(String projectFilePath) {
        File file = new File(projectFilePath);

        if (!file.exists()) {
            Assert.fail("File " + projectFilePath + " does not exist."); //$NON-NLS-1$//$NON-NLS-2$
        }
    }

    private void assertCreateProjectWithBadNameArg(String name) {
        URI location = null;
        try {
            CustomProjectSupport.createProject(name, location);
            Assert.fail("The call to CustomProjectSupport.createProject() did not fail!"); //$NON-NLS-1$
        } catch (AssertionFailedException e) {
            // An exception was thrown as expected; the test passed.
        }
    }

    private void deleteTempWorkspace(File workspace) {
        boolean deleted = workspace.delete();
        if (!deleted) {
            Assert.fail("Unable to delete the new workspace dir at " + workspace); //$NON-NLS-1$
        }
    }

    private File createTempWorkspace(String pathToWorkspace) {
        File workspace = new File(pathToWorkspace);
        if (!workspace.exists()) {
            boolean dirCreated = workspace.mkdir();
            if (!dirCreated) {
                Assert.fail("Unable to create the new workspace dir at " + workspace); //$NON-NLS-1$
            }
        }

        return workspace;
    }

}

The CustomProjectSupport code looks like this:

package customplugin.projects;

import java.net.URI;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;

import customplugin.natures.ProjectNature;

public class CustomProjectSupport {
    /**
     * For this marvelous project we need to:
     * - create the default Eclipse project
     * - add the custom project nature
     * - create the folder structure
     *
     * @param projectName
     * @param location
     * @param natureId
     * @return
     */
    public static IProject createProject(String projectName, URI location) {
        Assert.isNotNull(projectName);
        Assert.isTrue(projectName.trim().length() > 0);

        IProject project = createBaseProject(projectName, location);
        try {
            addNature(project);

            String[] paths = { "parent/child1-1/child2", "parent/child1-2/child2/child3" }; //$NON-NLS-1$ //$NON-NLS-2$
            addToProjectStructure(project, paths);
        } catch (CoreException e) {
            e.printStackTrace();
            project = null;
        }

        return project;
    }

    /**
     * Just do the basics: create a basic project.
     *
     * @param location
     * @param projectName
     */
    private static IProject createBaseProject(String projectName, URI location) {
        // it is acceptable to use the ResourcesPlugin class
        IProject newProject = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);

        if (!newProject.exists()) {
            URI projectLocation = location;
            IProjectDescription desc = newProject.getWorkspace().newProjectDescription(newProject.getName());
            if (location != null && ResourcesPlugin.getWorkspace().getRoot().getLocationURI().equals(location)) {
                projectLocation = null;
            }

            desc.setLocationURI(projectLocation);
            try {
                newProject.create(desc, null);
                if (!newProject.isOpen()) {
                    newProject.open(null);
                }
            } catch (CoreException e) {
                e.printStackTrace();
            }
        }

        return newProject;
    }

    private static void createFolder(IFolder folder) throws CoreException {
        IContainer parent = folder.getParent();
        if (parent instanceof IFolder) {
            createFolder((IFolder) parent);
        }
        if (!folder.exists()) {
            folder.create(false, true, null);
        }
    }

    /**
     * Create a folder structure with a parent root, overlay, and a few child
     * folders.
     *
     * @param newProject
     * @param paths
     * @throws CoreException
     */
    private static void addToProjectStructure(IProject newProject, String[] paths) throws CoreException {
        for (String path : paths) {
            IFolder etcFolders = newProject.getFolder(path);
            createFolder(etcFolders);
        }
    }

    private static void addNature(IProject project) throws CoreException {
        if (!project.hasNature(ProjectNature.NATURE_ID)) {
            IProjectDescription description = project.getDescription();
            String[] prevNatures = description.getNatureIds();
            String[] newNatures = new String[prevNatures.length + 1];
            System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length);
            newNatures[prevNatures.length] = ProjectNature.NATURE_ID;
            description.setNatureIds(newNatures);

            IProgressMonitor monitor = null;
            project.setDescription(description, monitor);
        }
    }

}

For the above tests to run you need to export some of the packages from the customplugin project. In the customplugin plugin.xml Runtime tab add the following packages to the Exported Packages list:

  • customplugin.natures
  • customplugin.projects

Finally, let’s add CustomProjectSupport to the CustomProjectNewWizard:

    @Override
    public boolean performFinish() {
        String name = _pageOne.getProjectName();
        URI location = null;
        if (!_pageOne.useDefaults()) {
            location = _pageOne.getLocationURI();
        } // else location == null

        CustomProjectSupport.createProject(name, location);

        return true;
    }

One last thing: let’s set up the process of creating a new project to end with the opening of the Custom Plug-in Perspective.

Select the “Custom Project (wizard)” entry under org.eclipse.ui.newWizards.

  • finalPerspective: customplugin.perspective
  • Save the file

Add IExecutableExtension to CustomProjectNewWizard:

public class CustomProjectNewWizard extends Wizard implements INewWizard, IExecutableExtension {

Let the editor add the unimplemented (and empty) method setInitializationData().

Before you implement the method add the following field to hold the plug-in configuration information necessary to make the perspective change:

private IConfigurationElement _configurationElement;

The plug-in will call setInitializationData() to supply the plug-in with the information it needs to display the proper perspective when performFinish() is complete.

    @Override
    public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
        _configurationElement = config;
    }

In performFinish() add the call to updatePerspective():

    @Override
    public boolean performFinish() {
        String name = _pageOne.getProjectName();
        URI location = null;
        if (!_pageOne.useDefaults()) {
            location = _pageOne.getLocationURI();
            System.err.println("location: " + location.toString()); //$NON-NLS-1$
        } // else location == null

        CustomProjectSupport.createProject(name, location);
        // Add this
        BasicNewProjectResourceWizard.updatePerspective(_configurationElement);

        return true;
    }

All done. Go create a project and check that the tests actually did their jobs. For extra points, open the Custom Project Navigator. It should show you the same thing as the Package Navigator or the plain vanilla Navigator view.

On the off chance I missed something or did not explain something properly, please let me know. I wrote this all down as I was doing it so I may have missed a step or 12.

Perhaps I should re-release my book….

About these ads
  1. Martin
    October 5, 2009 at 4:23 am

    Oh c’mon…

    when will you go on with that tutorial?
    this is exactly what I searched for :)

    So pleeeaaase…

  2. cvalcarcel
    October 6, 2009 at 11:56 am

    I expect to get back to this soon. Yes, I have neglected this….I apologize, but not too much.

    • Pedro
      November 10, 2009 at 7:01 am

      I need your help. I have a problem with this code.
      if (!project.hasNature(ProjectNature.NATURE_ID))
      What is the NATURE_ID?

      Thanks

      • cvalcarcel
        November 10, 2009 at 10:02 pm

        Hi, Pedro!

        Line 14 in CustomProjectSupport.java shows:

        import customplugin.natures.ProjectNature;
        

        which is used at line 103:

        if (!project.hasNature(ProjectNature.NATURE_ID)) {
        

        In ProjectNature.java NATURE_ID is defined as:

            public static final String NATURE_ID = "customplugin.projectNature"; //$NON-NLS-1$
        

        Sadly, I left that code out. I have added it to Part 4. Thanks for pointing it out!

  3. November 27, 2009 at 10:19 am

    Excellent tutorial!

    One note: the paragraph about adding the nature is missing the bit about setting nature id to “customplugin.projectNature”. Without this addNature() function fails.

  4. cvalcarcel
    November 29, 2009 at 7:15 pm

    Oops! Good catch! I have added the missing line to the offending paragraph.

    Thanks for the catch!

  5. Augusto
    November 30, 2009 at 5:38 am

    Hi Carlos!
    First of all, thanks for your tutorials, they have been really helpful!
    I just wanted to make a question concerning the new project wizard. Mine works like a charm but I would like to add it as a submenu in the navigators context menu under New. I would like it to be New -> Custom Project directly instead of New -> Project and then have to select Custom Project. Do you know how to make this?

    Have a nice day,
    Augusto

  6. cvalcarcel
    December 2, 2009 at 12:50 am

    Hmm. There are two ways to do it: the lazy way and the right way.

    First, the lazy way: run the instance of Eclipse that has your new project definition already set up. Open Window –> Customize Perspective –> Menu Visibility –> File –> New and then put a check mark next to Custom Project. Click OK and select from the main menu bar File –> New –> Custom Project.

    While that works I am sure that is not what you wanted. You wanted to know how to configure the customplugin project to do that automatically.

    Jeez, what a tough crowd. I will add this to a future blog, but what the heck you could use it right now.

    Okay:
    1. Open up plugin.xml for customplugin
    2. Go to Extensions –> Add –> perspectiveExtension and click Finish
    3. Change
    targetID: *
    to
    targetID: customplugin.perspective
    4. Right click on customplugin.perspective (perspectiveExtension) –> new –> newWizardShortcut
    5. Select newWizardShortcut and enter:
    ID: customplugin.wizard.new.custom
    The above is the id of the New Custom Project Wizard entry under org.eclipse.ui,newWizards –> Custom Project (wizard)
    6. Save plugin.xml

    Run the runtime workbench, open the Custom Perspective, go to File –> New and you should see Custom Project in the submenu.

    What? You want it to appear in all of the perspectives, not just the Custom Perspective?

    You really are tough.

    Do the following:
    1. Go to the extension you just added: plugin.xml –> Extensions –> org.eclipse.ui.perspectiveExtension
    2. Change
    targetID: customplugin.perspective
    to
    targetID: *
    3. Save plugin.xml

    Run the runtime workbench, open the Custom Perspective, go to File –> New and you should see Custom Project in the submenu.

    Yes, if you do the same to the org.eclipse.ui.perspectiveExtension that adds the Custom Navigator it will also add the Custom Navigator to all of your perspectives.

    Trust me. You don’t want that. Try it. Can you say Ugly?

    Let me know if the above does not satisfy your curiosity!

  7. Augusto
    December 2, 2009 at 6:07 am

    Hi Carlos,

    Thank you for the quick answer.
    This isn’t exactly what I wanted although it is quite useful also. Maybe I didn’t explain correctly, what I want is to add exactly the same (the new custom project under New->…), but in the Context Menu in the navigator (the menu that appears when clicking the right mouse button on it).

    I was investigating and it looks like it might be related with the extension “org.eclipse.ui.popupMenus”. I then was able to add a contribution to navigator viewer using the “viewerContribution” but I can’t position the new action I contributed under the New menu. It appears in the bottom of the context menu if I set the “menubarPath” to “additions” though.

    Regards,
    Augusto

    • cvalcarcel
      December 8, 2009 at 10:47 pm

      Sorry I have taken so long to answer: and the answer isn’t good.

      The answer to your question is: what you want to do is trivial, but not that trivial. I will be writing about it soon…as soon as I get to that part in my rants about CNF.

      I told you it wasn’t a good answer.

  8. Augusto
    December 9, 2009 at 4:56 am

    Hi Carlos,

    I’m looking forward to the CNF chapters :)

    Have a nice day,
    Augusto

  9. Joseph Hillhouse
    February 11, 2010 at 5:07 pm

    Hi Carlos,

    Thanks for the tutorial. It was awesome. However, I got lost at the CustomProjectSupport and the CustomProject area. Where do I create these files (in which plug-in customplugin or customplugin.test) and I don’t follow how to add the CustomProjectSupport and CustomProject to the customplugin NewWizard class.

    Thanks

    • cvalcarcel
      February 14, 2010 at 12:23 am

      Sorry, I should have been more explicit. Tests go in the customplugin.test project; everything else goes in customplugin.

      Create the CustomProjectSupport class in a package named customplugin.projects in the customplugin project.

      Add the CustomProjectSupport code in CustomProjectNewWizard.performFinish() as shown in the performFinish() code above.

      The “Custom Wizard (wizard)” entry is located in the plugin.xml for the customplugin project. It has an element named finalPerspective where you should add the custom perspective id of customplugin.perspective.

      Don’t be afraid to experiment. Implementing an Eclipse plug-in can be daunting and intimidating, but doable.

      It is okay to get it wrong. Just do it again. And again. Eventually, it makes sense.

  10. Steffen Elste
    March 7, 2010 at 10:20 am

    Hi,
    when i run the Test as a ‘JUnit Plug-in Test’ the new workbench opens – but closes immediately again.
    JUnit complains about a ‘NoClassDefFoundError: customplugin/projects/CustomProjectSupport’ in method ‘assertProjectDotFileAndStructureAndNatureExist’.

    Any idea what i’m missing here?!

    Regards

    • cvalcarcel
      March 7, 2010 at 8:31 pm

      Interesting. It seems that perhaps the test plug-in does not have the customplugin listed as a Project Reference.

      Right click on the customplug.test and select Properties. Select Project References and check that the only project reference that is checked is customplugin.

      Let me know how that goes.

      • Steffen Elste
        March 8, 2010 at 12:14 pm

        … actually that was the first thing i checked after the test failed ;-)
        Nope, the reference is there, checked it – at least – twice.

        Hmm, think i’ll try again with a new workspace – if it works the second time around i can try to figure out the difference(s)!

        Thanks nevertheless for the hint.
        Cheers

  11. Matt
    March 31, 2010 at 9:44 am

    Hi Carlos,
    Thanks, these blogs are helping me very much. One microscopic correction: I think “Add org.eclipse.core.resource to plugin.xml (well, really MANIFEST.MF) –> Dependencies or else the code won’t compile.” should be “Add org.eclipse.core.resources to plugin.xml (well, really MANIFEST.MF) –> Dependencies or else the code won’t compile.” with an ‘s’ on resources.

    • cvalcarcel
      March 31, 2010 at 11:04 pm

      Fixed! Thanks for the catch!

  12. Paul Beusterien
    October 22, 2010 at 6:42 pm

    Thanks Carlos! Great tutorials! They’re very helpful.

    One minor nit. Tutorial #2 uses the constant WIZARD_NAME before it gets refactored in Tutorial #3.

    • cvalcarcel
      October 30, 2010 at 1:25 pm

      Oops! I hate when that happens. When I first started this blog I had the first 4 already written and the code in various states of completion so I would not doubt that I accidentally used the (partially) refactored code too soon.

      That hasn’t been a problem lately. :S

  13. curts
    January 24, 2011 at 6:03 am

    I have the customplugin working, but I have not managed to get the test class customplugin.test to work. When I try to launch the “JUnit Plug-in Test” from the ‘Run As’ menu, the new workspace launches, but then closes and in the Console I get the following errors: “The activator customplugin.test.Activator for bundle customplugin.test is invalid” and then “Class not found customplugin.test.CustomProjectSupportTest”. I suspect my Extensions for customplugin.test are incomplete. I am using Eclipse Helios SR1 for RCP and RAP Developers. My ‘plugin.xml’ for customplugin.test currently contains:

    build.properties contains:

    source.. = src/
    output.. = bin/
    bin.includes = META-INF/,\
    lib/dom4j-1.6.1.jar,\
    lib/jaxen-1.1-beta-6.jar,\
    plugin.xml

  14. March 11, 2011 at 7:14 pm

    Thanks a lot for this article. Maybe add a note to the part about “org.eclipse.core.resources.natures” that people might have to remove the checkbox below the list to actually enable this extension point…

  15. Varghese Cottagiri
    June 28, 2011 at 5:22 am

    Awesome tutorial, there isn’t another like this on the subject anywhere.
    I wanted to point out one discrepancy –
    Shouldn’t
    ESPProjectSupport.createProject(name, location);
    be
    CustomProjectSupport.createProject(name, location);
    in the ‘performFinish() add the call to updatePerspective()’ piece

    • cvalcarcel
      June 29, 2011 at 9:55 pm

      Arg. I have when the code changes upon observation. It doesn’t make the cat any happier either.

      Thanks for catching that! The code is updated.

  16. August 3, 2011 at 5:00 am

    Great articles, thanks a lot for that. Just a question: shouldn’t things like adding folders to the newProject rather be performed within the configure() of your CustomNature?

  17. Phani
    August 11, 2011 at 6:08 am

    No schema found for the ‘org.eclipse.core.resources.natures’ extension point

    Only generic appearing in new

    I added the below sources plugin to the target platform

    org.eclipse.core.resources.source_3.6.0.v20100526-0737

    Still the No schema…. not solved.

    Are there any other sources required. What else I need to do.

  18. elahe
    August 20, 2011 at 3:04 pm

    i add to argouml the capability to measure (Object Oriented) Metrics
    i modify ArgoUML code through eclipse
    now i want to have a plugin of what i’ve done to argouml code
    need some help

  19. alex
    September 12, 2011 at 6:48 am

    dude, honestly: this is the best step-by-step tutorial for a custom eclipse project wizard, nature & perspective that I found in the net.

    thank you very much cvalcarcel, you helped my a lot!

    alex

  20. September 21, 2011 at 9:22 am

    Hi,

    When I try this it throws an exception on the line: newProject.create(desc, null);

    Saying:
    Contains: /Users/James/Documents/Programs/runtime-EclipseApplication/Test overlaps the location of another project: ‘Test’

    But no project exists in the workspace with that name already. It only happens when I try to create a project in the subdirectory of the workspace, the “default” location. If I create it somewhere else it doesn’t give me this error.

    Any idea what’s going on?

    Thanks,
    James

    • September 21, 2011 at 9:36 am

      Never mind, I wasn’t passing null for when it was in the default location.

  21. October 8, 2011 at 11:32 am

    Hi Carlos
    Thanks for your enormously helpful tutorials.
    In trying to follow this one, when it comes to testing it by creating a new project (“as a user”) I get a CoreException “Contains: Nature does not exist: org.grammaticalframework.eclipse.ui.natures.projectNature”

    I’ve double checked all the steps and checked all my IDs are right and it won’t help… any ideas?
    Thanks again!
    John

  22. October 10, 2011 at 4:43 am

    Hi, I have found a response to my own question above (you may edit the comments as you see fit!):

    1. The nature class itself is: org.grammaticalframework.eclipse.ui.natures.GFProjectNature
    2. In plugin.xml > Extensions > org.eclipse.core.resources.natures I needed to specify only the _relative_ ID: “natures.projectNatureID”
    3. Then in GFProjectNature, I had to specify the _fully qualfied_ ID as:
    public static final String NATURE_ID = “org.grammaticalframework.eclipse.ui.natures.projectNatureID”; //$NON-NLS-1$

    Hope that helps someone who had the same problem as me!

    • Sunny
      April 13, 2012 at 9:57 pm

      Hi John
      I was actually stuck at the same place but that was actually a bug in my plugin.xml.
      I had actually misspelled the nature id in the plugin.xml fixing that it worked perfectly fine.

  23. vivek
    January 6, 2012 at 1:37 pm

    Hi Carlos,
    These are great tutorials for beginners like me. Thank you very much.

    I got many errors while working with this. I was able to get rid of many by importing files as suggested by it. But two errors I can’t understand are:

    1. if (location != null && ResourcesPlugin.getWorkspace().getRoot().getLocationURI().equals(location)) {
    projectLocation = null;
    }
    Here I get an error “amp cannot be resolved to a variable”

    2. Assert.isTrue(projectName.trim().length() > 0);

    I get a similar error “gt cannot be resolved to a variable” Can you please explain? Am I missing something really basic.

    Regards,
    Satya

  24. vivek
    January 6, 2012 at 2:30 pm

    Ok Sir I got it…I think its escaping as part of html. I replaced them with > in > case and && in &&amp case.

    Thanks,
    Satya

  25. Federico Sellanes
    January 16, 2012 at 11:54 am

    Hi sir, your tutorial is awesome. The customplugin.test_1.0.0.4 download is not available. Thanks for everything.

  26. Sunny
    April 13, 2012 at 10:08 pm

    Hi Carlos
    Thanks for the excellent tutorial.
    I am stuck though whenever I try to launch the test file as a junit it gives me an error ClassNotFoundException on the test class itself. Platform v 3.7. Please help

  27. fat
    July 24, 2012 at 8:51 am

    Hi,
    It’s a perfect tutorial but I have some troubles with the two classes customProjectSupport & customProjectSupportTest : I have followed step by step this tutorial I don’t Know where exactly I should create these classes ( well, in customplugin/src or custopplugin.test/src ) and eclipse (Juno) gives me a lot of errors he don’t recognise a lot of imports such as org.junit, org.domj4 …etc
    please I need your help.
    All My Best.

  28. Tijs
    August 22, 2012 at 2:44 pm

    The tutorial is great, but I ran into trouble: My performFinish() method looks completely different. I don’t know where to place
    // Add this
    BasicNewProjectResourceWizard.updatePerspective(_configurationElement);

    Another issue is that I cannot find
    CustomProjectSupport.createProject(name, location);
    So there is no call to CustomProjectSupport which is rather strange..

    My performFinish() looks like this:

    public boolean performFinish() {
    final String containerName = page.getContainerName();
    final String fileName = page.getFileName();
    IRunnableWithProgress op = new IRunnableWithProgress() {
    public void run(IProgressMonitor monitor) throws InvocationTargetException {
    try {
    doFinish(containerName, fileName, monitor);
    } catch (CoreException e) {
    throw new InvocationTargetException(e);
    } finally {
    monitor.done();
    }
    }
    };
    try {
    getContainer().run(true, false, op);
    } catch (InterruptedException e) {
    return false;
    } catch (InvocationTargetException e) {
    Throwable realException = e.getTargetException();
    MessageDialog.openError(getShell(), “Error”, realException.getMessage());
    return false;
    }
    return true;
    }

    I use eclipse 4.1 for plug in development, maybe that has something to do with it.
    Regards,
    Tijs

  29. Krishnaraj Bhat
    January 1, 2013 at 4:41 am

    Hi Carlos,

    This is a very good tutorial for the beginners like me. I am trying this to create a custom project. I followed the step by step process as mentioned in this and previous tutorials. I have successfully created customplugin and customplugin.test plug-in projects as mentioned in the tutorial. But for some reason, when I run the project, I couldn’t create a new custom project. When I click on File->New->Custom Wizards->Custom Project, New Custom Plug-in Project dialog opens. This dialog box includes the fields for Project Name and location with Use Default location checkbox checked. This dialog also contains Back, Next Cancel and Finish button. When I give some meaningful name, Finish button enables. But clicking the finish button couldn’t create a new project. Could you please let me know what might be the reason for this.

    Below is the code for CustomProjectNewWizard class.

    package customplugin.wizards;

    import java.net.URI;

    import org.eclipse.core.runtime.CoreException;
    import org.eclipse.core.runtime.IConfigurationElement;
    import org.eclipse.core.runtime.IExecutableExtension;
    import org.eclipse.jface.viewers.IStructuredSelection;
    import org.eclipse.jface.wizard.Wizard;
    import org.eclipse.ui.INewWizard;
    import org.eclipse.ui.IWorkbench;
    import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
    import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;

    import customplugin.projects.CustomProjectSupport;

    public class CustomProjectNewWizard extends Wizard implements INewWizard, IExecutableExtension {

    private IConfigurationElement _configurationElement;
    private static final String PAGE_NAME = “Custom Plug-in Project Wizard”;
    private static final String WIZARD_NAME = “New Custom Plug-in Project”;
    private WizardNewProjectCreationPage _pageOne;
    public CustomProjectNewWizard() {
    // TODO Auto-generated constructor stub
    setWindowTitle(WIZARD_NAME);
    }

    @Override
    public void init(IWorkbench workbench, IStructuredSelection selection) {
    // TODO Auto-generated method stub

    }

    @Override
    public void addPages() {
    super.addPages();

    _pageOne = new WizardNewProjectCreationPage(PAGE_NAME);
    _pageOne.setTitle(“From Scratch Project”); //$NON-NLS-1$
    _pageOne.setDescription(“Create something from scratch.”); //$NON-NLS-1$

    addPage(_pageOne);
    }

    @Override
    public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
    _configurationElement = config;
    }

    @Override
    public boolean performFinish() {
    String name = _pageOne.getProjectName();
    URI location = null;
    if (!_pageOne.useDefaults()) {
    location = _pageOne.getLocationURI();
    System.err.println(“location: ” + location.toString()); //$NON-NLS-1$
    } // else location == null
    System.err.println(“location: ” + location.toString());
    CustomProjectSupport.createProject(name, location);
    // Add this

    BasicNewProjectResourceWizard.updatePerspective(_configurationElement);

    return true;
    }

    }

  30. February 14, 2013 at 12:01 pm

    Hi

    JUnit complains about a ‘NoClassDefFoundError: customplugin/projects/CustomProjectSupport’ in method ‘assertProjectDotFileAndStructureAndNatureExist’.

    For solving this issue, one should make customplugin as a required plug-ins dependencies in the customplugin.test plugin.xml

  31. February 14, 2013 at 12:33 pm

    Hi Carlos

    I forgot also to mention that the workspaceFilePath should also be customized to fit the local Eclipse machine. I would suggest to use “C:/TEMP/customws” on Windows.

  32. Vinodh
    April 30, 2013 at 11:04 am

    Hi,

    Thanks for your wonderful tutorial. I’ve implemented the steps and the fixes which you have given in the comments.
    But after the new eclipse plugin is open, I’m trying to create a new custom project in the wizard which is there in New->Project-> Others-> . If i select and click next button, i’m getting following error:

    “The selected wizard could not be started.
    Plug-in customplugin.test was unable to load class CustomProjectNewWizard.
    CustomProjectNewWizard”

    Could you please provide the solution for this issue.

    Thanks
    Vinodh.R

  1. December 3, 2013 at 12:53 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 3,182 other followers

%d bloggers like this: