Dealing with Java Hell using JarJar life boat

Okay, so I wanted to use Hex.encodeHexString method from org.apache.commons.codec.binary.Hex (commons-codec-1.6.jar)library to generate encoded singnature. I was able to do this in plain Java, but not in Android. I googled for a while and found out this ticket about Android not supporting the latest versions of commons-codec-1.6.jar.The solutions was to use magical "jarjar" ! But How ??? Again, I googled and come across this and this, and I came up with solution to solve mystery of using  Hex.encodeHexString method in code running on Android (Dalvik VM). Android uses old version of commons-codec jar which doesn't define org.apache.commons.codec.binary.Hex.encodeHexString method signature. Even if you add new commons-codec-1.6.jar to build path of project, code will try to refer to built-in commons-codec not the new one that you added in build path. But, if you change the package name/namespaces for commons-codec-1.6.jar, then you can easily reference from your code and finally can use Hex.encodeHexString. So, you have to create a custom jar with modified package name structure.

Here is how you can spin a new custom jar, say
commons-codec-1.6-jarjar.jar:

Step-1: Create a build.xml like follows:
<project name="generate-jarjar">
    <property name="jarjarfile" value="commons-codec-1.6-jarjar.jar"/>
    <path id="classpath">
      <pathelement location="jarjar-1.4.jar"/>
      <pathelement location="asm-2.2.3.jar"/>
    </path>
    <taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask"   classpathref="classpath"/>
    <delete file="${jarjarfile}"/>
    <jarjar destfile="${jarjarfile}">
    <zipfileset src="commons-codec-1.6.jar"/>
    <rule pattern="org.apache.**" result="org.jarjar.apache.@1"/>
    </jarjar>
</project>
Step-2: Run command "ant" from command line. This build script will generate a new jar  commons-codec-1.6-jarjar.jar, which you can add in your build path and use this new jar to import from.

You can download all the files mentioned in above script and build.xml from here.








Setting up .netrc file on Mac OS X (Lion) for Git

Couple of days ago, I started using Google's code projects for Git as well. It required me to setup and use .netrc file. Here are steps I took:

  1. CD to $HOME directory and typing on command line 
  2. $ cd ~
  3. Create .netrc file
  4. $ vi .netrc
  5. Add these line to .netrc
  6. machine code.google.com login <username> password <password>
  7. Set permissions "chmod 600 .netrc" to make sure that no one else is able to access this file
  8. $ chmod 600 .netrc
  9. Now, you should be able to push and pull from remote git repo without having to enter password every time.


Android NDK vs Android SDK

This post throws some light on when to use Android SDK over NDK or vice versa. This is a on-going post and will be updated as my research continues on SDK/NDK comparison. Please leave comments if you want to contribute in this list.


NDK

  • Pros
    • Enables legacy code re-use between iOS and Android platforms
    • Good for implementing CPU intensive operations that don't allocate much memory like signal processing, physics simulations
  • Cons
    • Seems to introduce security and stability issues
    • NDK activities disables SDK feature use like broadcast receivers, content providers, services. Some better SDK libraries becomes un-usable in NDK.

SDK

  • Pros
    • Java has superior memory management model
    • Superior threading model
    • Better exception handling model
    • Rich set of libraries
    • Superior support for unicode characters
  • Cons




[GIT] How to apply Pull Request

I use "Fetch and Merge" approach to apply Pull request from a forked repo to main repo. What is actually done in this approach is to fetch changes from the forked repo in main repo working copy and merge the changes. Once changes from forked repo are merged in main repo working copy, push it to remote main repo as usual.

This process is achieved in these steps:

1- CD to main.git repo working directory
$ git checkout master

2- Add forked repo forked.git in remotes
$ git remote add <forked> <forked.git>


3- Fetch changes from forked.git
$ git fetch forked

4- Merge into master branch
$ git merge <forked>/<master>

5- Push the merged changes to main.git
$ git push origin master 

How to List Users and Groups in OSX (Mac-Lion)

To list the users :
dscl . -list /Users
To list the groups:
dscl . -list /Groups 

How to Stop a Jenkins Server

Simply, unload the jenkins from Launch daemon using:

sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist

How did I setup SSL with HTTPClient-4.1.2

I've been struggling to get this working for about 2 days now. I was able to POST a request directly from sockets, but it took me a while to see it working with HTTPClient-4.1.2. There are different variants out there in google for legacy HTTPClient and less than 4.1.x.
The key was to specify TrustManager and KeyManager while initializing SSLContext.

Step-1: First, you have to initialize SSLContext like this:

SSLContext ctx = SSLContext.getInstance("TLS");

Step-2: Getting TrustManager. Java look into its trust managers to check against authorized Certification Authorities(CA). Default trust store in Java is "jks". This is how you can get trust manager:
TrustManager[] getTrustManagers(String trustStoreType, InputStream trustStoreFile, String trustStorePassword) throws Exception {
KeyStore trustStore = KeyStore.getInstance(trustStoreType);
trustStore.load(trustStoreFile, trustStorePassword.toCharArray());
TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmfactory.init(trustStore);
return tmfactory.getTrustManagers();
}

It should be called as:
TrustManager[] trustManagers = getTrustManagers("jks", new FileInputStream(new File("/Library/Java/Home/lib/security/cacerts")), "changeit");

/Library/Java/Home/lib/security/cacerts is the default path to trust managers in Mac OSX

Step-3: Getting KeyManager: This is where your client certificates are stored. KeyManager in the code can be retrieved as :
KeyManager[] keyManagers = getKeyManagers("pkcs12", new FileInputStream(new File("clientCertificate.p12")), "password");

You have to get KeyManagers using KeyManagerFactory like this:

KeyManager[] getKeyManagers(String keyStoreType, InputStream keyStoreFile, String keyStorePassword) throws Exception {
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(keyStoreFile, keyStorePassword.toCharArray());
KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmfactory init(keyStore, keyStorePassword.toCharArray());
return kmfactory.getKeyManagers();
}

Step-4: Once you have TrustManager and KeyManager ready, pass them in SSLContext:
ctx.init(keyManagers, trustManagers, new SecureRandom());

Step-5: Now create a SSLSocketFactory object using SSLContext object:
SSLSocketFactory sf = new SSLSocketFactory(ctx, new StrictHostnameVerifier());

Step-6: Assign Scheme to the HttpClient:
DefaultHttpClient httpclient = new DefaultHttpClient();
ClientConnectionManager manager = httpclient.getConnectionManager();
manager.getSchemeRegistry().register(new Scheme("https", 443, sf));

Done !
Now use this httpclient in HttpPost, HttpGet ….

Scheduling Repeating Local Notifications using Alarm Manager

Learn about Scheduling Repeating Local Notifications using Alarm Manager in this post .