tags:

views:

718

answers:

2

Hello,

I work with many small, but unrelated java projects. I made an Ant script that creates the .project and .classpath automatically whenever I create a new project, with the needed libraries and project name. I would like to be able to open Eclipse with that project, from the command line. Right now I do it manually, by closing the old open project in the workspace, then I do an Import and find the new project. I could not find a way to do this from either Ant or batch. I can open Eclipse, but it comes up with the last workspace/project. I don;t mind if I would have to create an individual worspace/project, but i don't know how to do that from a script. Thank you for any suggestions.

A: 

Partial solution: Open eclipse in a specified workspace:

eclipse.exe -data c:\code\workspace-name

Mr. Shiny and New
As mentioned, I can do that already, but it's not much help. I still have to close the previous project and go through import to get the new one open.
alex
+3  A: 

I would recommend against doing this as it is not really that much effort to import the project using the standard wizards. I'd focus on closing the inactive projects (see more below).

Edit: If you are dead set on using ant to bring the projects into the workspace, you can implement a plugin doing something like the code below.

Do you close the old projects or delete them? I don't see any reason to actually delete them. If you close all projects you aren't working on (right click on them and select close project or select the project you do want and right click->close unrelated projects), they are ignored by the platform so won't impact development of the open project.

To hide the closed projects from the view, you can click the downwards pointing triangle in the top right corner of the Package Explorer view, select Filters... and in the Select the elements to exclude from the view: list check the Closed projects option.


This is a plugin that will read a set of names from a file in the workspace root, delete all existing projects (without removing the contents) and create the new projects in the workspace. Use is at your own risk, no liability blah blah.

Take the contents and put them in the relevant files and you can package an Eclipse plugin. I'd recommend using a separate Eclipse install (actually I recommend against using it at all) as it will run every time it finds the newprojects.txt in the workspace root.

The declaration in the plugin.xml implements an Eclipse extension point that is called after the workbench initializes. The earlyStartup() method of the StartupHelper is called. It creates a new Runnable that is executed asynchronously (this means the workspace loading won't block if this plugin has issues). The Runnable reads lines from the magic newprojects.txt file it expects to see in the workspace root. If it finds any contents it will delete/create the projects.

Update: The helper has been modified to allow for projects to be created outside the workspace, if you define a value in newprojects.txt it is assumed that is the absolute URI of the project. Note that it doesn't escape the string, so if you are on a windows platform, use double slashes on the path.

Example contents:

#will be created in the workspace
project1 
#will be created at c:\test\project2
project2=c:\\test\project2

Good luck!

/META-INF/MANIFEST.MF:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Project fettling Plug-in
Bundle-SymbolicName: name.seller.rich;singleton:=true
Bundle-Version: 1.0.0
Bundle-Activator: name.seller.rich.Activator
Require-Bundle: org.eclipse.core.runtime,
 org.eclipse.ui.workbench;bundle-version="3.4.1",
 org.eclipse.swt;bundle-version="3.4.1",
 org.eclipse.core.resources;bundle-version="3.4.1"
Bundle-ActivationPolicy: lazy

/plugin.xml:

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin>
  <extension
         point="org.eclipse.ui.startup">
      <startup class="name.seller.rich.projectloader.StartupHelper"/>                    
   </extension>
</plugin>

/.project:

<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
    <name>name.seller.rich.projectloader</name>
    <comment></comment>
    <projects>
    </projects>
    <buildSpec>
        <buildCommand>
            <name>org.eclipse.jdt.core.javabuilder</name>
            <arguments>
            </arguments>
        </buildCommand>
        <buildCommand>
            <name>org.eclipse.pde.ManifestBuilder</name>
            <arguments>
            </arguments>
        </buildCommand>
        <buildCommand>
            <name>org.eclipse.pde.SchemaBuilder</name>
            <arguments>
            </arguments>
        </buildCommand>
    </buildSpec>
    <natures>
        <nature>org.eclipse.pde.PluginNature</nature>
        <nature>org.eclipse.jdt.core.javanature</nature>
    </natures>
</projectDescription>

/.classpath:

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
  <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
  <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
  <classpathentry kind="src" path="src/main/java"/>
  <classpathentry kind="output" path="target/classes"/>
</classpath>

/src/main/java/name/seller/rich/Activator.java:

package name.seller.rich;

import org.eclipse.core.runtime.Plugin;
import org.osgi.framework.BundleContext;

/**
 * The activator class controls the plug-in life cycle
 */
public class Activator extends Plugin {

    // The plug-in ID
    public static final String PLUGIN_ID = "name.seller.rich";

    // The shared instance
    private static Activator plugin;

    /**
     * Returns the shared instance
     * 
     * @return the shared instance
     */
    public static Activator getDefault() {
        return plugin;
    }

    /**
     * The constructor
     */
    public Activator() {
    }

    @Override
    public void start(final BundleContext context) throws Exception {
        super.start(context);
        plugin = this;
    }

    @Override
    public void stop(final BundleContext context) throws Exception {
        plugin = null;
        super.stop(context);
    }

}

/src/main/java/name/seller/rich/projectloader/StartupHelper .java:

package name.seller.rich.projectloader;

import java.io.File;
import java.io.FileInputStream;
import java.util.Map;
import java.util.Properties;

import name.seller.rich.Activator;

import org.eclipse.core.internal.resources.ProjectDescription;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.ui.IStartup;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;

public class StartupHelper implements IStartup {

 private static final class DirtyHookRunnable implements Runnable {
  private IWorkspaceRoot workspaceRoot;

  private DirtyHookRunnable(final IWorkspaceRoot workspaceRoot) {
   this.workspaceRoot = workspaceRoot;
  }

  public void run() {

   try {
    IPath workspaceLocation = this.workspaceRoot.getLocation();

    File startupFile = new File(workspaceLocation.toOSString(),
      "newprojects.txt");

    IProgressMonitor monitor = new NullProgressMonitor();

    Properties properties = new Properties();
    if (startupFile.exists()) {
     properties.load(new FileInputStream(startupFile));
    }
    if (properties.size() > 0) {
     // delete existing projects
     IProject[] projects = this.workspaceRoot.getProjects();

     for (IProject project : projects) {
      // don't delete the content
      project.delete(false, true, monitor);
     }

     // create new projects
     for (Map.Entry entry : properties.entrySet()) {
      IProject project = this.workspaceRoot
        .getProject((String) entry.getKey());

      // insert into loop
      ProjectDescription projectDescription = new ProjectDescription();
      projectDescription.setName((String) entry.getKey());

      String location = (String) entry.getValue();

      // value will be empty String if no "=" on the line
      // in that case it will be created in the workspace
      // WARNING, currently windows paths must be escaped,
      // e.g. c:\\test\\myproject
      if (location.length() > 0) {
       IPath locationPath = new Path(location);
       projectDescription.setLocation(locationPath);
      }

      project.create(projectDescription, monitor);

      // project.create(monitor);
      project.open(monitor);
     }
    }
   } catch (Exception e) {
    IStatus status = new Status(IStatus.INFO, Activator.PLUGIN_ID,
      0, "unable to load new projects", null);
    Activator.getDefault().getLog().log(status);
   }
  }
 }

 public StartupHelper() {
  super();
 }

 public final void earlyStartup() {

  IWorkbench workbench = PlatformUI.getWorkbench();
  IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();

  workbench.getDisplay().asyncExec(new DirtyHookRunnable(workspaceRoot));
 }
}
Rich Seller
First of all thank you for answering. This is an interesting take and I will look at it, but it may seem a bit out of the way. A few more words about my setup: we generate java projects (.java, resources) through preprocessing from a "master" code base. Then we tweak and compile it to jars. Occasionally we need to debug in Eclipse, at which point we manually create a project and import the source, res and libraries. I made this process now automatic, and I would like to end the code generation by opening Eclipse with the newly created project. Older projects are throwaway (closed/deleted).
alex
I am not dead-set on using Ant, anything goes, including batch (Win platform).
alex
this is a bit of a hack but you could define a plugin that checks a well known file for the "new" project on Eclipse startup. By implementing the IStartup interface the earlyStartup() method will be called and you can create the project as above. If I get some time I'll put together a more detailed response
Rich Seller
WOW! I expected maybe a link or something, but you went all out. Thank you. I will try to integrate this into the build process but it will take a few days since my script is incomplete. I will post my comments back when it is done
alex
I have two plugins that between them do 99% of this (one does the early startup, the other creates projects) so it only took a few minutes to write up and test, my main problem was an elegant way to read the properties file, see http://stackoverflow.com/questions/1091449/is-there-an-equivalent-of-java-util-properties-for-sets
Rich Seller
Ok, I couldn't wait a few days to try it, so I put this on priority. It works as advertised and I'm grinning like a crazed man. Just a few minor comments:- StartupHelper.java should be created in /src/main/java/name/seller/rich/projectloader/StartupHelper.java: not in /src/main/java/name/seller/projectloader/StartupHelper .java- the property file you mentioned (newprojects.txt) needs to contain simply the name of the project you want opened, nothing fancy: i.e test_project . Just to clarify it for other people.
alex
I need indeed to be able to create my projects outside the workspace root. If you have anything already done post, otherwise I will look it up in the near future and see if I can hack my way through your source code. When successful, I will post here. Thank you again for all you help.
alex
Thanks I'll update the post. From memory you can create a new org.eclipse.core.internal.resources.ProjectDescription and set the location URI.
Rich Seller
+1 for the über answer :-)
Newtopian