Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Tuesday, February 9, 2010

OSGi Clipboard Monitor for Java (on Windows using JNA)

Before you read on you should be familiar with JNA and OSGi as I will make heavy use of it in this posting.

Preface

For my CopyTo Eclipse plugin's preference page I wanted to enable the "Paste" button for label/URL combinations only if there is some text in the clipboard (and that text can be converted to a "CopyTo" target). So I would need to monitor the content of the systems clipboard.

SWT to the rescue! ... not!

So I checked if SWT can already help me here. There should be a Clipboard.addListener method that would allow me to register a listener with the clipboard and let SWT notify me about changed clipboard content. Unfortunately there is no such functionality in SWT. And I would soon know why that is ;)

The long way... using a Windows Clipboard "Viewer"

Since I am developing on a Windows machine, I fired up the Windows SDK help to see what it offers in regard to the clipboard. There is a SetClipboardViewer function that in a somewhat awkward way let your window become part of the clipboard viewer chain. Windows will then send 2 specific messages to this windows message proc to inform it about clipboard changes (WM_DRAWCLIPBOARD) or changes in the clipboard viewer chain (WM_CHANGECBCHAIN , if someone else calls SetClipboardViewer).

The first thing that bugged me was, that I do not have a window that I could give to the function and that could receive messages from Windows. Then, I remembered my old Win32 coding days in C++ and that one can create a hidden window just for messages. Instead of creating my own window class for that I decided to use an existing one. The "STATIC" window class does not need a lot of resources and does not receive a lot of messages so its the perfect candidate. We will just create an invisible instance of such window using JNA:

viewer = User32.INSTANCE.CreateWindowEx(0, "STATIC", "", 0, 0, 0, 0, 0, null, 0, 0, null);

Then we register the window with the clipboard viewer chain according to the API specs:

nextViewer = User32.INSTANCE.SetClipboardViewer(viewer);

The next thing to do is to redirect all messages to a custom window proc instead of the default one of the "STATIC" window class. This is called "subclassing" in Windows and in a sense is something like class subclassing in the Java world. Only on a "message only" basis.

Our new window proc will handle the two clipboard related messages and redirect the other messages to the original window proc of the "STATIC" window class.

User32.INSTANCE.SetWindowLong(viewer, User32.GWL_WNDPROC, this.ourProc);

Please note that ourProc is a member field, so that the Java GC will not remove its reference and JNA would no longer be able to send messages to our callback!

Thats how the callback looks like:

class OurProc implements WNDPROC {
public int callback(HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case User32.WM_CHANGECBCHAIN:
  // If the next window is closing, repair the chain.
  if (nextViewer.toNative().equals(wParam.toNative())) {
    nextViewer = new HWND(Pointer.createConstant(lParam.longValue()));
  } // Otherwise, pass the message to the next link.
  else if (nextViewer != null) {
    User32.INSTANCE.SendMessage(nextViewer, uMsg, wParam, lParam);
  }
  return 0;
case User32.WM_DRAWCLIPBOARD:
  try {
    onChange(new ClipboardEvent(this));
  } finally {
    User32.INSTANCE.SendMessage(nextViewer, uMsg, wParam, lParam);
  }
  return 0;
case User32.WM_DESTROY:
  User32.INSTANCE.ChangeClipboardChain(viewer, nextViewer);
  break;
}
return User32.INSTANCE.DefWindowProc(hWnd, uMsg, wParam, lParam);
}

That's pretty much the code from the Windows SDK help for programming a Clipboard Viewer. There is some strange chain repairing code included. Speaking of bad API design. How easily could that break, if one programmer gets it wrong?

Polling the message queue without wasting CPU cycles

Now, for the sub-classed static window to receive any messages we need to poll the message queue. In Windows you can only poll your own threads message queue. And, important to know, Windows only creates a message queue if a thread creates a window or calls one of the message queue related functions like GetMessage or PeekMessage. So a simple message poller in our threads run() method would look like this:

while (User32.INSTANCE.GetMessage(msg, null, 0, 0)>0) {
  User32.INSTANCE.TranslateMessage(msg);
  User32.INSTANCE.DispatchMessage(msg);
}

However, GetMessage is a blocking call and so our Thread would consume all the available CPU cycles it could get until a new message arrives in the queue. That's certainly not what we want. Instead we have to create more sophisticated message queue polling logic. We also want to be able to end our clipboard monitor at any given time. We do that by signaling a special Win32 kernel event object. The MsgWaitForMultipleObjects allows us to wait for message to arrive in the queue as well as events that get signaled. So our new message polling loop that cost (almost) no CPU cycles looks like this:

final HANDLE handles[] = { event };
while (true) {
  int result = User32.INSTANCE.MsgWaitForMultipleObjects(handles.length, handles, false, Kernel32.INFINITE, User32.QS_ALLINPUT);

  if (result == Kernel32.WAIT_OBJECT_0) {
    User32.INSTANCE.DestroyWindow(viewer);
    return;
  }
  if (result != Kernel32.WAIT_OBJECT_0 + handles.length) {
    // Serious problem, end the thread's run() method!
    break;
  }

  while (User32.INSTANCE.PeekMessage(msg, null, 0, 0, User32.PM_REMOVE)) {
    User32.INSTANCE.TranslateMessage(msg);
    User32.INSTANCE.DispatchMessage(msg);
  }
}

Please note that we poll all messages out of the queue until there are no more left and only then return to another round of MsgWaitForMultipleObjects until our halt event is signaled.

That's it about the gory details of implementing such a "viewer" in Windows (without displaying anything). The hard thing to figure out was, that all user level related calls had to be made from the thread that will read out the message queue.

Why Microsoft decided to put the responsibility of a chain into the hands of the programmer is beyond me. Clearly bad API design.

Adding some spin - OSGi services

Of course when programming in Java I will always use OSGi whenever possible. The Clipboard Monitor is no exception. Granted, the whole code can be used without OSGi too. But then you would have to implement a kind of listener management yourself. That's up to the reader of this entry and I welcome everyone to contribute a plain old Java implementation of AbstractWindowsClipboardMonitor that integrates hand crafted listener management instead of using the OSGi service registry.

So there is a monitor component that will consume ClipboardListener services registered in the system and inform them about changes in the clipboard.

Listener that publishes an event using the EventAdmin

Now we can have a fairly simple listener that publishes an event on every clipboard change:

public class EventAdminClipboardListener implements ClipboardListener {
  private static final String TOPIC = "clipboard/monitor/event"; //$NON-NLS-1$

  private final AtomicReference ref = new AtomicReference();

  protected void bind(EventAdmin eventAdmin) {
    ref.set(eventAdmin);
  }

  protected void unbind(EventAdmin eventAdmin) {
    ref.compareAndSet(eventAdmin, null);
  }

  public void onEvent(ClipboardEvent event) {
    EventAdmin eventAdmin = ref.get();
    if (eventAdmin != null) {
      eventAdmin.postEvent(new Event(TOPIC, (Map) null));
    }
  }
}

Pretty simple.

The SWT Clipboard Listener service

Then we have this listener service that will examine the content of the clipboard and use the OSGi EventAdmin to publish specialized events with topics describing the content of the clipboard. EventHandler services can so easily react on specific changes in the clipboard. The following event topics are currently implemented:

  • clipboard/monitor/swt/TEXT
  • clipboard/monitor/swt/URL
  • clipboard/monitor/swt/IMAGE
  • clipboard/monitor/swt/RTF
  • clipboard/monitor/swt/HTML
  • clipboard/monitor/swt/FILE

So you could register an EventHandler that reacts on changes in the clipboard, and only if the new clipboard content contains (also) text. Your EventHandler service would register with the topic set to "clipboard/monitor/swt/TEXT". The beauty of this componentized approach is that you do not even have to know that there is a clipboard monitor installed and running in the system. You have no dependencies on it. You simply register for events of a specific topic and get informed about changes. You can then use SWT to read out the clipboard.

Conclusion

I hope this rather lengthy posting gave you another clue what can be done using clean OSGi component design. And maybe some of you can even put the components to some use in your own projects. It's all licensed under EPL 1.0 so feel free to use the code.

Here you can watch a little video demonstration (if you cannot see the video below).

Code at GitHub

You are invited to check out the full source code over at GitHub and you are invited to fork/clone and contribute, if you want. Maybe someone can add a GTK/Linux clipboard viewer?

Friday, February 5, 2010

P2 error messages are useless - for users and for me as a programmer

I handed out the update site URL of my "copyto" Plug-in to a friend and when he wanted to install it, p2 threw this message at him:
Cannot complete the install because one or more required items could not be found. Software being installed: codepad.org support 0.1.0.201002050243 (eclipseutils.ui.copyto.codepad.feature.feature.group 0.1.0.201002050243) Missing requirement: eclipseutils.ui.copyto 0.1.0.201002050243 requires 'package org.eclipse.core.runtime.preferences 3.3.0' but it could not be found Cannot satisfy dependency: From: codepad.org support 0.1.0.201002050243 (eclipseutils.ui.copyto.codepad.feature.feature.group 0.1.0.201002050243) To: eclipseutils.ui.copyto 0.0.0
I would guess that there is at least one package with the name "org.eclipse.core.runtime.preferences" installed and it would be very helpful if p2 prints out the available versions of that package. That would have made it easier for me to recognize, that 3.3.0 is obviously an Eclipse 3.6 package (I am using the I-Build as my target). Beside that, this error message displayed to a non-programmer is equally useless. It's filled with cryptic numbers and too much information the average user cannot understand. Heck, I do not even understand it and then it's also missing crucial information for me as a programmer. I filed a bug to get at least the required information into the error message.

CopyTo...Pastebin (and others) Plug-In for Eclipse

I am currently working on a small Plug-In that some of you might find useful (especially if you are hanging out in IRC a lot). The plugin allows you to select resources, classes or methods in Java projects and posts them to your favorite pastebin. After that it provides the URL of the pastebin entry in your clipboard so you can easily send it to others. This little video demonstrates this: Some pastebins allow the user to specify additional options when posting. This will be covered when the user helds down the "CTRL" while selecting the menu entry. A dialog is then display where the user can adjust such options. Likewise he could change the content type of the pasted text, if the automatic detection failed. The Plug-In will be released under EPL 1.0 and the source will be up at github. Now, if anyone of you have a nicer name for the Plug-In, I would like to replace the rather generic "CopyTo" (Pasty?). The Plug-In is very easily extensible with new pastebin providers. In fact all current providers are supplied via Fragement-Bundles that basically just add their menuContribution the the CopyTo menu. There is support for the usual redirect based pastebins, as well as ones that send back JSON. Additional response handlers can be easily plugged in (SOAP *yikes*) and additional JSON helpers, that extract the new location URL component from a JSON response are queried using the Eclipse IAdapterManager. Currently there is only support for copying JDT elements (Classes, Methods) but other sources of "Copyable" content can be also plugged in via Adapters. I also plan to provide a "History" view of pastes that allows you to copy the URL again into the clipboard at any time.

Thursday, February 4, 2010

Enterprise OSGi does not make JPA more dynamic

I just browsed the draft version of the new OSGi specs for the enterprise. I was especially interested in how they want to address the JPA related problems. They have not chosen a fundamentally different path than I've been doing JPA development in OSGi for 2 years now. Difference is, they propose a new interface (PersistenceUnitProvider) to be registered for each persistence unit while I was just registering an EntiyManagerFactory with the "pu-name" service property. So every interested service could directly bind to a specific EntityManagerFactory and create its EntityManager from it. So far so good. I was surprised however, that the OSGi specs do not address the main issue with JPA. It's static. You can not add/remove entities dynamically. It was never designed that way and the OSGi enterprise will not solve that issue. You still have to specify all entities up front in the dreaded persistence.xml. Yet, the more OSGi way would be to skip that file altogether, have the name of the persistence unit name as service property (unit.name) of the PersistenceUnitProvider and let the PUP consume entity beans (exported as java.lang.Object services) with their "unit.name" specifying their target unit. The PersistenceUnitProvider would then have to parse the beans annotations and incorporate it into its EntityManagers. I am aware of the big problems that can bring with it. What if there are currently transactions running? Does removing an entity from the system also mean to clean up the database? The JPA implementation would have to rebuild its internal state and caches on entity changes. I had hopes the OSGi enterprise spec would address those issues of non-dynamically of current JPA implementations. So even with this new spec, not much is going to change how I program JPA. It will still not be possible to add new business logic to a running OSGi system without touching the persistence.xml.

Tuesday, January 12, 2010

Notification Listeners

To let other components in the system know about displayed notifications we use the White-Board-Pattern to consume listener services in our NotificationServiceImpl class. A listener for notifications has a very easy interface:
public interface NotificationListener extends EventListener {
  void onEvent(NotificationEvent event);
}
It extends the default Java (empty) EventListener base interface and contains a single method. This single method and its associated event object allows us to extend the kind of events we can publish without changing the interface for each new event like "Show" or "Hide". For now we will only publish "Show" events. But if in the future we decide to also notify listeners about the close/hide of a notification popup we would have to add another method to the interface "onHide" and breaking the API somehow. Using an event object we can put the type of the event inside the event object and the client would then have to decide what to do for each event type. It would still only implement a single method "onEvent" instead of having to implement a new method for each new event type such as "onShow" or "onHide". The event object itself looks like this:
public class NotificationEvent extends EventObject {
private static final long serialVersionUID = -8633958140848611658L;

private Notification notification;

private NotificationEventType type;

public NotificationEvent(NotificationService source, Notification notification, NotificationEventType type) {
  super(source);
  this.notification = notification;
  this.type = type;
}

public Notification getNotification() {
  return notification;
}

public NotificationEventType getType() {
  return type;
}
}
The event type is an enum:
public enum NotificationEventType {
Show
}
The NotificationServiceImpl is only slightly changed:
Object listeners[] = context.locateServices("NotificationListener"); //$NON-NLS-1$
if (listeners != null) {
 NotificationEvent event = new NotificationEvent(this, notification, NotificationEventType.Show);
 for (Object listener : listeners) {
   try {
     ((NotificationListener)listener).onEvent(event);
   } catch (Throwable e) {          
   }
 }
}
Right before we display the notification we get all the NotificationListener registered in the OSGi system and (safely) call their onEvent method. There are several ways to get the list of currently registered NotificationListener services. One way is to use the BundleContext.getServiceReferences(String, String) method. But this would involve getting the service object ourself and not forget to "unget" it also. Another way is to use a ServiceTracker. But since our implementation already is a Component with bindings we can just add a new binding to our service component definition XML:
<reference cardinality="0..n" interface="ui.notification.NotificationListener" name="NotificationListener" policy="dynamic"/>
We then use the ComponentContext object to get an array of services that could be bound to "NotificationListener" (as named in the component XML). This context we get from OSGi in a new protected method:
protected void activate(ComponentContext context) {
 this.context = context;
}
That's all for notifying listeners about notification display. We can now create a simple new bundle that will register a NotificationListener into the system and simply System.out.println the notifications data.
public class SysoutNotificationListener implements NotificationListener {

  public void onEvent(NotificationEvent event) {
    if (event.getType() == NotificationEventType.Show) {
      System.out.println(event.getNotification().getTitle() + ": " //$NON-NLS-1$
          + event.getNotification().getMessage());
    }
  }
}
Its component definition would look like this:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="ui.notification.listener.sysout">
 <implementation class="ui.notification.listener.sysout.internal.SysoutNotificationListener"/>
 <service>
    <provide interface="ui.notification.NotificationListener"/>
 </service>
</scr:component>
Pretty simple. Here is what the result looks like: Listeners could also be used to log a history of notifications in various ways. In the next chapter of this series we will develop a View for Eclipse RCP apps that logs a history of notifications in a table.

Thursday, December 17, 2009

Displaying OSGi bundle informations in the Windows Explorer

I am currently working on a small Windows Shell Extension that will help to get a quick overview on all the OSGi bundles in the currently browsed folder.



The following features will be supported:

  • Detail columns for all bundle headers
  • Additional Property sheet for bundle files and unpacked bundle folders
  • Overlay icons to display various informations: if the bundle has Service Components, is a fragment or a normal bundle
  • Tooltips with the most important bundle headers
The extension can already read out the default Bunde-l10n. However there is no support for reading out the l10n matching the current Windows locale yet. In the future I plan to support Windows Search 4 and Vista and allow them to find bundles based on their OSGi manifest. I will upload the extension soon to github and everybody is invited to provide feedback. The source package will include documented classes and unit-tests (using googletest) maybe I will create a small tutorial about this later.

Wednesday, December 16, 2009

Notification Framework

In this series of tutorials I will describe a small, extensible notification framework for JFace/Eclipse applications. I will make heavy use of OSGi services and Eclipse Extensions. So before you continue to read, I suggest you make yourself familiar with those concepts to be able to follow the series.
  1. Basic Notification Service
  2. Notify listeners about notifications
  3. Showing all notifications in a view
  4. Notifications via OSGi EventAdmin
  5. Adding links to notifications
  6. Let the notify console command quote "The Big Lebowski" from the IMDB with links
  7. Declarative colour customization for Notifications
  8. Add preferences which notifications should be shown
  9. Showing notifications after a "copy" command was executed
There is git repository accompanied with this tutorial series. You can clone it directly from git://github.com/pke/Notifications.git

Inspiration

The inspiration for using notifications in my own programs came from Mylyn that shows neat little notifications upon changes in the watched buglists. I was further inspired by the great blog post over at Hexapixel: Creating a Notification Popup Widget. We will use this widget as the base of this tutorial series.

Creating the service

First we create a simple service interface for our NotificationService. Its intentionally simple and does not contain any query methods to enumerate notifications or such. It simply provides a method to show a single notification. But as you will see in the course of this series that's enough to drive a powerful notification system. So the interface will look like this:
public interface NotifyService {
 /**
  * Shows a notification. Re-arranges already visible notifications.
  *
  * @param notification
  */
 void show(Notification notification);
}
For the Notification interface itself we will use JFace's IMessageProvider as a base as it provides already a message text and type for our notification. All that is left is a title. So our Notification interface looks pretty simple too:
interface Notification extends IMessageProvider {
 /**
  * @return the title of this notification or null if none.
  */
 String getTitle();
}
Thats basically all we need for a simple notification. As the base for the implementation of our Notification Service we will use Hexapixel's code for now. That makes the implementation of the NotificationService really simple:
public void show(final Notification notification) {
  if (notification != null) {
    Display.getDefault().asyncExec(new Runnable() {
      public void run() {
        NotificationType type;
        switch (notification.getMessageType()) {
        case IMessageProvider.WARNING:
          type = NotificationType.WARN;
          break;
        case IMessageProvider.ERROR:
          type = NotificationType.ERROR;
          break;
        default:
          type = NotificationType.INFO;
          break;
        }
        NotifierDialog.notify(notification.getTitle(), notification.getMessage(), type);
      }
    });
  }
}
I only modified the original NotifierDialog class so that it no longer requires an active shell for operating. There is one more little thing we also need to do, to actually see the notification on screen. We need a thread that polls the SWT message loop. This is usually done for us when we run inside the Eclipse workbench, but since we are going to test this notification framework in an OSGi environment (for now) we need a thread that polls the SWT message loop for us. The code is also inside the NotificationService component implementation:
Runnable runnable = new Runnable() {
  public void run() {
    while (!Display.getDefault().isDisposed()) {
      if (!Display.getDefault().readAndDispatch()) {
        Display.getDefault().sleep();
      }
    }
  }
};
new Thread(runnable, "SWT").start();

Equinox Console Command to show notifications

Basically we have everything in place now to show notifications programmatically. We can have other components use our notification service to display messages. So we will create a console command for the Equinox OSGi console and implement a simple CommandProvider. It will expose the command "notify" to the Equinox console if you start the OSGi configuration with the "-console" command. The notify command will take at least one parameter, which will be the notifications message. If you specify another parameter, then this will become the notifications title. Otherwise a default title is choosen.
public class NotifyCommand implements CommandProvider {

 NotificationService service;

 protected void activate(ComponentContext context) {
   service = (NotificationService) context.locateService("NotificationService");
 }

 public void _notify(CommandInterpreter ci) {
   final String message = ci.nextArgument();
   if (null == message) {
     ci.println("You need to specify a message");
     return;
   }
   String title = ci.nextArgument();
   if (title == null) {
     title = "Notification";
   }
  
   final String finalTitle = title;
   service.show(new Notification() {
     public String getTitle() {
       return finalTitle;
     }
    
     public String getMessage() {
       return message;
     }

     public int getMessageType() {
       return IMessageProvider.INFORMATION;
     }
   });
 }

 public String getHelp() {
   return "--- Notification ---\n\tnotify message [title]";
 }
}

Create the component definitions

All that is left to make those 2 services run as Declerative Services is to create the required component XML files in /OSGI-INF/. For the NotificationService it looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="ui.notification.NotificationService">
  <implementation class="ui.notification.internal.NotificationServiceImpl"/>
  <service>
     <provide interface="ui.notification.NotificationService"/>
  </service>
</scr:component>
And for the NotifyCommand it looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="ui.notification.NotifyCommand">
  <implementation class="ui.notification.command.internal.NotifyCommand"/>
  <service>
     <provide interface="org.eclipse.osgi.framework.console.CommandProvider"/>
  </service>
  <reference cardinality="1..1" interface="ui.notification.NotificationService" name="NotificationService" policy="static"/>
</scr:component>

Run configuration

To run this we create an OSGi run configuration and add the following bundles to it:
  • ui.notification
  • ui.notification.command
  • org.eclipse.osgi
  • org.eclipse.osgi.services
  • org.eclipse.equinox.ds
  • org.eclipse.equinox.util
  • org.eclipse.equinox.common
  • org.eclipse.core.commands
  • org.eclipse.swt
  • org.eclipse.swt.win32.win32.x86
  • org.eclipse.jface
Make sure the org.eclipse.equinox.ds bundle is started, as well as our two ui.notification* bundles. If we start the configuration now, we will be able to type: notify "Hello World" and see a notification coming up at the right bottom of our primary screen as seen in this video: That's all for now. Stay tuned for the next part where we will notify listener services about notifications using the White-Board pattern. Feedback is always welcome, especially about how to poll the SWT message loop in OSGi apps.

Source:

Check out the source code at github or clone directly from git://github.com/pke/Notifications.git

Tuesday, December 15, 2009

Toggle Commands that toggle other contributions

Introduction

This is a follow up to Commands Part 6: Toggle & Radio menu contributions of fellow blogger Prakash G.R.. He described how to use command toggle and radio states. Here I will show you how to drive other contributions in the Eclipse Workbench using a toggle command.

What we want to achieve

I needed to show another toolbar button when a certain toggle command was executed. Imagine something like "Show clock" that will show or hide a little clock in the worbench window status bar. Such contribution can be easily added using a menuContribution for the trim area. First create a toolbar in the trim area and then contribute controls/commands to this toolbar also using the menuContribution extension point. Since we want the clock contribution
<menucontribution locationuri="toolbar:mytoolbar">
<control class="test.ui.clocl.internal.ClockControlContribution" id="test.ui.clock">
<visiblewhen checkenabled="false">
<with variable="activeWorkbenchWindow">
  <test args="test.ui.clock.ToggleCommand"
    forcepluginactivation="true"
    property="org.eclipse.core.commands.toggle"
    value="true"/>
</with>
</visiblewhen>
</control>
</menucontribution>
That will create a toolbar contribution that is only visible when the test.ui.clock.ToggleCommand is in the "true" state, when its checked. Lets define the command:
<command defaulthandler="org.eclipse.core.commands.extender.ToggleCommandHandler" id="test.ui.clock.ToggleCommand" name="Show clock">
<state
class="org.eclipse.ui.handlers.RegistryToggleState:true"
id="org.eclipse.ui.commands.toggleState">
</state>
</command>
How this command works and what the state is you have already read in Prakash's blog entry. The default handler for this command does a little more than the one in the latter mentioned blog entry. It is defined like this:
/**
* Generic command that toggles the executed command and re-evaluates property testers for the
* org.eclipse.core.commands.toggle property.
*
*/
public class ToggleCommandHandler extends AbstractHandler {

public Object execute(final ExecutionEvent event) throws ExecutionException {
HandlerUtil.toggleCommandState(event.getCommand());
final IWorkbenchWindow ww = HandlerUtil.getActiveWorkbenchWindowChecked(event);
final IEvaluationService service = (IEvaluationService) ww.getService(IEvaluationService.class);
if (service != null) {
  service.requestEvaluation("org.eclipse.core.commands.toggle");
}
return null;
}
}

How to toggle the visibility of the clock contribution

The connection between toggling the command and making the clock contribution visible is hidden in a property tester, that the clock contribution uses:
public class CommandsPropertyTester extends PropertyTester {
public static final String NAMESPACE = "org.eclipse.core.commands"; //$NON-NLS-1$
public static final String PROPERTY_BASE = NAMESPACE + '.';
public static final String TOGGLE_PROPERTY_NAME = "toggle"; //$NON-NLS-1$
public static final String TOGGLE_PROPERTY = PROPERTY_BASE + TOGGLE_PROPERTY_NAME;

public boolean test(final Object receiver, final String property, final Object[] args, final Object expectedValue) {
if (receiver instanceof IServiceLocator && args.length == 1 && args[0] instanceof String) {
  final IServiceLocator locator = (IServiceLocator) receiver;
  if (TOGGLE_PROPERTY_NAME.equals(property)) {
    final String commandId = args[0].toString();
    final ICommandService commandService = (ICommandService)locator.getService(ICommandService.class);
    final Command command = commandService.getCommand(commandId);
    final State state = command.getState(RegistryToggleState.STATE_ID);
    if (state != null) {
      return state.getValue().equals(expectedValue);
    }
  }
}
return false;
}
}
It is defined in plugin.xml like this:
<propertytester
class="org.eclipse.core.commands.extender.internal.CommandsPropertyTester"
id="org.eclipse.core.expressions.testers.CommandsPropertyTester"
namespace="org.eclipse.core.commands"
properties="toggle"
type="org.eclipse.ui.services.IServiceLocator"/>
That means we define a new property for the namespace "org.eclipse.core.command" and the property is named "toggle". It will operate on IServiceLocator variables. Such variable that is an IServiceLocator is the "activeWorkbenchWindow" variable. Now you should understand the visibleWhen expression of the clock contribution. It should be only visible when the toggle for the clock toggle command is "true". The re-evaluation of the property testers is triggered by the generic ToggleCommand.

A little tip at the end

If you put the ToggleCommand and property tester in a seperate bundle for easier re-use in all your projects and other bundles make sure you either start the bundle at the beginning or set the "test" expressions "forcePluginActivation" to true to let the Eclipse expression framework activate the bundle for you. Otherwise the property tester is completly ignored and the clock would be always visible.

Bonus

Since the state of the toggle is preserved in an instance preference value, the visibility of all associated contributions that use the property tester to check for the toggle state of the command is as well. Of course you can also reverse the test expression for your contributions if you have a toggle command that says something like "Hide clock".

Sunday, December 13, 2009

Using JNA to query power status on Windows CE device - with a crash

Introduction

I am using the wonderful JNA library to use the Microsoft Remote API (RAPI) to access Windows Mobile Devices on Windows desktops. It allows you to connect to an attached mobile device using ActiveSync. This works all wonderfully easy thanks to the JNA library. I do not need to write any JNI code anymore. The RAPI offers a method to query the power status of the device which is somewhat limited. It does not return more detailed information about the battery type or voltage. There is a function available in the WinCE devices own libraries (coredll.dll) that allows me to query such informations (GetSystemPowerStatusEx2).

How to call methods directly on the device

To call a method on the device that is not exposed by RAPI itself, you can use the CeRapiInvoke function. So I implemented the following function according to the RAPI specs:
EXTERN_C int __declspec(dllexport) GetPowerInfos(DWORD cbInput, BYTE* pInput, DWORD* pcbOutput, BYTE** ppOutput, LPVOID pStream) {

 *pcbOutput = sizeof(SYSTEM_POWER_STATUS_EX2);
 *ppOutput = (SYSTEM_POWER_STATUS_EX2*)LocalAlloc(LPTR, *pcbOutput);

 return GetSystemPowerStatusEx2(*ppOutput, *pcbOutput, FALSE);
}
The spec requires to LocalAlloc the memory you return. The caller of CeRapiInvoke must then LocalFree the output memory. Now, you may wonder how that can work?

Memory management in CeRapiInvoke

The way I understand how it works is like this: For the pInput parameter you have to call LocalAlloc on the Windows machine and CeRapiInvoke will copy the content of this memory block into a newly created WindowsCE readable block of memory and hand it over to GetPowerInfos function as pInput. It is of course not the same memory pointer that I handed in on the Win32 side, it just contains the same data as I handed in. CeRapiInvoke also calls LocalFree on the pInput that I handed in. The same way around with the ppOutput parameter. I have to allocate it using LocalAlloc on the WindowsCE device. CeRapiInvoke will then copy the content of my returned buffer into a desktop process accessible block of memory that it allocates with LocalAlloc on the Windows machine. I, the caller of CeRapiInvoke am then responsible for calling LocalFree on the ppOutput that CeRapiInvoke created for me. Thats the theory. Lets see how to get the returned ppOutput into the Java world using JNA.

Calling CeRapiInvoke from Java using JNA

We define this prototype in our JNA library interface for RAPI.
public interface Rapi extends W32API {

    static Rapi instance = (Rapi) Native.loadLibrary("rapi", Rapi.class, DEFAULT_OPTIONS); //$NON-NLS-1$

    HRESULT CeRapiInvoke(String dllPath, String functionName, int cbInput, Pointer pInput, IntByReference outBuffer, PointerByReference outBufferSize, PointerByReference ppIRAPIStream, int dwReserved);
}
We also declare the SYSTEM_POWER_STATUS_EX2 structure:
static class SystemPowerStatusEx extends Structure {
 public SystemPowerStatusEx() {
 }

 protected SystemPowerStatusEx(final Pointer p) {
  super(p);
 }

 public byte ACLineStatus;
 public byte BatteryFlag;
 public byte BatteryLifePercent;
 public byte Reserved1;

 public int BatteryLifeTime;
 public int BatteryFullLifeTime;
 public byte Reserved2;
 public byte BackupBatteryFlag;
 public byte BackupBatteryLifePercent;
 public byte Reserved3;
 public int BackupBatteryLifeTime;

 public int BackupBatteryFullLifeTime;
}

class SystemPowerStateEx2 extends Structure {
 public SystemPowerStateEx2(final Pointer p) {
  super(p);
  read();
 }

 public SystemPowerStatusEx base;

 public int BatteryVoltage;
 public int BatteryCurrent;
 public int BatteryAverageCurrent;
 public int BatteryAverageInterval;
 public int BatterymAHourConsumed;
 public int BatteryTemperature;
 public int BackupBatteryVoltage;
 public byte BatteryChemistry;
}
Now we can call our DLLs exported function:
final PointerByReference outBuffer = new PointerByReference();

try {
 final IntByReference outBufferSize = new IntByReference();
 Rapi.instance.CeRapiInvoke("powerex.dll", "GetPowerInfos", 0, null, outBufferSize, outBuffer, null, 0);
 return new SystemPowerStateEx2(outBuffer.getValue());
} finally {
 Kernel32.INSTANCE.LocalFree(outBuffer.getValue());
}
This code has been simplified and usually contains return value checking and error handling. However it returns the power infos we would suspect. I also ommited the initialization of RAPI here.

The LocalFree crash problem

Calling this in a loop will eventually lead to an Access Violation and a crash of the VM. If I comment out the LocalFree call in the finally block, the program runs for hours. But it then leaks memory of course. I have played with different output parameters, pointer handling and more. Without finding a solution to the crashes. Enabling JNAs own VM crash protected reveals, that it sometimes causes an Access Violation inside the native code. It almost seems like the native code overwrites some memory internally. Most likely inside RAPI itself. However calling the same remote function from a C++ Win32 program in a loop does not cause any memory corruption or crash. I hope someone of the community has maybe an idea whats going on here? If not, you got at least a short introduction on how to use JNA and the Microsoft RAPI ;)

Monday, December 7, 2009

Allow contributions to Forms

Introduction

Each Form has a toolbar associated with it, as you probably already know. You can get it by calling form.getToolBarManager(). Once you got the manager you can add your own contribution items or (legacy) actions to it. But what if you could allow other bundles/developers to add contributions to your forms toolbar too? There exists already an extension point that allows adding of contributions to menus and toolbars. You most likely used it already to customize your popup menus or your RCP applications main menu.

How to implement

The menuConstribution extension point works in conjunction with the IMenuService. This service allows you to put matching contributions into any ContributionManager. It respects the current workbench evaluation state so contributions with expressions are carefully evaluated before they are added to the ContributionManager. The menu service also takes care of enabling the contributions and manages their visibility dynamically. Basically all that you already know from addin contributions to the various Eclipse menus and toolbars. To get the contributions you are interested in, you first have to decide on a menu URI schema that identifies contributions for your form. We should follow the Eclipse Schema and define "form:" as our new schema and the following parameter is the ID of the form. The ID can be anything and you as a programmer decide for each form that you create what its ID should be. A common way I use is, if the form is embedded into a ViewPart, to use the ViewPart.getSite().getId() method. So I would call
menuService.populateContributionManager(toolbarManager, "form:"+getSite().getId());

Cleanup

You have to remember to release the contributions when your form is disposed or otherwise the IMenuService will continue to track your contributions and waste time as well as resources. So be a good contribution citizen and call menuService.releaseContributions(toolbarManager) and also toolbarManager.dispose()to allow it to clean up its resources. I recommend using a DisposeListener on the form to perform the cleanup.

Extension: Allow contributions to any form

Much like you can add contributions to the global popup menu using the "popup:org.eclipse.ui.popup.any" we can define our new "form:org.eclipse.ui.form.any" URI that allows contributions to be added to each forms toolbar.
ContributionHelper.contributeTo(toolbarManager, "form:" + getSite().getId(), "form:org.eclipse.ui.form.any");


  
    
    
  


/**
* Adds menu contributions to a {@link ContributionManager} using the
* {@link IMenuService}.
*
* @param contributionManager
* @param locations
*            The format is the Menu API URI format.
*/
public static void contributeTo(final ContributionManager contributionManager, final String... locations) {
final IMenuService menuService = (IMenuService)PlatformUI.getWorkbench().getService(IMenuService.class);

for (final String location : locations) {
 menuService.populateContributionManager(contributionManager, location);
}
contributionManager.update(false);
}

Thursday, July 23, 2009

How to replace the default JFace message icons

We all know the standard JFace icons very well. They appear in Dialogs, Wizards and Forms.

And in a form they look like this:

Now, there is a quick and easy way to replace them with your own icons if you like.

You just have to create a Fragment bundle and set org.eclipse.jface as its Bundle-Host. In your fragment bundle you include the icons you want to replace in the following folder structure:
Don't forget to add the icons folder and all of its subfolder and content into your build.properties file:
bin.includes = META-INF/,\
             .,\
             OSGI-INF/,\
             icons/
Interesting fact: You can replace the JFace icons with PNGs too. You can just rename them to have the .GIF extensions. The image file loader of SWT does not care about the extension but analyses the content of the file.