<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>try {} catch () &#187; Uncategorized</title>
	<atom:link href="http://blog.gerardin.info/archives/category/uncategorized/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.gerardin.info</link>
	<description>Java, Agile, the Web and other nice things</description>
	<lastBuildDate>Tue, 14 Jun 2011 09:48:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Download Chrome extension from other browser (for offline installation)</title>
		<link>http://blog.gerardin.info/archives/763</link>
		<comments>http://blog.gerardin.info/archives/763#comments</comments>
		<pubDate>Fri, 25 Mar 2011 17:01:20 +0000</pubDate>
		<dc:creator>Olivier Gérardin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Chrome]]></category>
		<category><![CDATA[crx]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[Google]]></category>

		<guid isPermaLink="false">http://blog.gerardin.info/?p=763</guid>
		<description><![CDATA[This is a little trick I found nowhere on the web so I thought I&#8217;d share. Suppose you need to install an extension for Chrome, but for some reason you can&#8217;t access internet from Chrome itself&#8230; Easy, you just need to get the CRX file that contains the extension bundle, right? The trouble is, you [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.gerardin.info/wp-content/uploads/2011/03/chrome_logo.jpeg" class="liimagelink"><img class="alignleft size-thumbnail wp-image-764" style="margin: 8px;" title="chrome_logo" src="http://blog.gerardin.info/wp-content/uploads/2011/03/chrome_logo-150x150.jpg" alt="" width="150" height="150" /></a>This is a little trick I found nowhere on the web so I thought I&#8217;d share.</p>
<p>Suppose you need to install an extension for Chrome, but for some reason you can&#8217;t access internet from Chrome itself&#8230; Easy, you just need to get the CRX file that contains the extension bundle, right? The trouble is, you can&#8217;t easily get this file if you&#8217;re browsing the extension gallery with anything other than Chrome.</p>
<p>&nbsp;</p>
<p>Here&#8217;s how I did it:</p>
<ol>
<li>Find the ID of the extension you&#8217;re interested in. When on the details page of the extension, it will be something like &#8220;bfbmjmiodbnnpllbbbfblcplfjjepjdn&#8221; after &#8220;https://chrome.google.com/extensions/detail/&#8221; in the page URL</li>
<li>Paste this URL into your browser: &#8220;https://clients2.google.com/service/update2/crx?response=redirect&amp;x=id%3D____%26uc&#8221; replacing ____ with the extension ID.</li>
<li>You&#8217;ll be prompted to save a CRX file. Drag this file to a Chrome window and proceed with installation</li>
</ol>
<p>Done!</p>]]></content:encoded>
			<wfw:commentRss>http://blog.gerardin.info/archives/763/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>GWT: using JSON as history token?</title>
		<link>http://blog.gerardin.info/archives/725</link>
		<comments>http://blog.gerardin.info/archives/725#comments</comments>
		<pubDate>Fri, 09 Apr 2010 18:01:54 +0000</pubDate>
		<dc:creator>Olivier Gérardin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[GWT]]></category>
		<category><![CDATA[JSON]]></category>

		<guid isPermaLink="false">http://blog.gerardin.info/?p=725</guid>
		<description><![CDATA[As you might know, GWT provides a handy and elegant mechanism to manage back and forward buttons (and bookmarking) through the use of the &#8220;anchor&#8221; part of the URL, that is the part after the # sign. Basically, whatever you put after the # will not trigger a page reload, but can be intercepted by [...]]]></description>
			<content:encoded><![CDATA[<p>As you might know, GWT provides a handy and elegant mechanism to manage back and forward buttons (and bookmarking) through the use of the &#8220;anchor&#8221; part of the URL, that is the part after the # sign. Basically, whatever you put after the # will not trigger a page reload, but can be intercepted by JavaScript.</p>
<p>Using it in GWT is very straightforward:</p>
<ul>
<li>register a listener to be notified when the context changes (user pressed back or forward or jumped in history) with History.addHistoryListener(listener)</li>
<li>when you want to create a browser history savepoint, call History.newItem(token)</li>
</ul>
<p>The only thing is, GWT will not generate the token for you, because it has no way of knowing what must be included in the so-called application state. So when you want to manage history with GWT, you should always ask yourself the following questions:</p>
<ol>
<li>What must be saved? (just the active window? the selected item? etc.)</li>
<li>How will you encode this in a String?</li>
</ol>
<p>Depending on how complex is your answer to question 1, the answer to question 2 can be very trivial. For example, if all you want to save is the active tab in a multi-tab app, then the contents of the history token can be just an identifier of this tab. Generating it is easy, and so is parsing.</p>
<p>But what if you have more complex data, such as a list of items you want to restore, plus the currently selected item, plus the active view, etc.? I&#8217;ve been looking for a generic way to build a history token in such a case for a while. At first I considered a simple list of key/value pairs, such as:</p>
<blockquote><p>key0=value0; key1=value1</p></blockquote>
<p>This will certainly work in simple cases; you could write a parser and serializer that takes or generates a Map&lt;String, String&gt; without too much trouble. But then inevitably will come the need to embed another map (or a list) in the map&#8230; then the simple case is not so simple anymore.</p>
<p>Anyway, you could imagine handling recursivity with a format like :</p>
<blockquote><p>key0=(item00, item01), key1={key10=value10, key12=(item120, item121)}</p></blockquote>
<p>which would be parsed as:</p>
<ul>
<li>map
<ul>
<li>key0 -&gt; list
<ul>
<li>&#8220;item00&#8243;</li>
<li>&#8220;item01&#8243;</li>
</ul>
</li>
<li>key1 -&gt; map
<ul>
<li>key10 -&gt; &#8220;value10&#8243;</li>
<li>key12 -&gt; list
<ul>
<li>&#8220;item120&#8243;</li>
<li>&#8220;item121&#8243;</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>you get the picture.</p>
<p>I was set to write a parser for this type of format, and not very happy to have to do so, when it struck me how close this format was to JSON&#8230; what if a map was a JSON object, a list a JSON array ? My previous example would then generate the following JSON string:</p>
<blockquote><p>{&#8220;key0&#8243;:["item00"," item01"], &#8220;key1&#8243;:{&#8220;key10&#8243;:&#8221;value10&#8243;, &#8220;key12&#8243;:["item120"," item121"]}</p></blockquote>
<p>Given that GWT comes with a JSON parser/serializer, if I can represent my application state as a Map&lt;String, Object&gt; where objects are instances of String, List&lt;Object&gt; or Map&lt;String, Object&gt;, it would be very easy to build a JSON representation of it. Would that work?</p>
<p>The short answer: yes, but there are caveats.</p>
<p>First, since most of the special characters are URL-encoded, it&#8217;s not pretty. Actually it&#8217;s really ugly. This is what it looks like on an example:</p>
<blockquote><p>MyPage.html#%7B%22active%22:%222d22aa%22,%20%22selected%22:%222dff8%22,%20%22workFolder%22:%5B%222be34%22,%222dff8%22,%22414a4%22%5D%7D</p></blockquote>
<p>Scary, isn&#8217;t it? But, unless you believe every user pays attention to what&#8217;s going on in the address bar, it doesn&#8217;t really matter.</p>
<p>Second, it&#8217;s pretty verbose. The URL can&#8217;t grow in length indefinitely, and this burns a lot of precious characters.</p>
<p>Third, it&#8217;s not secure, if you use GWT&#8217;s native JSON parser that is, because as stated in the Javadoc: &#8220;<em>For efficiency, this method [parse] is implemented using the JavaScript  <code>eval()</code> function, which can execute arbitrary script. DO  NOT  pass an untrusted string into this method</em>.&#8221;.</p>
<p>The last one is a showstopper for public web sites, unless you reimplement your own JSON parser in GWT. So yes, it works, but no, don&#8217;t use it. And if you do anyway, don&#8217;t blame me.</p>
<p>If you want some detail here&#8217;s how I have done it. I&#8217;m in the context of a HMVC app; each controller has a getState() method which is supposed to return a Map representing its state to be saved, and a restoreState() method that takes a Map of the state to be restored. By default getState() returns an empty map, and restoreMap() does nothing, so subclasses are free to override those methods to provide something to save/restore (which might recursively include the state of subcontrollers).</p>
<p>The topmost controller is responsible for handling save state requests; it uses getState() to obtain the global application state, then converts it to a JSON representation, and calls History.newItem().</p>
<p>Conversely, when a history change is detected, the token is parsed as JSON and then converted to a Map. The result is passed to restoreState(), which takes what it needs from the map, does what is needed to restore the state, and recursively calls restoreState() on subcontrollers. How neat is that?</p>
<p>Here&#8217;s the code I use to convert my object graph that represents the app state to and from JSON:</p>
<pre lang="java">
    /**
     * Serialize the specified object as a JSONValue. The object to serialize must be an instance of:
     * - String
     * - Map<String, O>
     * - List<O>
     *
<p/>
     * where O has the same constraints.
     */
    public static JSONValue serializeAsJson(Object object) {
        if (object instanceof Map) {
            Map<String, Object> map = (Map<String, Object>) object;
            JSONObject jsonObject = new JSONObject();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();
                JSONValue convertedValue = serializeAsJson(value);
                jsonObject.put(key, convertedValue);
            }
            return jsonObject;
        }
        else if (object instanceof List) {
            List list = (List) object;
            JSONArray jsonArray = new JSONArray();
            for (int i = 0; i < list.size(); i++) {
                Object entry = list.get(i);
                JSONValue convertedValue = serializeAsJson(entry);
                jsonArray.set(i, convertedValue);
            }
            return jsonArray;
        }
        else if (object instanceof String) {
            return new JSONString((String) object);
        }
        else {
            throw new RuntimeException("Unsupported state type: " + object.getClass());
        }
    }

    /**
     * Parse a JSONValue as follows:
     * -if the value is a JSONObject, parse into a Map<String, Object>
     * -if the value is a JSONArray, parse into a List<Object>
     * -if the value is a JSONString, parse into a String
     * -otherwise fail
     */
    public static Object parseObject(JSONValue jsonValue) {
        if (jsonValue.isObject() != null) {
            return parseMap(jsonValue.isObject());
        }
        else if (jsonValue.isArray() != null) {
            return parseList(jsonValue.isArray());
        }
        else if (jsonValue.isString() != null) {
            return jsonValue.isString().stringValue();
        }
        else {
            throw new RuntimeException("Failed to parse JSON: " + jsonValue.toString());
        }
    }

    /**
     * Parse the specified JSONObject into a Map<String, Object>. The JSONValue associated to
     * a key is parsed recursively using {@link #parseObject(JSONValue)}
     */
    public static Map<String, Object> parseMap(JSONObject jsonObject) {
        Map<String, Object> result = new HashMap<String, Object>();
        for (String key : jsonObject.keySet()) {
            JSONValue jsonValue = jsonObject.get(key);
            Object convertedValue = parseObject(jsonValue);
            result.put(key, convertedValue);
        }
        return result;
    }

    /**
     * Parse the specified JSONArray into a List<Object>. The JSONValues contained in the array are
     * parsed recursively using {@link #parseObject(JSONValue)}
     */
    public static Object parseList(JSONArray array) {
        List<Object> result = new ArrayList<Object>();
        for (int i = 0; i < array.size(); i++) {
            JSONValue jsonValue = array.get(i);
            Object convertedValue = parseObject(jsonValue);
            result.add(convertedValue);
        }
        return result;
    }
</pre>]]></content:encoded>
			<wfw:commentRss>http://blog.gerardin.info/archives/725/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Is HTML5 Ready Yet?</title>
		<link>http://blog.gerardin.info/archives/706</link>
		<comments>http://blog.gerardin.info/archives/706#comments</comments>
		<pubDate>Wed, 10 Mar 2010 15:31:00 +0000</pubDate>
		<dc:creator>Olivier Gérardin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.gerardin.info/?p=706</guid>
		<description><![CDATA[Just attended Mark Pilgrim&#8217;s talk this morning at confoo.ca about HTML5. I&#8217;ll spare you the list of novelties and changes&#8230; HTML5 actually does two things: solves a lot of the current problems with HTML and AJAX apps that required ugly Javascript hacks work around (like initial focus, empty text, typed form fields, etc.) brings new functionalities much [...]]]></description>
			<content:encoded><![CDATA[<p>Just attended Mark Pilgrim&#8217;s talk this morning at confoo.ca about HTML5.</p>
<p>I&#8217;ll spare you the list of novelties and changes&#8230; HTML5 actually does two things:</p>
<ul>
<li>solves a lot of the current problems with HTML and AJAX apps that required ugly Javascript hacks work around (like initial focus, empty text, typed form fields, etc.)</li>
<li>brings new functionalities much required for new generation RIA apps (geolocation, storage, offline, video/audio support, etc.)</li>
</ul>
<p>Apparently it does that very well, allowing compatibility with older markup when possible, complying with standards&#8230; and HTML5 is already there in the latest versions of Chrome, Safari, Firefox and Opera.</p>
<p>Google is obviously pushing hard for HTML5, and the not-so-hidden goal is to get rid of the Flash plugin. Mark said several times during his presentation &#8220;look, no Flash!&#8221;&#8230; With Google and Apple openly trying to push Flash out of the picture, Adobe has a lot to do <img src='http://blog.gerardin.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>BTW check those links:</p>
<ul>
<li><a href="http://isHTML5ready.com" class="liexternal">http://isHTML5ready.com</a></li>
<li><a href="http://isHTML5readyyet.com" class="liexternal">http://isHTML5readyyet.com</a></li>
</ul>
<p>PS: <a href="http://www.pythian.com/news/9237/liveblogging-html5-confoo-keynote" target="_blank" class="liexternal">liveblog of Mark&#8217;s session</a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.gerardin.info/archives/706/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>This might be my next phone</title>
		<link>http://blog.gerardin.info/archives/634</link>
		<comments>http://blog.gerardin.info/archives/634#comments</comments>
		<pubDate>Mon, 14 Dec 2009 13:00:27 +0000</pubDate>
		<dc:creator>Olivier Gérardin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[gsm]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[palm]]></category>
		<category><![CDATA[pre]]></category>

		<guid isPermaLink="false">http://blog.gerardin.info/?p=634</guid>
		<description><![CDATA[I&#8217;ve been pondering a replacement for my (still reliable but aging) Treo 680. Since I have decided not to get an iPhone as long as the App Store has such insane policies, I&#8217;ve narrowed my search down to: Palm Pre An Android device The Pre has a groundbreaking OS called webOS which is almost entirely [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.gerardin.info/archives/634/android_logo" rel="attachment wp-att-636" class="liimagelink"><img class="alignleft size-thumbnail wp-image-636" style="border: 0px;" title="android_logo" src="http://blog.gerardin.info/wp-content/uploads/2009/12/android_logo-150x150.gif" alt="android_logo" width="120" height="120" /></a>I&#8217;ve been pondering a replacement for my (still reliable but aging) <a href="http://www.palm.com/europe/en/products/smartphones/treo680/" target="_blank" class="liexternal">Treo 680</a>. Since I have decided not to get an iPhone as long as the App Store has such insane policies, I&#8217;ve narrowed my search down to:</p>
<ul>
<li><a href="http://www.palm.com/us/products/phones/pre/" target="_blank" class="liexternal">Palm Pre</a></li>
<li>An <a href="http://www.android.com/" target="_blank" class="liexternal">Android</a> device</li>
</ul>
<p>The Pre has a groundbreaking OS called <a href="http://en.wikipedia.org/wiki/WebOS" target="_blank" rel="nofollow" class="liwikipedia">webOS</a> which is almost entirely built on JavaScript and web technologies. It&#8217;s the phone that was designed for &#8220;always on&#8221; operation; it integrates seamlessly with online services such as mail and calendar from several providers (including Google of course). On the down side, it&#8217;s only available in a handful of countries in Europe, Luxembourg NOT being one of them. I called all three mobile network operators and none of them had even heard the name &#8220;Palm Pre&#8221;, so I don&#8217;t suppose I should wait for it to arrive here anytime soon. I could get a German one, but apparently you need to activate it on a German network, plus it comes with a QWERTZ keyboard.</p>
<p>Android phones are not that much easier to get, but they exist. There was an offer for an HTC Hero not long ago, but most reviewers found the hardware a bit lagging, so I decided to wait.</p>
<p>But now it seems that <a href="http://www.techcrunch.com/2009/12/12/the-google-phone-unlocked-confirmed-and-more-details/" target="_blank" class="liexternal">Google might be selling soon its own Android 2.1 device</a>, unlocked GSM, with no carrier messing with the software&#8230; How great is that ? My own Christmas might be a little late this year <img src='http://blog.gerardin.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>]]></content:encoded>
			<wfw:commentRss>http://blog.gerardin.info/archives/634/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

