Thursday, October 11, 2007

Java and Ant Properties Refresher

I occasionally need a certain built-in Java property for use in code or in an Apache Ant script and this blog entry is intended to make an easy-to-remember location for me to find a list of some of the properties that I use most often.

Some of the Java properties available from the call to System.getProperties() are listed in the Java Tutorial on System Properties. This resource lists only a small subset of the available properties, but the listed properties are among the most significant and more frequently used of the properties. These significant properties include file.separator, line.separator, path.separator, user.dir, and user.home.

The Javadoc API documentation for the System class has even more properties listed than the Java Tutorial, but not all of the available properties are listed (such as user.country, user.language, and user.timezone).

One of the best ways to view all of the available properties is to call System.getProperties() and iterate over the returned properties to see what is available. The code below shows how this is done and takes advantage of some Java SE 6 features in the process.

Java Code Listing for One Way to Display Available Properties

package properties;

import java.util.Enumeration;
import java.util.Properties;
import java.util.Set;

/**
 * Lists all Java system properties.  Uses
 * Properties.stringPropertyNames for convenience,
 * but this is a Java SE 6 feature and it shows only
 * properties in which both the key and the value
 * are String types.
 */
public class SystemPropertiesExample
{
  public static void main(final String[] aArgs)
  {
     System.out.println(
        "Welcome!  Here are your Java System properties:");
     Properties systemProperties = System.getProperties();
     Set propertyNames =
        systemProperties.stringPropertyNames();
     for ( final String propertyName : propertyNames )
     {
        String propertyValue =
           systemProperties.getProperty(propertyName);
        if ( propertyValue.isEmpty() )
        {
           propertyValue =
              "<<<empty string>>>";
        }
        System.out.println(  propertyName
                           + " = "
                           + propertyValue );
     }
  }
}

Of course, Java developers have been iterating over available properties since the beginning days of Java using java.util.Enumeration (not related to the enum introduced in Java 5) with the Properties.propertyNames() method, but the above code example demonstrates the new-to-Java-SE-6 Properties.stringPropertyNames() method in action.

Ant also makes it easy to access the Java system properties in addition to Ant's own built-in properties. The build.xml excerpt below demonstrates how easy it is to use Ant to display custom properties (defined in a separate build.properties file in this case), Ant’s built-in properties, Java-related properties, and even Java implementation-specific properties.

An Ant build.xml File that Displays Available Properties

<project name="SystemPropertiesExample"
default="buildJar"
basedir=".">

<property file="build.properties" />

<tstamp />

<target name="init">
<mkdir dir="${classes.dir}" />
</target>

<target name="clean">
<delete dir="${classes.dir}" />
</target>

<target name="compile"
description="Compile Java class for Java System.properties example"
depends="init">
<javac srcdir="${src.dir}"
destdir="${classes.dir}"
includes="properties/SystemPropertiesExample.java"
debug="${javac.debug}"
deprecation="${javac.deprecation}"
verbose="${javac.verbose}" />
</target>

<target name="buildJar"
description="Build executable JAR to display Java System.properties"
depends="compile">
<jar destfile="${dist.dir}/${jar.system.properties}"
basedir="${classes.dir}"
includes="properties/SystemPropertiesExample.class">
<manifest>
<attribute name="Main-Class"
value="properties.SystemPropertiesExample" />
</manifest>
</jar>
</target>

<target name="echo"
description="Display custom and standard available properties">
<antcall target="echoCustomProperties" />
<antcall target="echoAntBuiltInProperties" />
<antcall target="echoJavaSystemProperties" />
<antcall target="echoSunSpecificProperties" />
</target>

<!-- Properties created specifically for use in this build file (see the
associated build.properties file. -->
<target name="echoCustomProperties"
description="Display properties custom to this build file">
<echo message="------------- CUSTOM PROPERTIES ---------------" />
<echo message="jar.system.properties = ${jar.system.properties}" />
<echo message="javac.debug = ${javac.debug}" />
<echo message="javac.deprecation = ${javac.deprecation}" />
<echo message="javac.verbose = ${javac.verbose}" />
<echo message="classes.dir = ${classes.dir}" />
<echo message="dist.dir = ${dist.dir}" />
<echo message="src.dir = ${src.dir}" />
</target>

<!-- Ant's built-in properties as described in Ant manual at
http://ant.apache.org/manual/using.html#built-in-props. -->
<target name="echoAntBuiltInProperties"
description="Display Ant's built-in properties">
<echo message="------------- ANT PROPERTIES ---------------" />
<echo message="ant.file = ${ant.file}" />
<echo message="ant.home = ${ant.home}" />
<echo message="ant.java.version = ${ant.java.version}" />
<echo message="ant.project.name = ${ant.project.name}" />
<echo message="ant.version = ${ant.version}" />
<echo message="basedir = ${basedir}" />
</target>

<!-- Ant's peek at select Java's properties. Ant actually can see many more
properties than shown here, including Sun-specific properties when using
that particular JVM, but only a sample is shown here. -->
<target name="echoJavaSystemProperties"
description="Display Java properties">
<echo message="------------- (SELECT SAMPLE OF) JAVA PROPERTIES ---------------" />
<echo message="java.class.path = ${java.class.path}" />
<echo message="java.class.version = ${java.class.version}" />
<echo message="java.home = ${java.home}" />
<echo message="java.library.path = ${java.library.path}" />
<echo message="java.runtime.name = ${java.runtime.name}" />
<echo message="java.runtime.version = ${java.runtime.version}" />
<echo message="java.vendor.url = ${java.vendor.url}" />
<echo message="java.vendor.url.bug = ${java.vendor.url.bug}" />
<echo message="java.version = ${java.version}" />
<echo message="java.vm.info = ${java.vm.info}" />
<echo message="java.vm.name = ${java.vm.name}" />
<echo message="java.vm.specification.vendor = ${java.vm.specification.vendor}" />
<echo message="java.vm.vendor = ${java.vm.vendor}" />
<echo message="java.vm.version = ${java.vm.version}" />
<echo message="os.arch = ${os.arch}" />
<echo message="os.name = ${os.name}" />
<echo message="os.version = ${os.version}" />
<echo message="user.country = ${user.country}" />
<echo message="user.home = ${user.home}" />
<echo message="user.language = ${user.language}" />
<echo message="user.name = ${user.name}" />
<echo message="user.timezone = ${user.timezone}" />
</target>

<!-- Display Ant's peek at select Sun-specific properties. -->
<target name="echoSunSpecificProperties" if="sun.management.compiler">
<echo message="--------------- (SELECT) SUN-SPECIFIC PROPERTIES ---------------" />
<echo message="sun.boot.library.path = ${sun.boot.library.path}" />
<echo message="sun.cpu.isalist = ${sun.cpu.isalist}" />
<echo message="sun.java.launcher = ${sun.java.launcher}" />
<echo message="sun.management.compiler = ${sun.management.compiler}" />
</target>

</project>

The build.properties file used by the build.xml file above


# Directories
classes.dir = classes
dist.dir = dist
src.dir = src

# Generated Files
jar.system.properties = displayJavaProperties.jar

# Java Compiler (javac) Attributes
javac.debug = off
javac.deprecation = off
javac.verbose = no

UPDATE (6 November 2007): This <echoproperties /> task is an even easier way to display properties available to an Ant build.xml file. I cover this useful Ant task in more detail in this blog entry.

There are some differences between the properties returned from the Java System.getProperties() call and the Java-related properties accessed in Ant. For example, the property java.class.path has a value shown only of the executable JAR file that was executed with "java –jar displayJavaProperties.jar" to print out the properties while the Ant java.class.path display shows a very long classpath value with paths pointing to various Java and Ant JAR and ZIP files.

Fred Swartz has a nice discussion of using Java's System.getProperties with Swing in his Java: Systems Properties page.

1 comment:

gebuh said...

I know I'm late to the party, but a couple of comments about your system properties iteration.

I had to use for(Object propertyName : propertyNames) and then cast propertyName to a String.

you can use the 2 param getProperty method:
propertyValue = properties.getProperty((String)propertyName, "empty string");
instead of setting this separately, the 2nd param becomes the default value.