Showing posts with label ant. Show all posts
Showing posts with label ant. Show all posts

Quick way to untar and bunzip files in java

Have you ever felt a need to deal with bzip2 compressed tarballs in Java? Recently I compressed a lot of test resources in our source tree using bzip2 compression. The resources were static and were meant to change very rarely. bzip2 was the best choice in terms of amount of compression. What it also meant was my SVN download of the source tree would take much lower time. I planned to extract the resources and make them available at runtime while running tests.

If you already know, there is no way to handle bzip compression in Java core API. But at the back of my mind I knew that you can create bzipped tarballs using Ant. So I looked at the Ant tasks and figured that there was untar task which can be instructed to also process it through bzip2 uncompression.

Here is the code snippet that can untar and bunzip the file using Java code.
Untar untar = new Untar();
untar.setSrc(new File("./src/test/resources/files.tar.bz2"));
untar.setDest(new File("./target"));
UntarCompressionMethod compression = new UntarCompressionMethod();
compression.setValue("bzip2");
untar.setCompression(compression);
untar.setOverwrite(true);
untar.execute();

Also make sure that you put ant jar on the classpath.

Maven users can simply add following dependency,

<dependency>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant</artifactId>
   <version>1.7.0</version>
   <scope>test</scope>
</dependency>

Ant / Junit and Class Loaders

Have you ever come across situations where you need to load external resources in your Junit tests? I generally prefer loading external resource files from the classpath. So I add the resources on the classpath and in the test case I look up the resource using the ClassLoader.getResource(). If you are running the Junit tests using ant, you can run into all sorts of problems if you are trying to load resources from the classpath.

Ant runs each Junit test in its own class loader. This makes sure that any libraries on the ant's classpath wont interfere with the test's environment.

If you are using a class loader to load the resources, always use the immediate class loader to load the resource. Generally you can get the handle to class loader through
ClassLoader.getSystemClassLoader(). But if you try to load a resource using this class loader in the test case, JVM will try to load the resource using the system class loader. System class loader in this case is class loader for Ant. But unfortunately since Ant created a special class loader for the test, the system class loader does not contain the same classpath that you have configured in ant's build.xml for running tests (Ideally you would have added the directories containing the resources that you need to dynamically look up in test cases here). You would end up with a resource not being found.

To overcome this, always use immediate class loader, how to dot it?

use
MyTest.class.getClassLoader()

This ensures that we are getting the class loader that loaded test class. Which infact is the immediate class loader.

This also applies for any framework / API you write. Using immediate class loader makes sure that your framework would be testable in the multi classloader environements.