Afghanistan - Kabul,Asia/Kabul,Afghanistan Time,UTC/GMT +4:30
Algeria - Algiers,Africa/Algiers,Central European Time,UTC/GMT +1:00
Argentina - Buenos Aires,America/Argentina/Buenos_Aires,Argentine Time,UTC/GMT -3:00
Australia - Australian Capital Territory - Canberra,Australia/Canberra,Eastern Standard Time (New South Wales),UTC/GMT +10:00
Australia - New South Wales - Sydney,Australia/Sydney,Eastern Standard Time (New South Wales),UTC/GMT +10:00
Australia - Northern Territory - Darwin,Australia/Darwin,Central Standard Time (Northern Territory),UTC/GMT +9:30
Australia - Queensland - Brisbane,Australia/Brisbane,Eastern Standard Time (Queensland),UTC/GMT +10:00
Australia - South Australia - Adelaide,Australia/Adelaide,Central Standard Time (South Australia),UTC/GMT +9:30
Australia - Victoria - Melbourne,Australia/Melbourne,Eastern Standard Time (Victoria),UTC/GMT +10:00
Australia - Western Australia - Perth,Australia/Perth,Western Standard Time (Australia),UTC/GMT +8:00
Austria - Vienna,Europe/Vienna,Central European Time,UTC/GMT +1:00
Bahamas - Nassau,America/Nassau,Eastern Standard Time,UTC/GMT -5:00
Bangladesh - Dhaka,Asia/Dhaka,Bangladesh Time,UTC/GMT +6:00
Belarus - Minsk,Europe/Minsk,Eastern European Time,UTC/GMT +2:00
Belgium - Brussels,Europe/Brussels,Central European Time,UTC/GMT +1:00
Bolivia - La Paz,America/La_Paz,Bolivia Time,UTC/GMT -4:00
Brazil - São Paulo - Sao Paulo,America/Sao_Paulo,Brasilia Time,UTC/GMT -3:00
Bulgaria - Sofia,Europe/Sofia,Eastern European Time,UTC/GMT +2:00
Canada - Alberta - Edmonton,America/Edmonton,Mountain Standard Time,UTC/GMT -7:00
Canada - British Columbia - Vancouver,America/Vancouver,Pacific Standard Time,UTC/GMT -8:00
Canada - Manitoba - Winnipeg,America/Winnipeg,Central Standard Time,UTC/GMT -6:00
Canada - Newfoundland and Labrador - St. John's,America/St_Johns,Newfoundland Standard Time,UTC/GMT -3:30
Canada - Nova Scotia - Halifax,America/Halifax,Atlantic Standard Time,UTC/GMT -4:00
Canada - Ontario - Toronto,America/Toronto,Eastern Standard Time,UTC/GMT -5:00
Canada - Quebec - Montreal,America/Montreal,Eastern Standard Time,UTC/GMT -5:00
Chile - Santiago,America/Santiago,Chile Time,UTC/GMT -4:00
China - Shanghai,Asia/Shanghai,China Standard Time,UTC/GMT +8:00
Colombia - Bogota,America/Bogota,Colombia Time,UTC/GMT -5:00
Croatia - Zagreb,Europe/Zagreb,Central European Time,UTC/GMT +1:00
Cuba - Havana,America/Havana,Cuba Standard Time,UTC/GMT -5:00
Czech Republic - Prague,Europe/Prague,Central European Time,UTC/GMT +1:00
Denmark - Copenhagen,Europe/Copenhagen,Central European Time,UTC/GMT +1:00
Dominican Republic - Santo Domingo,America/Santo_Domingo,Atlantic Standard Time,UTC/GMT -4:00
Egypt - Cairo,Africa/Cairo,Eastern European Time,UTC/GMT +2:00
El Salvador - San Salvador,America/El_Salvador,Central Standard Time,UTC/GMT -6:00
Estonia - Tallinn,Europe/Tallinn,Eastern European Time,UTC/GMT +2:00
Ethiopia - Addis Ababa,Africa/Addis_Ababa,Eastern African Time,UTC/GMT +3:00
Fiji - Suva,Pacific/Fiji,Fiji Time,UTC/GMT +12:00
Finland - Helsinki,Europe/Helsinki,Eastern European Time,UTC/GMT +2:00
France - Paris,Europe/Paris,Central European Time,UTC/GMT +1:00
Germany - Berlin - Berlin,Europe/Berlin,Central European Time,UTC/GMT +1:00
Greece - Athens,Europe/Athens,Eastern European Time,UTC/GMT +2:00
Guatemala - Guatemala,America/Guatemala,Central Standard Time,UTC/GMT -6:00
Honduras - Tegucigalpa,America/Tegucigalpa,Central Standard Time,UTC/GMT -6:00
Hong Kong - Hong Kong,Asia/Hong_Kong,Hong Kong Time,UTC/GMT +8:00
Hungary - Budapest,Europe/Budapest,Central European Time,UTC/GMT +1:00
Iceland - Reykjavik,Atlantic/Reykjavik,Greenwich Mean Time,UTC/GMT +0:00
India - Delhi - New Delhi,Asia/Kolkata,India Standard Time,UTC/GMT +5:30
India - Maharashtra - Mumbai,Asia/Kolkata,India Standard Time,UTC/GMT +5:30
India - West Bengal - Kolkata,Asia/Kolkata,India Standard Time,UTC/GMT +5:30
Indonesia - Java - Jakarta,Asia/Jakarta,West Indonesia Time,UTC/GMT +7:00
Iran - Tehran,Asia/Tehran,Iran Standard Time,UTC/GMT +3:30
Iraq - Baghdad,Asia/Baghdad,Arabia Standard Time,UTC/GMT +3:00
Ireland - Dublin,Europe/Dublin,Greenwich Mean Time,UTC/GMT +0:00
Israel - Jerusalem,Asia/Jerusalem,Israel Standard Time,UTC/GMT +2:00
Italy - Rome,Europe/Rome,Central European Time,UTC/GMT +1:00
Jamaica - Kingston,America/Jamaica,Eastern Standard Time,UTC/GMT -5:00
Japan - Tokyo,Asia/Tokyo,Japan Standard Time,UTC/GMT +9:00
Jordan - Amman,Asia/Amman,Eastern European Time,UTC/GMT +2:00
Kazakstan - Almaty,Asia/Almaty,Alma-Ata Time,UTC/GMT +6:00
Kenya - Nairobi,Africa/Nairobi,Eastern African Time,UTC/GMT +3:00
Kiribati - Christmas Island - Kiritimati,Pacific/Kiritimati,Line Is. Time,UTC/GMT +14:00
Kuwait - Kuwait City,Asia/Kuwait,Arabia Standard Time,UTC/GMT +3:00
Lebanon - Beirut,Asia/Beirut,Eastern European Time,UTC/GMT +2:00
Madagascar - Antananarivo,Indian/Antananarivo,Eastern African Time,UTC/GMT +3:00
Malaysia - Kuala Lumpur,Asia/Kuala_Lumpur,Malaysia Time,UTC/GMT +8:00
Mexico - Federal District - Mexico City,America/Mexico_City,Central Standard Time,UTC/GMT -6:00
Morocco - Casablanca,Africa/Casablanca,Western European Time,UTC/GMT +0:00
Myanmar - Yangon,Asia/Rangoon,Myanmar Time,UTC/GMT +6:30
Nepal - Kathmandu,Asia/Kathmandu,GMT+05:45,UTC/GMT +5:45
Netherlands - Amsterdam,Europe/Amsterdam,Central European Time,UTC/GMT +1:00
New Zealand - Auckland,Pacific/Auckland,New Zealand Standard Time,UTC/GMT +12:00
New Zealand - Chatham Islands,Pacific/Chatham,Chatham Standard Time,UTC/GMT +12:45
Nicaragua - Managua,America/Managua,Central Standard Time,UTC/GMT -6:00
Nigeria - Lagos,Africa/Lagos,Western African Time,UTC/GMT +1:00
Norway - Oslo,Europe/Oslo,Central European Time,UTC/GMT +1:00
Pakistan - Karachi,Asia/Karachi,Pakistan Time,UTC/GMT +5:00
Paraguay - Asuncion,America/Asuncion,Paraguay Time,UTC/GMT -4:00
Peru - Lima - Lima,America/Lima,Peru Time,UTC/GMT -5:00
Philippines - Manila,Asia/Manila,Philippines Time,UTC/GMT +8:00
Poland - Warsaw,Europe/Warsaw,Central European Time,UTC/GMT +1:00
Portugal - Lisbon,Europe/Lisbon,Western European Time,UTC/GMT +0:00
Puerto Rico - San Juan,America/Argentina/San_Juan,Argentine Time,UTC/GMT -3:00
Romania - Bucharest,Europe/Bucharest,Eastern European Time,UTC/GMT +2:00
Russia - Anadyr,Asia/Anadyr,Anadyr Time,UTC/GMT +12:00
Russia - Kamchatka,Asia/Kamchatka,Petropavlovsk-Kamchatski Time,UTC/GMT +12:00
Russia - Moscow,Europe/Moscow,Moscow Standard Time,UTC/GMT +3:00
Russia - Vladivostok,Asia/Vladivostok,Vladivostok Time,UTC/GMT +10:00
Saudi Arabia - Riyadh,Asia/Riyadh,Arabia Standard Time,UTC/GMT +3:00
Serbia - Belgrade,Europe/Belgrade,Central European Time,UTC/GMT +1:00
Singapore - Singapore,Asia/Singapore,Singapore Time,UTC/GMT +8:00
South Africa - Johannesburg,Africa/Johannesburg,South Africa Standard Time,UTC/GMT +2:00
South Korea - Seoul,Asia/Seoul,Korea Standard Time,UTC/GMT +9:00
Spain - Madrid,Europe/Madrid,Central European Time,UTC/GMT +1:00
Sudan - Khartoum,Africa/Khartoum,Eastern African Time,UTC/GMT +3:00
Sweden - Stockholm,Europe/Stockholm,Central European Time,UTC/GMT +1:00
Switzerland - Zurich,Europe/Zurich,Central European Time,UTC/GMT +1:00
Taiwan - Taipei,Asia/Taipei,China Standard Time,UTC/GMT +8:00
Thailand - Bangkok,Asia/Bangkok,Indochina Time,UTC/GMT +7:00
Turkey - Ankara,Turkey,Eastern European Time,UTC/GMT +2:00
Turkey - Istanbul,Turkey,Eastern European Time,UTC/GMT +2:00
U.K. - England - London,Europe/London,Greenwich Mean Time,UTC/GMT +0:00
United Arab Emirates - Dubai - Dubai,Asia/Dubai,Gulf Standard Time,UTC/GMT +4:00
Uruguay - Montevideo,America/Montevideo,Uruguay Time,UTC/GMT -3:00
U.S.A. - Alaska - Anchorage,America/Anchorage,Alaska Standard Time,UTC/GMT -9:00
U.S.A. - California - Los Angeles,America/Los_Angeles,Pacific Standard Time,UTC/GMT -8:00
U.S.A. - Colorado - Denver,America/Denver,Mountain Standard Time,UTC/GMT -7:00
U.S.A. - Hawaii - Honolulu,Pacific/Honolulu,Hawaii Standard Time,UTC/GMT -10:00
U.S.A. - Illinois - Chicago,America/Chicago,Central Standard Time,UTC/GMT -6:00
U.S.A. - Michigan - Detroit,America/Detroit,Eastern Standard Time,UTC/GMT -5:00
U.S.A. - New York - New York,America/New_York,Eastern Standard Time,UTC/GMT -5:00
Uzbekistan - Tashkent,Asia/Tashkent,Uzbekistan Time,UTC/GMT +5:00
Venezuela - Caracas,America/Caracas,Venezuela Time,UTC/GMT -4:30
Vietnam - Hanoi,Asia/Vientiane,Indochina Time,UTC/GMT +7:00
Yemen - Aden,Asia/Aden,Arabia Standard Time,UTC/GMT +3:00
Zimbabwe - Harare,Africa/Harare,Central African Time,UTC/GMT +2:00
Tuesday, August 18, 2009
List of countries and timezones
I'm pasting a csv file containing a list of timezone data of some of the cities from timeanddate.com. I was unable to find such a list and eventually had to do a lot of manual work. Do comment if there are any errors.
Friday, August 07, 2009
Flex
I had an opportunity to look into Flex a few weeks back. I've been mostly focused on Swing last couple of years and before that was fairly involved with web development (pre-ajax). So it's been a nice exercise to investigate what it offers and compare and contrast.
Flex has a good out of the box widget set, similar to Swing. One of its major strengths is its UI designer - no real surprise there, given it grew out of flash. Actionscript, the ECMAScript compliant language, tries to be dynamic with optional static typing. This can be useful, especially during at development time with code completion. Debugging can be a challenge though, especially the mix between actionscript and mxml. End up falling back on Alerts which isn't the greatest thing (more so given that they don't block and you can end up with a flurry of alert boxes). I also found that there are multiple ways to do the same thing. This can be quite confusing especially when looking at samples on the web. You don't really know which is the best way or why. One other small thing - event names don't follow "on[event_name]" convention... it's very easy to confuse them with attributes in mxml. Overall, there's a big similarity with the html/js/css style of development - mxml/as/css.
Flex demos really well. For creating small simple apps involving fetching data from a remote data source and rendering it, it is probably unrivaled from a productivity perspective. Drag a datagrid onto the canvas, construct an http service and attach a result event handler to bind the result to the datagrid. Simple. Done. I think the 'Bindable' attribute is a big part of why Flex is so successful for these types of apps. It takes care of all that plumbing of syncing model with view. It's interesting to note that JavaFX has introduced the 'bind' keyword in JavaFX Script.
Most of what I've come across - articles/examples deal with small apps. I'm interested in how development in Flex would scale. It can be double edged sword. Given that it is so simple to just drag/drop and attach handlers, I would think it would require more discipline and good coding practices. It would be all too easy to keep doing this all over without really giving much thought to overall design and code hygiene. I don't particularly like the script tag in the MXML file. There should've been strict separation between the .mxml file and the .as file. I understand this was probably done to emulate the html/js model but why not force the separation as with separate .js files.
Running a fairly complicated app - like TourDeFlex which chronicles the wonders of the various flex widgets - sucks up a lot of resources. Usability suffers. The experience feels sluggish. A similarly "heavy" "ajaxy" app doesn't. What's worse is that on more than one occasion, the browser has crashed running that demo. It's no surprise I haven't seen full fledged flex apps out on the 'open web'. Enterprises can, and have, embraced it since they can dictate the environment.
There's a lot of revival in interest in web standards. Just as Adobe has AIR, Microsoft has Silverlight and Sun/Oracle has JavaFX, Google is embracing and evangelizing open web standards - HTML5/CSS/Javascript - as their RIA platform. GWT is the browser independent development platform with generated Javascript as the bytecode. I've started playing around with GWT recently and am quite impressed with its abilities - especially the development environment/cycle. Version 2.0 promises more useful features.
It'll be interesting to see where these platforms end up 3-4 years from now.
Flex has a good out of the box widget set, similar to Swing. One of its major strengths is its UI designer - no real surprise there, given it grew out of flash. Actionscript, the ECMAScript compliant language, tries to be dynamic with optional static typing. This can be useful, especially during at development time with code completion. Debugging can be a challenge though, especially the mix between actionscript and mxml. End up falling back on Alerts which isn't the greatest thing (more so given that they don't block and you can end up with a flurry of alert boxes). I also found that there are multiple ways to do the same thing. This can be quite confusing especially when looking at samples on the web. You don't really know which is the best way or why. One other small thing - event names don't follow "on[event_name]" convention... it's very easy to confuse them with attributes in mxml. Overall, there's a big similarity with the html/js/css style of development - mxml/as/css.
Flex demos really well. For creating small simple apps involving fetching data from a remote data source and rendering it, it is probably unrivaled from a productivity perspective. Drag a datagrid onto the canvas, construct an http service and attach a result event handler to bind the result to the datagrid. Simple. Done. I think the 'Bindable' attribute is a big part of why Flex is so successful for these types of apps. It takes care of all that plumbing of syncing model with view. It's interesting to note that JavaFX has introduced the 'bind' keyword in JavaFX Script.
Most of what I've come across - articles/examples deal with small apps. I'm interested in how development in Flex would scale. It can be double edged sword. Given that it is so simple to just drag/drop and attach handlers, I would think it would require more discipline and good coding practices. It would be all too easy to keep doing this all over without really giving much thought to overall design and code hygiene. I don't particularly like the script tag in the MXML file. There should've been strict separation between the .mxml file and the .as file. I understand this was probably done to emulate the html/js model but why not force the separation as with separate .js files.
Running a fairly complicated app - like TourDeFlex which chronicles the wonders of the various flex widgets - sucks up a lot of resources. Usability suffers. The experience feels sluggish. A similarly "heavy" "ajaxy" app doesn't. What's worse is that on more than one occasion, the browser has crashed running that demo. It's no surprise I haven't seen full fledged flex apps out on the 'open web'. Enterprises can, and have, embraced it since they can dictate the environment.
There's a lot of revival in interest in web standards. Just as Adobe has AIR, Microsoft has Silverlight and Sun/Oracle has JavaFX, Google is embracing and evangelizing open web standards - HTML5/CSS/Javascript - as their RIA platform. GWT is the browser independent development platform with generated Javascript as the bytecode. I've started playing around with GWT recently and am quite impressed with its abilities - especially the development environment/cycle. Version 2.0 promises more useful features.
It'll be interesting to see where these platforms end up 3-4 years from now.
Friday, July 24, 2009
TurboStringMap for Gwt
In my previous post I did mention that Gwt has the basic Java collections emulated in Javascript. In the browser such rich interfaces may not be needed. There is a lightweight Map implementation where the keys are constrained to String types only called FastStringMap. It is directly backed by a Js array. Want to go even lighter then here is the derived TurboStringMap which even a thinner API over a Js array to act like a Map.
The rest of the this post is Gwt Java code-
The rest of the this post is Gwt Java code-
package com.onyem.finance.client;
import com.google.gwt.core.client.JavaScriptObject;
class TurboStringMap{
/*
* Accesses need to be prefixed with ':' to prevent conflict with built-in
* JavaScript properties.
*/
@SuppressWarnings("unused")
private JavaScriptObject map;
public TurboStringMap() {
init();
}
public void clear() {
init();
}
private native void init() /*-{
this.@com.onyem.finance.client.TurboStringMap::map = {};
}-*/;
// Prepend ':' to avoid conflicts with built-in Object properties.
public native T get(String key) /*-{
return this.@com.onyem.finance.client.TurboStringMap::map[':' + key];
}-*/;
// Prepend ':' to avoid conflicts with built-in Object properties.
public native T put(String key, T value) /*-{
key = ':' + key;
var map = this.@com.onyem.finance.client.TurboStringMap::map;
var previous = map[key];
map[key] = value;
return previous;
}-*/;
// Prepend ':' to avoid conflicts with built-in Object properties.
public native T remove(String key) /*-{
key = ':' + key;
var map = this.@com.onyem.finance.client.TurboStringMap::map;
var previous = map[key];
delete map[key];
return previous;
}-*/;
// only count keys with ':' prefix
public native int size() /*-{
var value = this.@com.onyem.finance.client.TurboStringMap::map;
var count = 0;
for(var key in value) {
if (key.charAt(0) == ':') ++count;
}
return count;
}-*/;
public boolean isEmpty() {
return size() == 0;
}
public native String[] keys() /*-{
var value = this.@com.onyem.finance.client.TurboStringMap::map;
var keys = [];
for(var key in value) {
keys.push(key.substring(1));
}
return keys;
}-*/;
}
Wednesday, July 08, 2009
GWT
I've been working with Gwt since a while and in this post will dump some of my learnings
What is Gwt
Gwt is a toolkit primarily to enable writing webapps in Java which will then be cross compiled into plain Javascript and Html. The core is based on this java to javascript compiler. Additionally they have libraries for purposes like web gui creation, dom manipulation, json and xml parsing, RPC calls with java server support and also unit testing. The Gwt guys are seem pretty obsessed with performance so a lot of the design choices are based on this.
More Features
What is Gwt
Gwt is a toolkit primarily to enable writing webapps in Java which will then be cross compiled into plain Javascript and Html. The core is based on this java to javascript compiler. Additionally they have libraries for purposes like web gui creation, dom manipulation, json and xml parsing, RPC calls with java server support and also unit testing. The Gwt guys are seem pretty obsessed with performance so a lot of the design choices are based on this.
To code in Gwt you use your standard Java tools. This is a great advantage as you get great tool/ide support and java's static checking for code. Java generics are also supported. To create UIs a SWT-like library has been created which can be used. The library contains both Widget classes for common controls as well as layout classes for positioning. There are some quirks which you have to be aware of but thats true for almost any new platform. The layout library is one of the first reasons which got me to Gwt as I was (and still am) simply too scared to use CSS for managing a layout. Using the UI libraries for building interfaces is a bit painful in Java just as it is in Swing and Swt. But more importantly it does not translate to the best Html/Css layout code. For example to place child elements horizontally next to each other you can use the HorizontalPanel and add elements to this. Now when this code is cross compiled the HorizontalPanel is converted to a Html table with a single tr and all the child elements will be placed in td elements. Which depending on your style may not look that good. In the next version of Gwt a new UI Binder feature is going to be added. This will allow declaring the UI in an XML format and then writing the actual event handlers in Java. I guess a lot of UI frameworks are moving to this style which really does make sense in this domain. Also the code generated may be closer to the layout code you would have written by hand (if you knew CSS). You can also create your own Widgets and Panels if you want to. I also almost forgot to mention that you have access to a subset of the Java library. The API can be read here. Basic java.lang and other important packages like some collections are supported.
Now that you have written some Java code you compile it by using the GwtCompiler which can be invoked by an ant task. You get a whole bunch of files into your dist folder. Now these are plain html, js and css files. You dont need any Java support in your webserver to run these. Gwt will generate separate optimized files for each browser supported. A client using IE7 will get a file separate from a FF client and each file will manage the quirks of that browser. So a client downloads almost only what is needed. I lied a bit in this process though. When the browser first hits the entry point html file special js code will decide what browser is running the code. After that the client code for that browser is then loaded in another Http request. Search for more on deferred binding to learn more. Importantly most of the code generated can be cached with long expiration headers.
The Gwt compiler essentially compiles Java (source code) to Js. But from where does it get the java.lang and other code of the standard library? The Gwt team has re-written supported Java libraries in a more Js friendly fashion. The String class is based on a normal Js string but the extended Java API for the string class is supported. Similarly the ArrayList class is not something that Bloch wrote but a simpler Js friendly version. Just like the layout code generated some of this is overkill for Js. You dont really need the whole Collections API most of the time. You dont need the whole class hierarchy. Like I just needed a lame Map implementation with put and get and nothing else. And since some part of the Gwt library may use the collections in some way you end up using them anyways. See my bug for an extended rant
Atleast one compiler optimization has to mentioned at this point - dead code elimination. For example if you dont use the substing method in the String class.. that method will not be compiled to Js. Additionally Js code is minified and obfuscated which greatly helps in reduction of download size.
Where should you use GWT
Gwt is great for Ajax apps like Gmail, Google calendar etc. As a Java developer I dont think I could do better/faster had I been coding Js/Html for Onyem. There are deficiencies right now but things are improving and are already optimized enough.
I would not still recommend Gwt in sites that have a lot content like news sites or sites where you just want a small widget in one corner. Use jquery or yui for that.
Also there can be no substitute for knowing CSS and also how to build websites. With a desktop mindset you will end up just bulding really slow apps.
More Features
These may come in some other post-
Hosted mode to OOPHM
Async pattern
Jsni
RPC
Deferred binding
More Compiler optimizations
Wednesday, June 03, 2009
Open Source is Magic
- "Any sufficiently advanced technology is indistinguishable from magic." - Sir Arthur C. Clarke
Monday, June 01, 2009
Anti-social
In relation with normal human behaviour I am "anti-social". Personally I know I am just different-social which is great for me.
I've been emailing a few people of late whom I don't know that well. And shockingly those gmail contacts started popping up in my gtalk list. The reason was gmails default setting of over-friendly behaviour. If you want more privacy then you need to disable the "Auto-add suggested contacts" feature in chat as described in this help page
I've been emailing a few people of late whom I don't know that well. And shockingly those gmail contacts started popping up in my gtalk list. The reason was gmails default setting of over-friendly behaviour. If you want more privacy then you need to disable the "Auto-add suggested contacts" feature in chat as described in this help page
Thursday, May 21, 2009
Ubuntu Remixed
I upgraded to Jaunty Jackalope (9.04) over the weekend. Technically it wasn't an upgrade, rather a clean install. My setup makes it convenient to do this... I have three partitions - Windows, Ubuntu and DATA which contains all my docs/pics/music/movies. I tend to skip every other release and when I do want to "upgrade", I just back up my home directory (which is on the Ubuntu partition) to DATA and do a clean install.
Way back in Oct 2006, I wrote about my first foray into the Ubuntu universe. Two and a half years and five releases later it's thrilling to see how far its come and how much better the experience has gotten on that same machine. All issues listed in that post are virtually non-existent. One of Jaunty's specific goals was improving startup time and they delivered superbly... < 25 seconds on my laptop. I like the consistent new notification system as well. With every new release, it gets more and more polished.
Anyway, I thought I'd list the steps I take to get my setup going after every clean install...
Remix
I happened to have access to an Asus Eee 700 netbook. It comes with Xandros linux with a weird Windows XP like look and limited functionality ("basic mode" with no access to the terminal/can't install any app (only certain pre-selected ones)/etc...). Ubuntu Remix targets these types of netbooks. It's a full ubuntu system with added packages for the UI specifically tuned for small screen sizes.
With no cd/dvd drive, the way to install it is via a bootable usb drive which can easily be created using usb-imagewriter. The installation process is the same good ol ubuntu wizard. It ended up sucking up ~2.5 gb of the 4gb harddisk. There are things to tune/optimize which should reclaim some of that space as well as speed things up. For now, I'm just happy to get a chance to play around with it :)
Way back in Oct 2006, I wrote about my first foray into the Ubuntu universe. Two and a half years and five releases later it's thrilling to see how far its come and how much better the experience has gotten on that same machine. All issues listed in that post are virtually non-existent. One of Jaunty's specific goals was improving startup time and they delivered superbly... < 25 seconds on my laptop. I like the consistent new notification system as well. With every new release, it gets more and more polished.
Anyway, I thought I'd list the steps I take to get my setup going after every clean install...
- backup home directory: cp -R /home/mohnish /media/data/mohnish
- clean install
- install updates
- restore home directory: cp -R /media/data/mohnish /home/mohnish
- create sym links in home directory to media on DATA:
- ln -s /media/data/Docs Docs
- ln -s /media/data/Music Music
- ln -s /media/data/Pics Pics - install apps
- media codecs (audio/video playback, java, flash): apt-get install ubuntu-restricted-extras
- gnome do ('crazy delicious' once you're used to it): apt-get install gnome-do gnome-do-plugins
- listen (music during setup is essential): apt-get install listen
- opera (small, wicked fast and built-in mouse gestures... the best browser out there): grab .deb package from opera.com
- skype (convenient, saves money for cheapies like me): grab .deb package from skype.com
- vlc (the 'everything' media player): apt-get install vlc
- picasa (organize pics with nice web album integration): grab .deb package from goog
- googleearth (spy on your neighbourhood) - grab .bin file from goog
- gnomad2 (organize music on creative nomads/zens): apt-get install gnomad2
- sopcast-player (for those 5am Liverpool footy matches (with chinese commentary)): grab .deb package from goog code
- miro (get some gyan): apt-get install miro
Remix
I happened to have access to an Asus Eee 700 netbook. It comes with Xandros linux with a weird Windows XP like look and limited functionality ("basic mode" with no access to the terminal/can't install any app (only certain pre-selected ones)/etc...). Ubuntu Remix targets these types of netbooks. It's a full ubuntu system with added packages for the UI specifically tuned for small screen sizes.
With no cd/dvd drive, the way to install it is via a bootable usb drive which can easily be created using usb-imagewriter. The installation process is the same good ol ubuntu wizard. It ended up sucking up ~2.5 gb of the 4gb harddisk. There are things to tune/optimize which should reclaim some of that space as well as speed things up. For now, I'm just happy to get a chance to play around with it :)
Wednesday, September 03, 2008
Javascript Revisisted
When starting an expedition with a new language, (most) people take time to fully understand and learn it before attempting to program with it. Except with Javascript... almost universally, it invites people to dive in without really knowing it. I'm paraphrasing Douglas Crockford here.
I've found this to be very true. Almost 10 years back I started playing around with html and then CSS. The natural final progression led me to Javascript. I clearly remember going through Thau's Javascript tutorials over at WebMonkey trying to actually figure out what I was hacking. Those were exciting times at the height of the "Browser War" with the DOM coming into its own: MS introducing document.all and Netscape's document.layers. After IE won, nothing much happened for the next 5 years. And Javascript, already considered a toy language back then was more or less ignored.
With the emergence of Ajax all that changed. People actually started taking a serious look at JS. Rahul found a series of videos - The Javascript Programming Language - by the above mentioned Douglas Crockford over at YUI threatre. They are by far the best material on revealing the real javascript and what a wonderful dynamic language it is. It is simple, yet, deceptively powerful. I took notes and here are some language highlights:
Overview
Types
Ops
Objects
Arrays
Functions
Misc
DOM
Detailed slides:
The Javascript Programming Langauge
Advanced Javascript
DOM
I've found this to be very true. Almost 10 years back I started playing around with html and then CSS. The natural final progression led me to Javascript. I clearly remember going through Thau's Javascript tutorials over at WebMonkey trying to actually figure out what I was hacking. Those were exciting times at the height of the "Browser War" with the DOM coming into its own: MS introducing document.all and Netscape's document.layers. After IE won, nothing much happened for the next 5 years. And Javascript, already considered a toy language back then was more or less ignored.
With the emergence of Ajax all that changed. People actually started taking a serious look at JS. Rahul found a series of videos - The Javascript Programming Language - by the above mentioned Douglas Crockford over at YUI threatre. They are by far the best material on revealing the real javascript and what a wonderful dynamic language it is. It is simple, yet, deceptively powerful. I took notes and here are some language highlights:
Overview
- A real language - small, so easily approachable.
- Dynamic - "load and go"... i.e. interpreted + loosely typed.
- Objects are containers... i.e. HashMaps.
- Prototypical inheritance - No classes. Inherit directly from objects.
- Lambda support - Closures. "First lambda language to go mainstream".
Types
- Numbers - 64-bit floats. NaN is result of erroneous operations.
- Strings - 16-bit chars. Immutable. == compares string values.
- null - nothing.
- undefined - default variable value. Missing object members.
- Booleans - falsy: false, null, undefined, empty string, 0, NaN. truthy:!(falsy)
- Objects - everything else. Including functions.
- Loosely typed != Untyped. Checks at runtime. Any type can be stored in any variable including functions.
Ops
- == and != do type coersion. Use === and !== instead.
- && and || return values.
- foreach (i in object) iterates over ALL properties. Use hasOwnProperty check.
- Scope - blocks {} don't have scope. Only functions have scope. Variables inside function are not visible outside.
Objects
- Inherit from other objects.
- Are an unordered Map.
- Object literals: {} (Basis of JSON: simple data exchange format)
- New empty object: new Object() == {} == object(Object.prototype)
- New members are added by simple assignment. No need for a new class.
- "Linkage" to "parent" object - Simple inheritance.
- When setting values, only affects current object. When getting values, access goes "up", if not found in current object.
- Pass by ref.
- === is comparison on reference.
- Remove member: delete object[name]
Arrays
- Inherit from Object.
- Indexes are strings (numbers are converted).
- Array literals: [] (== new Array())
- delete array[index] leaves a "hole" (value is undefined). Use Array.prototype.splice instead.
Functions
- Are objects.
- Inherit from Object and can store name/value pairs!
- JS function == other language lambda.
- function foo() {} is equivalent to var foo = function() {}
- Can have inner functions with access to parent function scope even after parent function is invoked: Closures.
Misc
- Can augment built-in types by modifying prototypes.
- Avoid type wrappers (added to be similar to Java).
- Browser 'window' is global object. Container for all global vars and built-in objects.
- Every object is a separate namespace.
- Browser apps are all single threaded.
DOM
- id - uniquely identifies element.
- Avoid document.all. Use document.getElementById(id), document.getElementsByName(name),
.getElementsByTagName(tagName) . - Document Tree Structure: document is root. document.documentElement is HTML tag. document.body is BODY tag.
- Node: child, sibling, parent pointers. childNodes list.
- Style: node.className/node.style.styleName
- Events: Browser - event driven, single threaded, async programming model. Events targeted at particular nodes. Events cause invocation of event handlers. (Remove event handlers from nodes before deleting). node["on" + type] = function to add event handler. Event handlers send optional event object. Events bubble up from "specific" to "general".
- Dialogs: alert, confirm, prompt all block async model. Avoid them in ajaxy apps.
Detailed slides:
The Javascript Programming Langauge
Advanced Javascript
DOM
Thursday, June 26, 2008
Monday, March 31, 2008
Immutable locks
Immutability is something that's mentioned over and over when it comes to parallel programming. Part I of Java Concurrency In Practice is all about composing objects that "play well" in the concurrent world and those that are immutable are the "best" citizens. No wonder functional languages are coming up in a big way. Anyone want to bet on them taking over the world in the next decade? Or if not taking over outright, at least succeeding in mutating our beloved imperative ones into unrecognisable functional beasts.
Anyway, check out the method below:
public class Foo {
private Listener[] listeners;
public Foo() {
listeners = new Listener[0];
}
public void addListener(Listener listener) {
synchronized (listeners) {
Listener[] newListeners = new Listener[listeners.length + 1];
for (int i = 0; i < listeners.length; ++i) {
newListeners[i] = listeners[i];
}
newListeners[listeners.length] = listener;
listeners = newListeners;
}
}
}
So here, the first thread to obtain the lock on listeners reassigns it to a new Array object... newListeners. Subsequent threads would continue to lock on the old listeners array, while new threads would lock on the "new" listeners array, and potentially corrupt the data. So I guess there's an unwritten property about locks... they need to be immutable to avoid situations like the above.
So given that locks need to be constant, there's no way to have a workable solution in the above code without using an additional object as the lock. The easy "lazy" thing to do is to just synchronize the method itself. The Foo instance (this) would then be that "additional object". But that would be wasteful since it would prevent all other synchronized method calls, even ones that have nothing to do with listeners.
(If instead of an Array, a List was used, the problem wouldn't have occurred given that the List itself wouldn't change. And I think, nowadays mostly the thinking when programming in managed languages is to go for Collections, rather than mess with manually managing Arrays. But I have still seen code like the above, so it's not totally contrived.)
Anyway, check out the method below:
public class Foo {
private Listener[] listeners;
public Foo() {
listeners = new Listener[0];
}
public void addListener(Listener listener) {
synchronized (listeners) {
Listener[] newListeners = new Listener[listeners.length + 1];
for (int i = 0; i < listeners.length; ++i) {
newListeners[i] = listeners[i];
}
newListeners[listeners.length] = listener;
listeners = newListeners;
}
}
}
So here, the first thread to obtain the lock on listeners reassigns it to a new Array object... newListeners. Subsequent threads would continue to lock on the old listeners array, while new threads would lock on the "new" listeners array, and potentially corrupt the data. So I guess there's an unwritten property about locks... they need to be immutable to avoid situations like the above.
So given that locks need to be constant, there's no way to have a workable solution in the above code without using an additional object as the lock. The easy "lazy" thing to do is to just synchronize the method itself. The Foo instance (this) would then be that "additional object". But that would be wasteful since it would prevent all other synchronized method calls, even ones that have nothing to do with listeners.
(If instead of an Array, a List was used, the problem wouldn't have occurred given that the List itself wouldn't change. And I think, nowadays mostly the thinking when programming in managed languages is to go for Collections, rather than mess with manually managing Arrays. But I have still seen code like the above, so it's not totally contrived.)
Sunday, March 30, 2008
Constant Learning with Miro
In every field, it's important to continue to learn about one's discipline even after graduating from formal learning institutions. No where is this more pertinent than in the software industry where the only constant is (fast and furious) change. There's always books and articles to keep up with what's new, but videos have emerged in a big way as another avenue.
And it seems like the developer communities at all the big guns... Microsoft, Sun, Google and Yahoo... have jumped on the bandwagon and are producing great content. Microsoft had started channel 9 a few years back where they'd go around interviewing key engineers. Sun has videos through the Sun Developer Network Channel. Google has their Tech Talks series. Rahul introduced me to Yahoo's YUI Theater few months back.
The great thing about a lot of the talks is that although they are presented in the context of the company's platform/language/technology, they tend to transcend them and are concepts and trends that apply to general software engineering. Microsoft's channel9 for instance, has had wonderful discussions with architects and designers on everything from functional programming to garbage collection to concurrency.
In spite of all the great videos out there, it's a hassle to have to go to each of these different sites, see what's new and watch it. Enter Miro. Miro is an amazing open source application designed specifically to consume vidcasts (it works with podcasts too). Here's a screenshot where I've subscribed to some of these "channels" (yes, I have a lot of catching up to do!).

You may be wondering if this really is a huge deal. I think it is. Miro simplifies and automates the process and makes it so simple and easy. Every time you start miro, it'll tell you of the latest content available and ask if you want to download it. And the quality is generally much better what with being able to view it full screen and it also has nifty features like remembering where you left of in case you have to pause midway through etc... The one downside is that it has to download the video bits as opposed to streaming it through flash (as is common on many sites since the emergence of youtube). So for the bandwidth constrained it can be a bit of an issue. But then again, flash still has some issues on Linux and some of the videos don't play. Plus, looks like Microsoft recently converted to Silverlight which doesn't work on Linux (haven't looked into Moonlight). So most likely you'd end up having to download it anyway.
I've only mentioned few channels, but as you can imagine, there's tons of them around the web. Miro has a guide built-in which showcases some of them. Apart from tech content, many universities like Berkeley and Princeton are broadcasting some of their lectures and events. So there's definitely no lack of content. Just need to make time!
Overall, I love Miro and can't say enough good things about it. Kudos to the guys who've developed it.
And it seems like the developer communities at all the big guns... Microsoft, Sun, Google and Yahoo... have jumped on the bandwagon and are producing great content. Microsoft had started channel 9 a few years back where they'd go around interviewing key engineers. Sun has videos through the Sun Developer Network Channel. Google has their Tech Talks series. Rahul introduced me to Yahoo's YUI Theater few months back.
The great thing about a lot of the talks is that although they are presented in the context of the company's platform/language/technology, they tend to transcend them and are concepts and trends that apply to general software engineering. Microsoft's channel9 for instance, has had wonderful discussions with architects and designers on everything from functional programming to garbage collection to concurrency.
In spite of all the great videos out there, it's a hassle to have to go to each of these different sites, see what's new and watch it. Enter Miro. Miro is an amazing open source application designed specifically to consume vidcasts (it works with podcasts too). Here's a screenshot where I've subscribed to some of these "channels" (yes, I have a lot of catching up to do!).

You may be wondering if this really is a huge deal. I think it is. Miro simplifies and automates the process and makes it so simple and easy. Every time you start miro, it'll tell you of the latest content available and ask if you want to download it. And the quality is generally much better what with being able to view it full screen and it also has nifty features like remembering where you left of in case you have to pause midway through etc... The one downside is that it has to download the video bits as opposed to streaming it through flash (as is common on many sites since the emergence of youtube). So for the bandwidth constrained it can be a bit of an issue. But then again, flash still has some issues on Linux and some of the videos don't play. Plus, looks like Microsoft recently converted to Silverlight which doesn't work on Linux (haven't looked into Moonlight). So most likely you'd end up having to download it anyway.
I've only mentioned few channels, but as you can imagine, there's tons of them around the web. Miro has a guide built-in which showcases some of them. Apart from tech content, many universities like Berkeley and Princeton are broadcasting some of their lectures and events. So there's definitely no lack of content. Just need to make time!
Overall, I love Miro and can't say enough good things about it. Kudos to the guys who've developed it.
Thursday, December 20, 2007
Re: Growing Pains
I guess it started with the .Net guys getting aggressive with new features like annotations, generics, delegates and now Linq. They are becoming more dynamic. Something to watch out for.
I think the fact that .Net is a closed source platform controlled by Microsoft is a huge factor in them being able to be so aggressive. It seems like today, when everything is moving towards getting open sourced, this should be seen as a huge red flag. And in some sense I feel that way, but I mean you really have to marvel at the stuff they're doing. When you read the Evolution of LINQ you see some really neat concepts like Extension Methods and how they've used a previous language feature (Attributes) to actually implement it.
Regarding going the dynamic direction. I'm not sure that's necessarily true in the "core language/platform philosophy" sense. Both .Net and Java were designed from the ground up to be strong typed and will stay that way. I think it's more about abstracting out some tedious typing when it's possible for the compiler to infer the type... i.e. it's just syntactic sugar. It's especially useful when dealing with generics (and the endless <>s). So it's still going to all be the same under the covers, unlike in dynamic languages where there is no type safety at all. (Again it's interesting to see how var in C# came about as a necessity for another feature... Annonymous Types... which were needed for LINQ).
Java had to respond and got annotations and generics. Generics has been a mess with wildcards. Closures seems to be going down that route. If only we get something thats simpler and yet extensible. The memory model is simpler and concurrency API has also been a great addition.
Lets see how long before Java steals LINQ and related features ;) They're still arguing about closures and how the generics implementation was overly complicated (ppt). Wonder how long the insane backward compatibility requirement will continue. Also when Java was open sourced last year there was general optimism that there would be a lot more innovations to the language. But has it just cause a lot more arguments and disagreements about the direction? Java 5 was big release, but since then there hasn't been anything major.
My 2 cents for the year.
I think the fact that .Net is a closed source platform controlled by Microsoft is a huge factor in them being able to be so aggressive. It seems like today, when everything is moving towards getting open sourced, this should be seen as a huge red flag. And in some sense I feel that way, but I mean you really have to marvel at the stuff they're doing. When you read the Evolution of LINQ you see some really neat concepts like Extension Methods and how they've used a previous language feature (Attributes) to actually implement it.
Regarding going the dynamic direction. I'm not sure that's necessarily true in the "core language/platform philosophy" sense. Both .Net and Java were designed from the ground up to be strong typed and will stay that way. I think it's more about abstracting out some tedious typing when it's possible for the compiler to infer the type... i.e. it's just syntactic sugar. It's especially useful when dealing with generics (and the endless <>s). So it's still going to all be the same under the covers, unlike in dynamic languages where there is no type safety at all. (Again it's interesting to see how var in C# came about as a necessity for another feature... Annonymous Types... which were needed for LINQ).
Java had to respond and got annotations and generics. Generics has been a mess with wildcards. Closures seems to be going down that route. If only we get something thats simpler and yet extensible. The memory model is simpler and concurrency API has also been a great addition.
Lets see how long before Java steals LINQ and related features ;) They're still arguing about closures and how the generics implementation was overly complicated (ppt). Wonder how long the insane backward compatibility requirement will continue. Also when Java was open sourced last year there was general optimism that there would be a lot more innovations to the language. But has it just cause a lot more arguments and disagreements about the direction? Java 5 was big release, but since then there hasn't been anything major.
My 2 cents for the year.
Sunday, December 16, 2007
Growing Pains
These are pretty exciting times. A lot of languages are being extended to add more features...
I guess it started with the .Net guys getting aggressive with new features like annotations, generics, delegates and now Linq. They are becoming more dynamic. Something to watch out for.
Java had to respond and got annotations and generics. Generics has been a mess with wildcards. Closures seems to be going down that route. If only we get something thats simpler and yet extensible. The memory model is simpler and concurrency API has also been a great addition.
C++ seems be following on Java's line with a similar memory model. I dont know what else is there but C++Ox should be big.
There seem to be a lot of changes coming into Javascript and they want to make it much more Java like. Just heard a talk on the proposed changes and it seems much more complicated (read crappy). There seem to be so many new keywords that it just does not make sense.
Is it time to move to a language like Scala? Cause I've not been able to leave static checking for Ruby yet. Hey why not just listen to Paul Graham and code in Lisp :)
I guess it started with the .Net guys getting aggressive with new features like annotations, generics, delegates and now Linq. They are becoming more dynamic. Something to watch out for.
Java had to respond and got annotations and generics. Generics has been a mess with wildcards. Closures seems to be going down that route. If only we get something thats simpler and yet extensible. The memory model is simpler and concurrency API has also been a great addition.
C++ seems be following on Java's line with a similar memory model. I dont know what else is there but C++Ox should be big.
There seem to be a lot of changes coming into Javascript and they want to make it much more Java like. Just heard a talk on the proposed changes and it seems much more complicated (read crappy). There seem to be so many new keywords that it just does not make sense.
Is it time to move to a language like Scala? Cause I've not been able to leave static checking for Ruby yet. Hey why not just listen to Paul Graham and code in Lisp :)
Tuesday, November 20, 2007
Profiling - Just works
I've been trying to set up a profiler for Java development.
I use Eclipse primarily and my first choice was the Eclipse project TPTP. However the damn thing just refused to work on my machine(Windows 32). I needed to primarily attach to externally launched Java programs. The Agent Controller (which collects profiling data) sample scripts works. But Eclipse is still not able to find the Java process. And the same installation/setup steps worked on another machine. But memory profiling did not work there!
That's when I tried the latest RC build of Netbeans. They bundle their Profiler with the IDE so no need to install anything separately. They have a pretty nice UI wizard which gives directions to start the java application for profiling. And guess what.. it Just Works. Though some of their UI is not the best like UML interaction diagrams in Eclipse who cares. Atleast I am getting some profiling data.
Maybe I'll try Netbeans as my main IDE once its released.
I use Eclipse primarily and my first choice was the Eclipse project TPTP. However the damn thing just refused to work on my machine(Windows 32). I needed to primarily attach to externally launched Java programs. The Agent Controller (which collects profiling data) sample scripts works. But Eclipse is still not able to find the Java process. And the same installation/setup steps worked on another machine. But memory profiling did not work there!
That's when I tried the latest RC build of Netbeans. They bundle their Profiler with the IDE so no need to install anything separately. They have a pretty nice UI wizard which gives directions to start the java application for profiling. And guess what.. it Just Works. Though some of their UI is not the best like UML interaction diagrams in Eclipse who cares. Atleast I am getting some profiling data.
Maybe I'll try Netbeans as my main IDE once its released.
Tuesday, September 04, 2007
Fishy Serialization
In Java, "Object Serialization supports the encoding of objects and the objects reachable from them, into a stream of bytes". This representation of the object can then be used for purposes like persisting on disk or passing of objects over the network. To serialize an object the class needs to implement the Serializable interface which is a marker interface with no methods defined. Optionally the class may define "readObject" and "writeObject" methods which will be used in the serialization process as defined in Specification.
The signature of the read/write Object methods is what struck me recently(this implies that I've been reading serialization related code before and not realised this). The modifier is private which means that no other instance should be able to invoke that method! And yet its invoked somehow. Time for some hacking...
For a dummy class Dog the stack trace to call the writeObject from SerializeTest.main was:
java.lang.RuntimeException
at foo.bar.Dog.writeObject(SerializeTest.java:81)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
at foo.bar.SerializeTest.main(SerializeTest.java:23)
The ObjectOutputStream.writeObject is invoked from the main method and after lots of calls ObjectStreamClass.invokeWriteObject is called which does some reflection The writeObject method is dynamically invoked there. The interesting part of the implementation is:
void invokeWriteObject(Object obj, ObjectOutputStream out) {
writeObjectMethod.invoke(obj, new Object[]{ out });
}
writeObjectMethod is a member variable in ObjectStreamClass of type java.lang.reflect.Method
and is set as:
writeObjectMethod = getPrivateMethod(cl, "writeObject",
new Class[] { ObjectOutputStream.class },
Void.TYPE);
The definition of ObjectStreamClass.getPrivateMethod is:
/**
* Returns non-static private method with given signature defined by given
* class, or null if none found. Access checks are disabled on the
* returned method (if any).
*/
private static Method getPrivateMethod(Class cl, String name, Class[] argTypes,
Class returnType) {
Method meth = cl.getDeclaredMethod(name, argTypes);
meth.setAccessible(true);
int mods = meth.getModifiers();
return ((meth.getReturnType() == returnType) && ((mods & Modifier.STATIC) == 0) &&
((mods & Modifier.PRIVATE) != 0)) ? meth : null;
}
}
And there is the call to the method which does all that magic - Method.setAccessible.
The javadoc for the method says:
"A value of true indicates that the reflected object should suppress Java language access checking when it is used"
Using Reflection and with proper access its possible to even call private methods. This was something cool that I've learnt in a long time. Certainly makes Java more dynamic in nature. Now I'll have to read more on the Java security API soon.
The signature of the read/write Object methods is what struck me recently(this implies that I've been reading serialization related code before and not realised this). The modifier is private which means that no other instance should be able to invoke that method! And yet its invoked somehow. Time for some hacking...
For a dummy class Dog the stack trace to call the writeObject from SerializeTest.main was:
java.lang.RuntimeException
at foo.bar.Dog.writeObject(SerializeTest.java:81)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
at foo.bar.SerializeTest.main(SerializeTest.java:23)
The ObjectOutputStream.writeObject is invoked from the main method and after lots of calls ObjectStreamClass.invokeWriteObject is called which does some reflection The writeObject method is dynamically invoked there. The interesting part of the implementation is:
void invokeWriteObject(Object obj, ObjectOutputStream out) {
writeObjectMethod.invoke(obj, new Object[]{ out });
}
writeObjectMethod is a member variable in ObjectStreamClass of type java.lang.reflect.Method
and is set as:
writeObjectMethod = getPrivateMethod(cl, "writeObject",
new Class[] { ObjectOutputStream.class },
Void.TYPE);
The definition of ObjectStreamClass.getPrivateMethod is:
/**
* Returns non-static private method with given signature defined by given
* class, or null if none found. Access checks are disabled on the
* returned method (if any).
*/
private static Method getPrivateMethod(Class cl, String name, Class[] argTypes,
Class returnType) {
Method meth = cl.getDeclaredMethod(name, argTypes);
meth.setAccessible(true);
int mods = meth.getModifiers();
return ((meth.getReturnType() == returnType) && ((mods & Modifier.STATIC) == 0) &&
((mods & Modifier.PRIVATE) != 0)) ? meth : null;
}
}
And there is the call to the method which does all that magic - Method.setAccessible.
The javadoc for the method says:
"A value of true indicates that the reflected object should suppress Java language access checking when it is used"
Using Reflection and with proper access its possible to even call private methods. This was something cool that I've learnt in a long time. Certainly makes Java more dynamic in nature. Now I'll have to read more on the Java security API soon.
Wednesday, May 09, 2007
wget Google videos
Google has some amazing tech videos at their site by the user Google engEDU. And they even allow for downloads which is great for me.
But I prefer downloading files using wget to be able to resume downloads later. You can't just wget the video link url's as is because they have & characters which cause wget to try to download them as separate files. Instead try something like this for the "OSS Speaker Series: The State of the Linux Kernel" video..
wget -c --output-document=MortonLinuxKernel.mp4 "http://vp10.video.l.google.com/videodownload?version=0&secureurl=twAAAOFdafTKyCsBI7E0BCCT6060NjqUP0-3g9pfM0xl5X1YO8a1zhU5ArUNYf8PLb44VqTIrTR2hntorTVWAEL6bqWkChEIIVPqNeHV5F4PRqoHXwlvZRC0_giNoVtliPIDsfE7zAzQSPok2b8ShvvgxJVI3T3WoPwGtr6Vvmwfjj18i9wTbaZD_JGXpTjD2kJrvVIenN5CSTRBbXYMKR49YyVYLdRNu9BuY924qZaDV4zEd9YFUsoCP42JkguszqVlOg&sigh=hEHjkZDlhZrMiZnAQrs8O55mFdo&begin=0&len=4897661&docid=1742374580386548257&rdc=1"
But I prefer downloading files using wget to be able to resume downloads later. You can't just wget the video link url's as is because they have & characters which cause wget to try to download them as separate files. Instead try something like this for the "OSS Speaker Series: The State of the Linux Kernel" video..
wget -c --output-document=MortonLinuxKernel.mp4 "http://vp10.video.l.google.com/videodownload?version=0&secureurl=twAAAOFdafTKyCsBI7E0BCCT6060NjqUP0-3g9pfM0xl5X1YO8a1zhU5ArUNYf8PLb44VqTIrTR2hntorTVWAEL6bqWkChEIIVPqNeHV5F4PRqoHXwlvZRC0_giNoVtliPIDsfE7zAzQSPok2b8ShvvgxJVI3T3WoPwGtr6Vvmwfjj18i9wTbaZD_JGXpTjD2kJrvVIenN5CSTRBbXYMKR49YyVYLdRNu9BuY924qZaDV4zEd9YFUsoCP42JkguszqVlOg&sigh=hEHjkZDlhZrMiZnAQrs8O55mFdo&begin=0&len=4897661&docid=1742374580386548257&rdc=1"
Friday, March 09, 2007
Playing with Javascript
I've pasted an early version of a recursive function to walk the DOM from a particular node in Javascript. If you run the code though.. your browser will hang as it goes into a recursive loop. So whats wrong with the code?
<html>
<head>
<script type="text/javascript" language="javascript">
function walk(node) {
if (node) {
//do something with node
for (i=0; i<node.childNodes.length; i++) {
walk(node.childNodes[i]);
}
}
}
</script>
</head>
<body onLoad="walk(document.body)">
<a href="http://www.parivartana.org">parivartana.org</a>
</body>
</html>
The variable i in the for loop should be declared as 'var i' to fix the behaviour. Thats when I realised that I should not really code in Javascript assuming that it is a subset of Java. (But being as lazy as I am never really studied the language).
Then I came across some fantastic videos on Javscript by Douglas Crockford at the YUI theatre which is a part of the Yahoo Javascript library YUI. Some of the features of the language are explained really well. Some key features are Objects as containers, Prototypal Inheritance and Lamda. He also explains some browser and Javascript quirks.
Now I am wondering if Javascript should be a part of my resume!
One of his recommendations is to favour minification ie removing of whitespace to reduce download size versus obfuscation. Google actually always heavily obfuscate their Javascript. Also as part of the Google Web Toolkit, the deployable code is also obfuscated. So thats a debateable topic. Time to read some GWT generated code then.
<html>
<head>
<script type="text/javascript" language="javascript">
function walk(node) {
if (node) {
//do something with node
for (i=0; i<node.childNodes.length; i++) {
walk(node.childNodes[i]);
}
}
}
</script>
</head>
<body onLoad="walk(document.body)">
<a href="http://www.parivartana.org">parivartana.org</a>
</body>
</html>
The variable i in the for loop should be declared as 'var i' to fix the behaviour. Thats when I realised that I should not really code in Javascript assuming that it is a subset of Java. (But being as lazy as I am never really studied the language).
Then I came across some fantastic videos on Javscript by Douglas Crockford at the YUI theatre which is a part of the Yahoo Javascript library YUI. Some of the features of the language are explained really well. Some key features are Objects as containers, Prototypal Inheritance and Lamda. He also explains some browser and Javascript quirks.
Now I am wondering if Javascript should be a part of my resume!
One of his recommendations is to favour minification ie removing of whitespace to reduce download size versus obfuscation. Google actually always heavily obfuscate their Javascript. Also as part of the Google Web Toolkit, the deployable code is also obfuscated. So thats a debateable topic. Time to read some GWT generated code then.
Thursday, December 21, 2006
Re: Select you crazy Query
Are you saying the first query is wrong cause it did not get the results you expected? Cause I don't see anything technically wrong with it. A left outer join does not mean that at the end of the query (whatever it may be), you will get all foos. What you get in the end depends on your WHERE clause.
Break the first query down and you will see how it was arrived at. The cross product of the tables based on the ON clause of the LEFT OUTER JOIN "did" contain foo(1) but the WHERE clause which was applied over the cross product eliminated that record. Hence the result.
The behavior is standard and not MySQL specific. Both those queries on a different engine should return the same behavior. Also, I don't see why the ON clause should remember the composite primary key.
More on left outer join here.
Break the first query down and you will see how it was arrived at. The cross product of the tables based on the ON clause of the LEFT OUTER JOIN "did" contain foo(1) but the WHERE clause which was applied over the cross product eliminated that record. Hence the result.
The behavior is standard and not MySQL specific. Both those queries on a different engine should return the same behavior. Also, I don't see why the ON clause should remember the composite primary key.
More on left outer join here.
Tuesday, December 19, 2006
Select you crazy Query
Lets try a small SQL quiz this time. We have two tables foos and bars with the definition below..
CREATE TABLE foos ( foo_id INT NOT NULL, PRIMARY KEY (foo_id) ) ENGINE=InnoDB;
CREATE TABLE bars ( foo_id INT NOT NULL, bar_id CHAR(1) NOT NULL, PRIMARY KEY (foo_id, bar_id), FOREIGN KEY (foo_id) REFERENCES foos(foo_id)) type=InnoDB;
And lets do some sample data inserts..
INSERT INTO foos VALUES (1), (2), (3), (4);
INSERT INTO bars VALUES (1, 'a'), (2, 'b'), (3, 'b'), (3, 'c');
Now write query to give me all foos and those bars who have a bar_id 'b' for the same foo_id. Seems like an easy OUTER JOIN. This is what I came up with initially..
SELECT * FROM foos LEFT OUTER JOIN bars ON foos.foo_id = bars.foo_id WHERE bar_id = 'b' OR bar_id IS NULL;
And the result set was..
But the result set obtained is wrong because we did not get all the foos. Get back to the query then to obtain the result set below..
For the correct query just make a minor change to the above SELECT
SELECT * FROM foos LEFT OUTER JOIN bars ON foos.foo_id = bars.foo_id AND (bar_id = 'b' OR bar_id IS NULL);
I did not have enough time to search for the actual reason for this behaviour though and am not even sure if this is standard or MySql specific.
In table bars the primary key is a composite key between foo_id and bar_id. When foo_id is compared in the ON clause, it appears as if the rest of the primary key is forgotten. foos (1) joins with something like bars (1, NULL) and so the WHERE clause fails. When the ON contains all the clauses for the whole composite key, the LEFT OUTER JOIN behaves as expected.
That gives a whole new perspective to outer joins when dealing with composite primary keys then.
CREATE TABLE foos ( foo_id INT NOT NULL, PRIMARY KEY (foo_id) ) ENGINE=InnoDB;
CREATE TABLE bars ( foo_id INT NOT NULL, bar_id CHAR(1) NOT NULL, PRIMARY KEY (foo_id, bar_id), FOREIGN KEY (foo_id) REFERENCES foos(foo_id)) type=InnoDB;
And lets do some sample data inserts..
INSERT INTO foos VALUES (1), (2), (3), (4);
INSERT INTO bars VALUES (1, 'a'), (2, 'b'), (3, 'b'), (3, 'c');
Now write query to give me all foos and those bars who have a bar_id 'b' for the same foo_id. Seems like an easy OUTER JOIN. This is what I came up with initially..
SELECT * FROM foos LEFT OUTER JOIN bars ON foos.foo_id = bars.foo_id WHERE bar_id = 'b' OR bar_id IS NULL;
And the result set was..
| foo_id | foo_id | bar_id |
|---|---|---|
| 2 | 2 | b |
| 3 | 3 | b |
| 4 | NULL | NULL |
3 rows in set (0.00 sec) | ||
But the result set obtained is wrong because we did not get all the foos. Get back to the query then to obtain the result set below..
| foo_id | foo_id | bar_id |
|---|---|---|
| 1 | NULL | NULL |
| 2 | 2 | b |
| 3 | 3 | b |
| 4 | NULL | NULL |
4 rows in set (0.00 sec) | ||
For the correct query just make a minor change to the above SELECT
SELECT * FROM foos LEFT OUTER JOIN bars ON foos.foo_id = bars.foo_id AND (bar_id = 'b' OR bar_id IS NULL);
I did not have enough time to search for the actual reason for this behaviour though and am not even sure if this is standard or MySql specific.
In table bars the primary key is a composite key between foo_id and bar_id. When foo_id is compared in the ON clause, it appears as if the rest of the primary key is forgotten. foos (1) joins with something like bars (1, NULL) and so the WHERE clause fails. When the ON contains all the clauses for the whole composite key, the LEFT OUTER JOIN behaves as expected.
That gives a whole new perspective to outer joins when dealing with composite primary keys then.
Subscribe to:
Posts (Atom)
