GSF Classpath

WARNING: GSF has its own Classpath copy of the Java one, slightly renamed and in a different package. However, in NetBeans 6.5, the Java Classpath module has been moved from the java cluster into the IDE cluster and should be generic. I plan to retrofit GSF to use the standard Classpath package as soon as possible.
NOTE 2: The class path and project integration aspects of GSF are really half baked at this point. It works, but it's not pretty, and this is an area that I know will need to change and I plan to do something about it.

The GSF classpath API sits in its own module and its own package: gsfpath.api. It's a pretty small API. All it boils down to this this: For each project type (Ruby Project, Web Project for JavaScript, Groovy project for Groovy, etc.) you have to tell GSF where your sources are. The way you do this is to register a "project open hook", a callback provided by the project system which will call custom code after the project is opened. In the project open hook, you register a series of directories with GSF. That's really the gist of it.

Unfortunately, it's not the 3 lines it sounds like. What you actually have to register are "Classpath" objects, one for each source root, and one for each library. A classpath has both a directory/url, as well as a "type", such as "SOURCE" or "BOOT". A "SOURCE" classpath is exactly what you expect - it's a root directory for sources in your project. "BOOT" on the other hand designates a library. As explained in the indexing document, these can be treated differently by the code. Some features may only want to search local project sources, and so on.

What you end up doing is something like the following (I will use the Rails project as an example):

  1. Implement an implementation of a ClasspathProvider (org.netbeans.modules.gsfpath.spi.classpath.ClassPathProvider). In the Rails case, this is the ClassPathProviderImpl class in ruby.railsproject. I will describe this class in more detail below.
  2. Register the ClassPathProviderImpl in your project's lookup.
  3. In your project's open hook, register your class path with the global path registry, like this:
        ClassPathProviderImpl cpProvider = getLookup().lookup(ClassPathProviderImpl.class);
        GlobalPathRegistry.getDefault().register(ClassPath.BOOT, cpProvider.getProjectClassPaths(ClassPath.BOOT));
        GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, cpProvider.getProjectClassPaths(ClassPath.SOURCE));
                        
  4. Similarly. in your project's close hook, unregister the paths:
        ClassPathProviderImpl cpProvider = getLookup().lookup(ClassPathProviderImpl.class);
        GlobalPathRegistry.getDefault().unregister(ClassPath.BOOT, cpProvider.getProjectClassPaths(ClassPath.BOOT));
        GlobalPathRegistry.getDefault().unregister(ClassPath.SOURCE, cpProvider.getProjectClassPaths(ClassPath.SOURCE));
                        
That's basically it. So the only trick here is implementing the ClasspathProvider. Take a look at the one in the Rails project, or the Web project (web.project), etc. It's not rocket science. You just have to do whatever it takes for the specific project type to look up the source roots, decide whether all of these are relevant for your file type (for example, in Web projects, I only register the web folder for JavaScript, not the src folder which just contains Java code) and then produce classpath implementation objects for these. There are utility methods to help.

As I warned in the red box above, this will probably change soon.