Sunday, January 30, 2011

Codility certificate

Recently I found out a cool site that allows programmers to verify their programming skills and recruiters to verify the programming skills of candidates. I did an exam and got silver certificate.  
http://codility.com/cert/view/cert3D8D4M-ZZC7578U6V78B8UE
 
As far as I can see each task has 2 types of solutions: n^2 that can get silver certificate as maximum and better 0^n or ln(n) solution that has a chance to get gold certificate.

Thursday, January 13, 2011

Get program entry point

Today I read the following discussion: How can I determine which class's `main` method was invoked at runtime?


The problem was to distinguish the entry point to the program, i.e. which class' main was used to start the program. The suggestion was obvious:

public static getMainClassName() {
   StackTraceElement[] elem = new Exception().getStackTrace();
   return elem[elem.length - 1].getClassName();
}

This solution is fine but it is correct for main thread only. How to detect the program entry point from other thread? Fortunately we have method getAllStackTraces() available in class Thread since java 1.5. So, the solution is to iterate over all threads, detect the main thread and return last element of its stack trace:

private static String getMainClassName() {
 Map map = Thread.getAllStackTraces();
 for (Map.Entry entry : map.entrySet()) {
  Thread thread = entry.getKey();
  if ("main".equals(thread.getName()) && "main".equals(thread.getThreadGroup().getName())) {
   StackTraceElement[] trace = entry.getValue();
   return trace[trace.length - 1].getClassName();
  }
 }
 return null;
}

This method can be called from any thread in the application. But it also has its limitation. Method getAllStackTraces() returns currently running threads. If main thread was terminated before the method is called the program entry point can not be found.

Tuesday, January 4, 2011

Access windows registry with pure java

Introduction

Java is a cross platform language and therefore does not support platform specific features. Windows has a special unique feature - registry. So, java cannot access registry. We have to use JNI or external processes (directly or indirectly) to do this.


Solution

But recently I found a cool Java feature: preferences implemented by class java.util.prefs.Preferences. Yes, I am eating my hat now! This feature was introduced to Java 1.4 and I did not know and have never used it! What's cool in this feature? Its implementation is platform specific. As always we can access abstract class java.util.prefs.Preferences and get its instances using several static method like userRoot(), systemRoot() and others. But the concrete implementation depends on current operating system. Class WindowsPreferences uses registry to store values. It declares several native methods: WindowsRegOpenKey, WindowsRegCloseKey, WindowsRegDeleteKey etc. Sounds good, doesn't it?

So I decided to abuse this class and implement access to registry utilizing these methods. It was not very simple task. The class WindowsPreferences uses only specific registry path: Software\Java Soft\Prefs under HKLM and HKCU. Class itself is package protected and cannot be nether inherited nor called. So, reflection is the only real option.


Implementation

I called my class Registry and decided to make it singleton. It contains static enum Hive that enumerates all standard registry hives (HKLM, HKCU, HKCR etc). It implements the following public methods:


  • keys(Hive hive, String path)
  • values(Hive hive, String path)
  • get(Hive hive, String path, String name)
  • createKey(Hive hive, String path)
  • put(Hive hive, String path, String name, String value)
  • removeKey(Hive hive, String path)
  • removeValue(Hive hive, String path, String name)


The implementation is based on invocation of private native methods declared in WindowsPreferences class using reflection:


private <R> R call(String methodName, Class[] types, Object[] args) {
  try {
    Method m = winPrefClazz.getDeclaredMethod(methodName, types);
    m.setAccessible(true);
    return (R)m.invoke(null, args);
  } catch (Exception e) {
    throw new RuntimeException(e);
  }
}



Here is the example how this method is used. This is what I would like to write:

int hresult = WindowsRegCloseKey(handle);

This is what I have to do instead:

int result = call("WindowsRegCloseKey", new Class[] {int.class}, new Object[] {handle});

Using reflection sometimes has some benefits. For example methods that enumerate registry keys and values are very similar but they call different native methods (e.g. WindowsRegEnumValue and WindowsRegEnumKeyEx). So methods childrenNamesSpi() and keysSpi() are almost duplicate in WindowsPreferences. Using reflection allows creating one implementation for both cases.



Limitations

Careful examining of the API exposed by registry class shows that it is limited to work with string values only: method put accepts value of string type, method get returns string. Unfortunately this is the limitation of current approach. Class WindowsPreferences is not designed to work with other value types. Native method WindowsRegSetValueEx works with string values only; attempt to retrieve value of other type using WindowsRegQueryValueEx returns null.



Conclusions

Java programmers are regular to use native libraries to utilize platform specific features. But sometimes some of the features are already implemented by JVM but just not exposed as a public API. Investigation of JDK classes and utilizing of reflection allows us to get access to windows registry with simple and very compact java code. The implementation deals with string values only that is a serious limitation but still can be used because most values stored in registry are strings. The suggested technique is most useful when code size is critical. For example for applications started using JNLP.

Full source code of Registry class and unit test may be found here.


References

I found this trick myself and wrote this article. Then I googled "read windows registry with java" and found at least 2 similar implementations:

http://lenkite.blogspot.com/2008/05/access-windows-registry-using-java.html
http://www.davidc.net/programming/java/reading-windows-registry-java-without-jni

I have no idea why I did not search web before writing the code... The advantage of my solution is that I implemented full API that can be used in any application while these guys just showed that this solution is possible.