Sunday, June 28, 2009

All contributions are Equal, some are more equal than others

This evening I read Cay Hortmann's article on upgrading to Galileo. (For those of you who do not know Cay, he writes the fantastic Core Java books. I learned Java from the 1.1 version, as well as both the 1.4 and 1.5 versions. He writes great stuff.)

In the article he makes this comment:
There is now an option to generate toString automatically. This is something I've wanted for a long time. Unfortunately, it is not very good. Core Java gives these simple rules for toString:
  • Use getClass().getName() to print the class name. Then your toString can be inherited.
  • When you redefine toString in a subclass, first call super.toString(), then add the subclass data.
The Eclipse formatter follows neither of these eminently sensible rules. Maybe in 3.6.
I've not yet seen the toString generator, but having written more than enough toString implementations, I've worried that such a code generator may be less than ideal. Similarly, I've seen the equals and hashCode generators at work, and I also tend to not want to use them.

Given that I work for a company that has so much Java code that "If code was ice cream, it would be a lot of ice cream," [Ref Java Posse 240, 9:15] in addition to having very helpful helper methods for hashCode and equals, I'd love more finely-tuned generators for such critical methods.

But I feel a bit constrained by one of the basic rules guiding Eclipse contributions, as defined by the book Eclipse: Principles, Patterns and Plug-ins:
As the Contribution Rule reminds us, “Everything is a contribution.” And with many contributions, the possibilities are endless.
OK, so let's say I write my own generators for toString, hashCode and equals. Then there are two toString generators in the IDE, one possibly better than the other. Why should the end user be forced to deal with two confusing UI contributions?

Sure, there's also the recent object of my affections, patch fragments, but the patch fragment is a back-door lover.

I want to remove the default contributions altogether, and replace them with something better suited to my environment. But that violates the Contribution Rule. Am I stuck with something less than ideal until Eclipse 3.6, or worse, forever?

What's the solution here?

PS: Has someone picked up on Cay's concerns and logged a bug?

Friday, June 26, 2009

Lies, Damned Lies, and Eclipse Upload Statistics

Update: Added 4th assumption, Saturday, June 27

As promised, 48 hours ago I downloaded several Eclipse products across all five published platforms using Bittorrent. Now that two days have passed, and my downloads have been made available for others to upload, I thought I'd consolidate upload bittorrent upload data for the sake of gauging popularity.

Some notes on my bittorrent process:
  • I downloaded the torrent files at about 10:30pm, two nights ago. I collected the data at about 11:30pm tonight. I'm calling it 48 hours. Anyone who cares enough, call the data police.
  • I did nothing to cap bandwidth for any of these Eclipse distributions.
I collected data on both megabytes uploaded from my bittorrent client, as well as ratio of upload to download. Since all copies of my products were fully downloaded, an upload ratio of 2.5 means that virtually 2.5 copies of that distribution were uploaded from my machine. Of course bittorrent doesn't ship data in full files, it's just pieces of the distrubutions, here and there.

These are my three primary, and therefore, potentially disputable, assumptions:
  • More popular products will be uploaded by more people.
  • Upload ratios are a better measurement of popularity than megabytes uploaded. If product X is 50% larger than the size of product Y, equal bandwidth dedicated X and Y do not denote equal popularity. I just think people using bittorrent aren't really worried about the size of their Eclipse.
    • Similarly, I consider negligible any difference in compression ratios between the win32 zip file format and other gzipped tar files.
  • 48 hours of data collection is more than enough time to collect data, and taking more than the first 48-hours of data will not yield significantly different results.
    • I presume that files that are not as well seeded as others will take more time to initially download, and as such, will not contribute much to the other uploads during the first part of this process, and so may exaggerate the results slightly. Given that, I suspect the correctness of the 48-hour window will be the most disputed assumption.
  • Update: fourth assumption: People don't care about how long it takes, if they're using bittorrent. I assume it's a "set and forget" type of tool.
In retrospect, this turned out some really cool data. I'm very sorry now that I did not download all distributions. This analysis suddenly suffers from its absence.

Let's start with downloads by product:


Here, the clear winner is the JEE distribution. Modeling, which is heavily discussed on the modeling blog and had a crazy number of talks at EclipseCon, has just under 25% the popularity of JEE. I haven't used WTP in a while but I hope, if it's this popular, that the developer docs reflect the popularity. (Please?)

Next we move to downloads by operating system:


Wow, Windows, huh? That's a surprise, and also, not really a surprise. I'd love to see how these numbers compare next year. Will we see an complete inversion of Linux 32 and Linux 64 in a year? Two years? I predict four years.

Let's look at all the download ratio data without grouping by products or operating system.


This chart really highlights both the JEE and Win32 popularity. I'm pleased to see the CDT platform is well used by the Linux32 community. I wonder why, on the Classic platform, OSX Carbon is uploaded slightly more than OSX Cocoa? Are variances on that scale negligible?

I hear the Linux community say "Rob, come on. We just shut down the spin machine from that ludicrous browser comparison. How about something that reflects reality?" Reality, whatever. You punks are lucky drawing charts is fun, so I'll do one more for ya. Here's the same data, with OSX and Linux products as single pieces of data.


Seriously, this does have something more interesting to say:
  • RCP is more popular among the OSX and Linux communities than Win32.
  • Without JEE, Win32 is not nearly as popular a platform.
  • CDT and modeling are not particularly popular among the OSX community.
  • CDT is loved by the Linux users.
I mentioned earlier that downloads by megabyte are not interesting to me. That doesn't stop me from graphing it. Here's a chart:


and heck, here's another:


Do these last two charts tell you anything different from the download ratio charts? I'll leave that up to someone else to discover. Add it in the comments.

Here's the last three pieces of data I want to share tonight:
Total Uploads: 145
Total MB uploaded: 18,781.1 MB
Upload average (assuming 48 hours): 111.295 kbps
You could say, then, that 145 people got their instance of Eclipse from my bittorrent client.

Thank you, Verizon FIOS. Thank you, Eclipse Foundation!

Tuesday, June 23, 2009

Downloading Eclipse via bittorrent == community

Hi all,

Tomorrow is the big day: the public release of Eclipse 3.5, a.k.a. Galileo.

Those of us that have become Friends of Eclipse are eligible to download it today, and that's pretty damn cool. In fact, I'm eligible to download it right now. If I weren't on a train, that's exactly what I'd do.

But here's the thing: I'd rather download it with bittorrent. Why?
  • Once I've finished the download, I can participate in someone else's download by making my file available to them.
  • This means the rest of the community will have access to it faster than using a standard download.
  • Any bandwidth you contribute so someone else can download Eclipse results in less bandwidth required by the Eclipse Foundation. In other words, you're saving money for the Eclipse Foundation
  • For extra credit, you can download multiple versions of Eclipse via bittorrent, even the ones you won't use. For instance, I no longer use Microsoft Windows, but because I downloaded Eclipse 3.4.2 / win32, anyone who wants that version will get parts of it from my torrent client. And let me tell you, by watching the bandwidth statistics, that's the most popular upload in my torrent client.
  • I can start my download here, on the train.
So, please, tommorrow, download via bittorrent. And, hey, while I've got your attention: would you please make a donation to become a Friend of Eclipse?

Monday, June 22, 2009

Patch Fragments, Redux

Sorry for those of you who have already read my patch fragment blog posts. I'm re-listing them in this post for the sake of the Planet Eclipse aggregator.

In short, an OSGi fragment is a bundle that attaches to a host bundle [1]. While patch fragments really aren't meant to be use to replace behavior in a host bundle [2], it's the most elegant hackish way to do just that.


The first blog post shows that I was able to make changes to all text editors using a patch fragment.
The second blog post hosts a screencast showing, step by step, how to build a patch fragment.
The third blog post shows the code required to create the effect from the first post.

So if you're coming here from Planet Eclipse, you may find these interesting.


[1] http://static.springframework.org/osgi/docs/1.1.0/reference/html/appendix-tips.html
[2] http://wiki.eclipse.org/FAQ_Can_fragments_be_used_to_patch_a_plug-in%3F

System.err.println("Hello, Eclipse World!");

Blatherberg has just been added to the Planet Eclipse blog roll. It's just the subset of posts from Blatherberg with an "eclipse" label, which is the same as http://konigsberg.blogspot.com/search/label/eclipse.

For new Planet Eclipse readers, here's a little background: I've been a professional software engineer for almost twenty years. I started using Eclipse in 2002, and wrote my first plug-in at the end of 2006. I work for Google writing Eclipse plug-in developer tools full-time and I love it, love it, love it. If you want to learn a little bit about what my team at Google does to support our internal Eclipse users, come to Eclipse Day at the Googleplex. We'll be discussing it in one of the sessions.

The first IDE I ever used was Turbo Pascal. That was 1984. I used Turbo Pascal to write a Tetris clone called Soviet Block and a two-player sequel called Head-to-head-tris. (As far as I am aware, Head-to-head-tris was the first ever two-player Tetris variant.) After twenty five years, I still think CTRL-Y is the keystroke to delete a line. You never forget your first IDE.

Now that part of Blatherberg is federated, some of you may get my posts twice. Anyone enterprising enough can create a nice RSS filter using the superb Yahoo! Pipes.

Friday, June 12, 2009

The Code For Two Margins


OK, two posts ago I showed that I could make a double-margin in an editor using Patch Fragments. One post ago I used a screencast to demonstrate the basics of writing your own patch fragment.

In this post I will show the code for the double margin.

While in the screencast I messed with org.eclipse.core.resources, for this case, I wrote a patch fragment for org.eclipse.ui.workbench.texteditor. It's my expectation that you have read those last two posts, since I'm only a specific subset here.

First I imported the org.eclipse.ui.workbench.texteditor plug-in, and made a bundle fragment that lived off it.

In the fragment, I created the java package org.eclipse.ui.texteditor, and copied the entire source file for org.eclipse.ui.texteditor.SourceViewerDecoratorSupport from the source project to the new fragment package.

After much searching, I found the thing in SourceViewerDecoratorSupport responsible for painting the margin. It's MarginPainter. Because MarginPainter implements IPainter and PaintListener I hoped writing a delegate that implemented those interfaces would work. e.g.

class TwoColumnMarginPainter implements IPainter, PaintListener {
  private final MarginPainter delegate;

  public TwoColumnMarginPainter(...) {
    this.delegate = new MarginPainter(...);
  }

  public void initializer() {
    delegate.initialize();
  }

  ...
}

Any method defined by the interfaces would be implemented just like initialize: delegate the call to the delegate MarginPainter.

Next, I replaced all uses of MarginPainter with TwoColumnMarginPainter, a grand total of two locations:

From To
private MarginPainter fMarginPainter; private TwoColumnMarginPainter fMarginPainter;        
private void showMargin() {
...
  if (fMarginPainter == null) {
    if (fSourceViewer instanceof ITextViewerExtension2) {
     fMarginPainter= new MarginPainter(fSourceViewer);
private void showMargin() {
...
  if (fMarginPainter == null) {
    if (fSourceViewer instanceof ITextViewerExtension2) {
      System.err.println("Black Magic!");
      fMarginPainter= new
TwoColumnMarginPainter(fSourceViewer, 20)
;

The part where it prints "Black Magic!" was my cue during testing that the patch fragment was taking control of SourceViewerDecoratorSupport.

Once that worked, it was a matter of doubling up in my delegate. Here's the the final implementation of the painter, in full.

package org.eclipse.ui.texteditor;


import org.eclipse.jface.text.IPaintPositionManager;
import org.eclipse.jface.text.IPainter;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.MarginPainter;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;


public class TwoColumnMarginPainter implements IPainter, PaintListener {
  private final MarginPainter delegate;
  private final MarginPainter sibling;
  private final int offset;


  public TwoColumnMarginPainter(ITextViewer textViewer, int offset) {
    delegate = new MarginPainter(textViewer);
    sibling = new MarginPainter(textViewer);
    this.offset = offset;
  }


  // @Override
  public void setMarginRulerColumn(int width) {
    delegate.setMarginRulerColumn(width);
    sibling.setMarginRulerColumn(width + offset);
  }


  // @Override
  public void setMarginRulerStyle(int lineStyle) {
    delegate.setMarginRulerStyle(lineStyle);
    sibling.setMarginRulerStyle(lineStyle);
  }


  // @Override
  public void setMarginRulerWidth(int lineWidth) {
    delegate.setMarginRulerWidth(lineWidth);
    sibling.setMarginRulerWidth(lineWidth);
  }


  // @Override
  public void setMarginRulerColor(Color color) {
    delegate.setMarginRulerColor(color);
    sibling.setMarginRulerColor(color);
  }


  // @Override
  public void initialize() {
    delegate.initialize();
    sibling.initialize();
  }


  // @Override
  public void deactivate(boolean redraw) {
    delegate.deactivate(redraw);
    sibling.deactivate(redraw);
  }


  // @Override
  public void dispose() {
    delegate.dispose();
    sibling.dispose();
  }


  // @Override
  public void paint(int reason) {
    delegate.paint(reason);
    sibling.paint(reason);
  }


  // @Override
  public void paintControl(PaintEvent e) {
    delegate.paintControl(e);
    sibling.paintControl(e);
  }


  // @Override
  public void setPositionManager(IPaintPositionManager manager) {
    delegate.setPositionManager(manager);
    sibling.setPositionManager(manager);
  }
}

Between this post and the last one you should be able to reproduce the double-margin effect yourself. Let me know if you have any problems or interesting ideas.

Thursday, June 11, 2009

Screencast: Doing Unnatural Things with Eclipse Patch Fragments

In my previous blog post I showed screenshots of a proof-of-concept idea that took advantage of Eclipse Patch Fragments. Based on the original documentation I made this screencast to demonstrate the nuances. Enjoy.

Wednesday, June 10, 2009

Patching

Take a look at this editor window:

What do you see that's different about it? I'll tell you, there are two margin lines. Is this a new feature of the soon-to-be-released Eclipse Galileo? Did I write my own Java editor?

Nope!

I hacked Eclipse to make that second margin.

I added this because I really like having two margins: I consider the first one a 'warning track' indicator. I don't mind writing code longer than 80 characters, but will go to 100, and prefer to stay inside the warning track.

So, how did I do this? I used patch fragments. Some pages on the Eclipse wiki claim that Patch Fragments are a horrific misuse of Eclipse, and one actually taught me how to do it. (It missed one important point, though, that cost me about an hour. The page has been adjusted accordingly.)

Here's the best part, thanks to patch fragments, I was able to perform this surgery at exactly the right place. The same small piece of code (and really, this actual amount of code was shockingly small) provides two margins in any editor, such as the plain-ol text editor:

or the plug-in manifest editor.


Look, there are down-sides to doing this: if I plan to support this patch, I need to apply it with each release of Eclipse. But honestly, how likely do you think it would be for an enhancement like this to make it in to the release? Not very bloody likely.

This is purely a proof-of-concept, but I plan to finish this up and publish it as an EPL contribution.

In a subsequent blog post* I will document how I got it to work, but for now, I'll tell you: as a total hack, I changed about six lines of code in org.eclipse.ui.texteditor.SourceViewerDecorationSupport, and added a sibling class called org.eclipse.ui.texteditor.TwoColumnMarginPainter.

zx, thanks for the offer, I don't need the patch fragment tutorial! :-)

* Googlers, in the draft of this article I accidentally used "changelist" instead of "blog post". Apparently I do "subsequent changelists" a little too often. :)

Tuesday, June 09, 2009

Registration is open for Eclipse Day at the Googleplex

We've been working hard behind the scenes, but now I'm happy to report that registration is now open for Eclipse Day at the Googleplex 2009! This is a collaboration between the Google Open Source Office and the Eclipse Foundation.

Last year's Eclipse Day [videos] was a great success, and I'm happy that we're doing it again this year. Additionally, this year, my colleague Terry Parker, and I, are giving the keynote, titled Features, Deployment and Support in the Enterprise: Lessons from Google where we'll talk a bit about some of the things we've learned providing developer tools to a large base of smart users who love their tools.

It's free to attend, so register now.