Friday, November 28, 2008

Using VIM in troubleshooting JAVA application

After trying many Text Editor available on Windows as TexPad, UltraEdit, Wordpad, Notepad, etc. , finally I decided to use vim, an enhanced version of unix vi. Vim is never been an easy choice but once you master it, it is wonderful, it give you high productivity. Also it is free.
Some basic vi commands can be found in http://www.cs.uiuc.edu/class/fa07/cs225/calendar/vim.pdf.
During my daily work, I often have to troubleshoot complex JAVA application. Sometime I get exception with full JAVA stack printout, but the application is provided by vendor without source code so there is very difficult to find a root cause.
There is a tool called JAD that can decompile JAVA classes. Because my primary editor is VIM so I decided to integrate the JAD into VIM. Googling a while, I found vim JAD plugin, that display decompiled java class whenever we open the class file. However JAVA application(s) are mostly provided in form of several jar, zip, ear package so it is not so convenient.
There is luckily zip plugin that is part of vim installation and can browse zip, jar, ear package and display content of selected file inside the package when we hit enter. Modify just few lines of this plugin, I am able to browse content of jar, zip file and view a decompiled inside JAVA class.
The steps is as follows (for version 7.2, that was installed in D:\Vim\)

1. open D:\Vim\vim72\autoload\zip.vim and change
fun! zip#Read(fname,mode)
...
  exe "silent r! ".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fname,1)
...
endfun
to
fun! zip#Read(fname,mode)
...
 if fname =~ '.class$'
   exe "silent r! ".g:zip_unzipcmd." -o -- ".s:Escape(zipfile,1)." ".s:Escape(fname,1)
   exe "silent r! jad -lnc -p ".s:Escape(fname,1)
 else
   exe "silent r! ".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fname,1)
 endif
...
endfun
2. download unzip.exe, jad.exe and put them in the PATH
3. start vim and open a jar file, a list of files inside the jar file will be displayed
4. select one class file and hit ENTER The '-lnc' option of JAD display line number of original source code as comment on the left side of decompiled code so it can be used to identify which part of code cause an exception.

Saturday, November 8, 2008

Simple Python Syntax

Start interpreter and print out something then exit
C:\python
ActivePython 2.5.2.2 (ActiveState Software Inc.) based on
Python 2.5.2 (r252:60911, Mar 27 2008, 17:57:18) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print 'hello world'
hello world
>>> print 1+2+3
6
>>> exit()
Run a script in the interpreter
To run a script within Python interpreter use execfile(path), it is useful for people who use Jython, because startup time of JVM is horrible . e.g
>>execfile('sample.py')
Create string from a template
This is one of my most frequently used statement, Python follow style of C printf function
>>> "my name is %s, my age is %d" % ("Goto",30)
'my name is Goto, my age is 30'
>>>
Ruby has the same function
irb(main):004:0> "my name is %s, my age is %d" % ["Goto",30]
=> "my name is Goto, my age is 30"
irb(main):005:0>
but there is nicer way to do it
irb(main):005:0> name,age = "Goto",31
=> ["Goto", 31]
irb(main):006:0> "my name is #{name}, my age is #{age}"
=> "my name is Goto, my age is 31"
Create a substring from a string
Python has nice methods get a substring from string
>>> s='hello world'
>>> s[0]
'h'
>>> s[0:10] #substring from a position(inclusive) until other (non inclusive)
'hello worl'
>>> s[2:] #substring to end of string
'llo world'
>>> s[:2] #substring from start until other (non inclusive)
'he' 
>>> s[-2:] #negative position indicates position from end of the string
'ld'
The equivalent in Ruby would be
$ irb
>> s="hello world"
=> "hello world"
>> s[0]
=> 104
>> s[0..0]
=> "h"
>> s[0..(10-1)] #unlike Python, Ruby includes the end position
=> "hello worl"
>> s[2..-1] # -1 indicate relative position from end
=> "llo world"
>> s[0..(2-1)]
=> "he"
>> s[-2..-1]
=> "ld"
Unlike Ruby, Python still throw out of range exception for single indice operation
>>> s[20]
Traceback (most recent call last):
  File "", line 1, in 
IndexError: string index out of range
>>> s[20:30] # this is OK as it consider as slice operation
''
String is immutable
Unlike Ruby, Python string can not be changed directly
>>> s[0:5]
'hello'
>>> s[0:5]="bye"
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'str' object does not support item assignment
>>> s1 = "bye" + s[5:] # to achieve the same goal we need create string from other string 
>>> print s1
bye world
In Ruby we can do
>> s[0..4]="bye"
=> "bye"
>> print s
bye world=> nil
As string is considered value object, create new string instead of changing an existing express that concept more clearly.
List and tuple
Python has tuple and list for representation of variable size array of items. Tuple is immutable array while list is mutable. People think that list is intended for homogeneous while tuple is for non-homogeneous, but this is convention only is not enforced by the language. However some api accept only tuple as argument e.g. String format %, that sometime lead to a confusion. In contras Ruby has only Array.
example of tuple
>>> y=('a',2)
>>> y[1]=1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> y
('a', 2)
example of list
>>> x=['a',2]
>>> x[1]=1
>>> x
['a', 1]
iterate over list or tuple
>>> items = ('a','b',2)
>>> for e in items:
...   print e
...
a
b
2
Hash aka dictionary
Python has hash structure called dictionary
>>> h = {1:'a',2:'b',3:'c'}
>>> h.__class__
<type 'dict'>
>>> h[3] = 'z'
>>> h
{1: 'a', 2: 'b', 3: 'z'}
>>>
iterate over dictionary
>>> for k,v in h.iteritems():
...   print "%d=>%s" % (k,v)
...
1=>a
2=>b
3=>z
h.items() also works well
Class, Object, method
Class is defined using class keyword, name of a class can start lower case or upper case character, which is different from Ruby. Ruby requires name of class start with upper case character.
However the convention is that, name of built-in class as string, unicode, list, tuple start with lower case character while user-defined class starts with upper case.
example of built-in class
>>> y = ('a',2)
>>> y.__class__
<type 'tuple'>
>>> y.__class__ == tuple
True
>>> z = tuple(y)
>>> z
('a', 2)
example of user defined class
>>> class Foo:
...   def m(self):
...     print self.__class__
...
>>>
>>> Foo().m()
__main__.Foo
>>>
Module
Every Python script store in a file is a module, the name of the file is module name.
$ cat hello.py
def say(whom):
  return "hello %s" % whom
To use method defined in a module, just import the module and call the function preceding by the module name plus '.'
>>> import hello
>>> hello.say('world')
'hello world'
It is also common to mix module methods into current name space, so we can call method without typing module name
>>> from hello import *
>>> say('moon')
'hello moon'
>>>
Parameters
Beside normal position based parameters, Python has two extra forms of passing parameters to a function *params and **params.
The first form is argument list, in which caller pass a list parameters and calling function receives them in form of an array.
 def foo(*numbers):
      return sum(numbers)
 
print foo(23, 42)        # prints: 65
The second form is name based, in which caller pass a list name,value pairs and calling function receives then as a hash map.
def bar(**options):
  if "verbose" in options and options["verbose"]:
     print "verbose is ON"
  else:
     print "verbose is OFF"

bar(verbose=True) # print: "verbose is ON"
bar(verbose=False) # print: "verbose is OFF"
bar(force=True) # print: "verbose is OFF"


Closures
Python closures