« JProfiler: Your Java code could be running faster in under two hours | Main | Java Riddle: Static Members in Inner Classes? »

Jul 22, 2008

Eclipse: Gracefully Loading a Heavy Plugin

Here's the challenge: I have a plug-in which may take more than a few seconds to load. That's not a problem if the plug-in is loaded when the platform starts since the user waits for platform to load anyway. However, if the plug-in is loaded on-demand, after the platform is already started, the user may experience an unexplained freeze. 

To overcome this behavior, it is best to use some progress dialog with a monitor when starting your plugin. This is simple, however, the less-than-trivial question is: how to determine if the platform is starting?  

Those with some knowledge of Eclipse would simply direct me to a very simple API call:

PlatformUI.isWorkbenchRunning()

One major disadvantage.. this is useless, since it will return true when the platform is still loading as well. It is considered running at this point.

Searching in the Eclipse newsgroups portal, I came across another idea:

Bundle b = Platform.getBundle("org.eclipse.swt");
if (b==null || b.getState() != Bundle.ACTIVE) {
   System.out.println("no UI...");
}

This doesn't work, since SWT is already resolved when the splash screen is shown. You can test other bundles, if you'd like, but I find it hard to believe you'll discover any well-defined and consistent difference between the two situations: loading upon launch and loading after it is complete.

My next idea was to check the visibility of the default shell. Nope, it is considered visible at startup. I tried checking for the existence of workbench visual parts and, guess what, they're already there in both cases. After some trial and error I found a very simple way of doing that. One of the distinct features when the splash screen is showing is that you don't see a menu-bar. From that I derived the following test:

Display.getCurrent().getActiveShell().getMenuBar() == null

This will return true when the platform is still launching and a splash screen is shown. Putting it all together and adding all the null checks I could think of, I wrote the following method for checking if the shell is already open and return it if it is:

private Shell findStartedShell() {
   Shell result = null;
   final Display currentDisplay = Display.getCurrent();
   if (currentDisplay != null) {
      result = currentDisplay.getActiveShell();
      if ((result != null) && (result.getMenuBar() == null)) {
         result = null;
      }
   }
   return result;
}

I used a ProgressMonitorDialog to show the progress and an IRunnableWithProgress to implement the lengthy startup process. Eventually, the plugin Activator start method would look like this:

public void start(final BundleContext context) throws Exception {
   super.start(context);
   plugin = this;
   final IRunnableWithProgress statupOperation = 
      new IRunnableWithProgress() {

      public void run(final IProgressMonitor monitor) throws
         InvocationTargetException, InterruptedException {
         // do your initialization here
         // use the monitor to set the task name 
         // and report progress

      }
   };

   final Shell activeShell = findStartedShell();
   if (activeShell != null) {
      final ProgressMonitorDialog progressMonitorDialog =
         new ProgressMonitorDialog(activeShell);
      progressMonitorDialog.run(false, false, statupOperation);
   } else {
      statupOperation.run(new NullProgressMonitor());
   }
}

The above will do exactly what we were looking for: if the platform is launching, it will proceed with normal startup (the splash screen shows the progress of loading all the plugins) and, if the platform is already loaded, it will show a progress dialog.

Found a better way of doing that?  Let me know in the comments.

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00d83548421753ef00e553b062e38833

Listed below are links to weblogs that reference Eclipse: Gracefully Loading a Heavy Plugin:

Comments

About nWire

  • nWire Logo
    Browse & visualize all code association in one extremely powerful view, quick search for methods, fields and more. Boost your coding productivity in Eclipse™.
    Watch a 4 minute demo that will change the way you look at your code.
    Visit nwiresoftware.com

Twitter Updates

    follow me on Twitter
    My Photo

    My Other Accounts

    Delicious Digg Facebook FriendFeed Google Talk LinkedIn Reddit Twitter

    AddThis Social Bookmark Button
    Blog powered by TypePad
    Member since 05/2007