Monday, October 11, 2010

Modifying the Unmodifiable Map

Some days back I needed to work on setting up the system environment variables. Well, actually the need was to add a new env variable to the system properties.

In Java how this works is, you can get all the system variables values using System.getenv(). This function returns a Map, key-value pair. But, this is read only. You cannot modify the map, say, to put in an extra env variable into the system properties.

If you try, you will get:

java.lang.IllegalAccessException: Class org.system.SystemTest can not access a member of class java.util.Collections$UnmodifiableMap with modifiers "private final"
at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
at java.lang.reflect.Field.doSecurityCheck(Unknown Source)
at java.lang.reflect.Field.getFieldAccessor(Unknown Source)
at java.lang.reflect.Field.get(Unknown Source)
at org.system.SystemTest1.main(SystemTest1.java:34)

So basically, the modifier of java.util.Collections$UnmodifiableMap class is set to false. This will not let you override the existing environment variables.

After going through lot of sites and scavenging the forums I came across the following "cool" code.

Class[] classes = Collections.class.getDeclaredClasses();
for(Class cl : classes) {
if("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
Field field = cl.getDeclaredField("m");
field.setAccessible(true);
Object obj = field.get(env);
Map map = (Map) obj;
map.put("NEW_PROPERTY", "NEW_PROPERTY_VALUE");
map.putAll(env);
}
}

This code changes the modifier field "m" to true and that will give you the liberty to change the unmodifiable map :)

Output:
Before:
(OS,Windows_NT)
(PROCESSOR_LEVEL,15)
(ANT_HOME,C:\apache-ant-1.7.1)
(windir,C:\WINDOWS)
(SystemRoot,C:\WINDOWS)
(asl.log,Destination=file;OnFirstLog=command,environment)
(NUMBER_OF_PROCESSORS,1)

After:
(OS,Windows_NT)
(PROCESSOR_LEVEL,15)
(ANT_HOME,C:\apache-ant-1.7.1)
(windir,C:\WINDOWS)
(SystemRoot,C:\WINDOWS)
(asl.log,Destination=file;OnFirstLog=command,environment)
(NUMBER_OF_PROCESSORS,1)
(NEW_PROPERTY,NEW_PROPERTY_VALUE)

No comments:

Post a Comment