I’ve been working with Gmail using javamail library for a long time now, the standard IMAP/SMTP capabilities were quite enough, even to deal with the labels. But recently I decided to also pull the gmail custom attributes: X-GM-THRID and X-GM-LABELS (see Gmail Imap Extensions).

At first it looked like there was no easy way to fetch those custom attributes using the standard javamail FetchProfile mechanism so I went searching in Google.

I found the  java-gmail-imap project which was quite encouraging but after studying it more I figured that I did want to use it:

  1. It incorporated javamail 1.4.4 and I really needed some new 1.5.x functionality
  2. A lot of original javamail classes if not all were extended/re-written which seemed like an overkill
  3. Last release was on Mar 23, 2012

So I went exploring further.

I must say that I really do appreciate that so much code these days is open source. Both java-gmail-imap and javamail sources showed me what was really happening under the hood and I came up with a simpler hack which only requires one extended class.

I’ll explain the hack here and if you want my code let me know.

So, for a list of messages that I am reading from Gmail I now do a standard javamail profile fetch:

folder.fetch(msgs, stdFetchProfile);

followed by my custom fetch using IMAPFolder’s doCommand():


final MessageSet[] mSets = MessageSet.createMessageSets(mns);
((IMAPFolder) folder).doCommand(new IMAPFolder.ProtocolCommand() {

	@Override
	public Object doCommand(IMAPProtocol p) throws ProtocolException {
		try {
			Response[] r = p.fetch(mSets, "X-GM-LABELS X-GM-THRID");
			for (int i = 0; i < r.length; i++) {
				if (!FetchResponse.class.isInstance(r[i]))
					continue;

				// Got a FetchResponse.
				GmailFetchResponse gfr = new GmailFetchResponse(
								((FetchResponse) r[i]).toString());
				// Use gfr.getNumber() to get the msg number
				for (int j = 0; j < gfr.getItemCount(); j++) {
					Item item = gfr.getItem(j);
					if (X_GM_LABELS.class.isInstance(item))
						// get the labels
						((X_GM_LABELS) item).x_gm_labels);
				}
			}
		} catch (ProtocolException e) {
			logError(e.getMessage(), e);
		}
		return null;
	}
});

GmailFetchResponse is the class I had to create by extending Javamail’s Response. It’s aware of the X-GM-* attributes and I make it re-parse the response received in the standard FetchResponse. I used only the required part of the java-gmail-imap’s parse() method:

private void parse() throws ParsingException {
		skipSpaces();
		if (buffer[index] != '(')
			throw new ParsingException(
					"error in FETCH parsing, missing '(' at index " + index);

		Vector v = new Vector();
		Item i = null;
		do {
			index++; // skip '(', or SPACE

			if (index >= size)
				throw new ParsingException(
						"error in FETCH parsing, ran off end of buffer, size "
								+ size);

			switch (buffer[index]) {
			case 'X':
				if (match(X_GM_MSGID.name)) {
					index += X_GM_MSGID.name.length;
					i = new X_GM_MSGID(this);
				}
				if (match(X_GM_THRID.name)) {
					index += X_GM_THRID.name.length;
					i = new X_GM_THRID(this);
				}
				if (match(X_GM_LABELS.name)) {
					index += X_GM_LABELS.name.length;
					i = new X_GM_LABELS(this);
				}
				break;
			default:
			}
			if (i != null)
				v.addElement(i);
		} while (buffer[index] != ')');

		index++; // skip ')'
		items = new Item[v.size()];
		v.copyInto(items);
	}

X_GM_LABELS* classes I copied from java-gmail-imap project, they’re very simple. I only added required UTF-7 conversion:

public class X_GM_LABELS implements Item {

	static final char[] name = { 'X', '-', 'G', 'M', '-', 'L', 'A', 'B', 'E', 'L', 'S' };
	public int seqnum;

	public String[] x_gm_labels;

	public X_GM_LABELS(GmailFetchResponse r) throws ParsingException {
		seqnum = r.getNumber();
		r.skipSpaces();
		x_gm_labels = r.readAtomStringList();
		if (x_gm_labels != null)
			for (int i = 0; i < x_gm_labels.length; i++)
				try {
					x_gm_labels[i] = new String(
							x_gm_labels[i].getBytes("US-ASCII"),
							"X-MODIFIED-UTF-7");
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
					break;
				}
	}
}

That is all. With one additional custom fetch call (which is not a huge overhead) you have read the Gmail attributes for your messages.

I hope this can be useful for others.

-Alexey

Desktop Disadvantage

November 24, 2010

Mobile applications flourish, and it makes a desktop UI developer jealous. Desktop applications are supposed to have more system resources: big screen size, full-sized keyboard, a mouse, and a fast CPU.  So what?  Two decades after a mouse became widely available it’s still considered an optional device on a desktop. The same applies to every other aspect: screen resolutions vary from 1024×768 to 1920×1200, and screen sizes vary from 10” to 30”. This directly affects user feedback. When recently I made an app that used 48×48 icons, I had complaints that the icons are too big. Come on, iPhone 3 icons are 57×57, and iPhone 4 icons are 114×114! On a desktop, we are still mastering the techniques of making readable 16×16 icons. Another thing I am jealous of is touch gestures. Zooming and scrolling is just natural in touch-screen UI. On a desktop, we have ugly scrollbars and primitive non-standardized zoom controls. Desktop apps must be 5 times cooler than mobile apps because they have 5 times more resources! It’s time to reevaluate the window-based concept of desktop UI. It’s not user’s job to move windows around.

App integration also deserves mentioning. There is no simple cross-platform app integration mechanism on a desktop. Software installation, upgrades, and removal is a pain that users shouldn’t deal with. It’s one of the reasons, I think, why web applications ate the market share of desktop apps. Java and Flex try to address this problem but they have a long way to go. Clearly, it’s the OS to blame here. Linux, Windows, Mac OS all suffer from these issues. I hope the wisdom of iPhone and Android will rub on a desktop someday.

I discovered Quercus (PHP in Java) a while back and have become quite a fan of the solution. Of cause, one thing is that I personally have shifted to Java from PHP and prefer Java to any interpreting language these days (and that is after having developed the whole Yoxel open source project in PHP) but aside this bias my main reason is “ease of deployment”.

It is sometimes tricky to install PHP software packages because standard PHP configuration that you have on your system may not be enough. For example, Yoxel, depending on the configuration, may require LDAP (–with-ldap), IMAP (–with-imap), JPEG/FREETYPE/PNG (–with-freetype-dir, –with-jpeg-di, –with-png-dir). All that may require custom compilation of PHP itself (and even additional libraries) and complicates life for the person installing the package. I am actually pretty sure many users simply give up because they did not want to compile their PHP from scratch.

With Quercus/Java this problem would be solved. I, as a producer of the software package, can throw all necessary jars into my WAR (including the quercus.jar) and the WAR is ready to be deployed in your app server. No re-compilation of anything required!

One could go even one step further and embed jetty http server in the package then the end user simply starts the app on a port and it runs. No app server is even required! Isn’t this great?

Of cause I have also discovered that some of the 3rd party modules that we use are not working under Quercus so we would have to throw them away and use JVM’s functionality instead. Some rewriting on our side would have to happen if we wanted to keep the full functionality of our software (not much though). But that is probably only better, the package would be leaner.

Anyways, internally we have an installation of Yoxel under Quercus and it works just fine. I hope to productize it some day and make that “easy to deploy” (php for java) package available for download.

-Cheers

Just wanted to mention this open source project that makes it possible for Java apps to access Windows Registry: http://code.google.com/p/java-registry/

I have been quite successful in retrieving MS Outlook User Profile related settings using this tool. Definitely recommend it.

Here is an interesting blog post, JavaFX: one year later. For Java developers who hoped to adopt JavaFX and integrate it with their Swing applications, this is still a challenge and Sun is not helping. Why?

The last paragraph mentions their VP of marketing,  quite interesting:

Wait a minute, according to Eric’s LinkedIn profile, he joined Sun in February ‘08. How long has he been working on JavaFX? That guy, actually, is also an angel investor in a startup called Zoodles, which uses Adobe AIR as the technology for its rich internet application.

Go figure …