Adding P2 self update to your RCP
There is a nice tutorial explaining how to convert your existing RCP to become a self updating P2 enabled RCP here: http://wiki.eclipse.org/Equinox/p2/Adding_Self-Update_to_an_RCP_Application.
First I had to change my hudson build to build a P2 enabled RCP. We use the plugin builder to configure the PDE headless build scripts. Even with the plugin builder it is far from trivial to set up a headless build. But once you get used to it it works quite well. Unfortunately the plugin builder doesn't seem to support P2 enabled builds. So I had to mess a bit around with the ant scripts. But after a day of swearing and sweating I was able to get it to work. Ok, the build now takes about twice as long as before but who cares?
Next step was to add the P2 dependencies to the product, by adding the p2.user.ui feature. This worked quite well. The RCP now is only like 30 Megabytes larger but who cares?
Next step was to add the check for update action as described in the above tutorial. This action is only about 100 lines long and uses almost exclusively internal P2 code plus it doesn't work out of the box because of this bug. But who cares?!
Now, I've increased the version number of the product, a feature and a plugin. Then I've add the location of the P2 repository which my brave little hudson builder crated as a touchpoint to the p2.inf file. For a start I've chosen to use a local repository located somewhere in my file system. All what's left is to start the old RCP and off we go with the automatic update! Yeah, whatever. It didn't work. Nothing, no update, no exception, no nothing. I've started to care!
I've played around with it, several hours, googled, read forums, read the p2 equinox wiki. I've added the P2 update UI to my RCP and realized that it actually found the update site but did refuse to update. Then I made an interesting discovery: If I created the p2 repository by exporting the product with my local eclipse install and used this repository it worked!
I assume something, no idea what, is wrong with my headless build. I thought ok, I can life with that for now: I only have to export the site every now and then. All what's left is to add the repository to some web server and point a touchpoint to the repository URL. Guess what: Didn't work! The exact same repository: If located in the file system it works, if added to a web server it doesn't. What's this good for!?
No, it doesn't work!
I had a tough night, got up at 4 o'clock in the morning and couldn't sleep no more. It was time to visit our CTO.
Our CTO is a unix hacker, he likes scripts and configuration files, he thinks that a console is a more then sufficient user interface (they even have copy paste support nowadays you know). He doesn't like frameworks and of course he hates Java. He said: Fuck that shit! You want to update your RCP? Just make your RCP download a self extracting zip file, close the RCP, execute the self extracting zip file in the install folder and start the RCP again: Voila! Know what: This sounds like a hack but there is a golden rule when writing software:
GET THINGS DONE!
And his approach does the Job. We can even update the JRE which we ship with the RCP (not like P2 that tries to delete the JRE while the JRE is still used which of course doesn't work on windows).
But self extracting zips have some drawbacks:
- We couldn't find an easy way to generate them for windows with our linux build server
- You can only add files and not delete files.
- They only work on windows (not a problem for us though)
- build windows installers with linux.
- execute various actions on install, including deleting files
- run the installer in silent mode such that the user doesn't realize that what is executed is actually an installer
- start your program after the installer has finished
- build installers for windows, linux and they say osx support is coming soon
Here is my advice: If you need to update an RCP which you control, which can not be extended by users, then do not get into the P2 businesses. That's my opinion. I know it is possible to use P2 for this and I know there are people which used it successfully. But I like solutions which I can control and understand, and P2 I can not.
In a next post I will explain a bit more in detail how we did it with the installer approach.