random memes }

property.import task for Ant

I have Ant build scripts that can be run on either Windows or Linux. There are a few properties that need to be set differently, depending on the platform in use. Been using this little snippet for a while now.

import.js

    Array.prototype.map = function(f) {
        var a = [];
        for (var i=0; i<this.length; ++i) {
            a.push(f(this[i],i));
        }
        return a;
    };
    Array.as = function(v) {
        var a = [];
        for (var i=0; i<v.length; ++i) {
            a.push(v[i]);
        }
        return a;
    }

    var PROPERTY = (function(){
        var t = {};
        var _get = function(k) {
            return project.getProperty(k);
        };
        t.get = _get;
        t.verbose = function(n) {
            n = 1 * n;
            if (0 < n) {
                t.get = function(k) {
                    var v = project.getProperty(k);
                    self.log("get " + k + " = " + v);
                    return v;
                };
            } else {
                t.get = _get;
            }
        };
        t.low = function(s) { var v = t.get(s); return v && v.toLowerCase(); };
        var os_name = t.low("os.name");
        var user_name = t.low("user.name");
        if (os_name.match(/^windows/)) {
            os_name = "win32";
        }
        t.byUser = function(s) {
            return t.get(s + "." + user_name);
        };
        t.byOS = function(s) {
            return t.get(s + "." + os_name);
        };
        t.byPlatform = function(s) {
            return t.get(s + "." + os_name + "." + user_name);
        };
        t.pick = function() {
            return Array.as(arguments).map(function(k){
                var v = t.get(k) || t.byPlatform(k) || t.byUser(k) || t.byOS(k);
                project.setProperty(k,v);
                self.log("set " + k + " = " + v);
                return v;
            });
        };
        return t;
    })();

    PROPERTY.verbose(attributes.get("verbose"));
    PROPERTY.pick(attributes.get("name"));

Task definition from Ant build file:

        <scriptdef
            name        = "property.import"
            language    = "javascript"
            src         = "import.js"
            >
            <attribute name="name" />
            <attribute name="verbose" />
        </scriptdef>

Example contents of build.properties:

    nsis.home.win32=c:/Program Files/NSIS
    launch4j.home.win32=c:/tools/launch4j
    launch4j.home.linux=${user.home}/tools/launch4j

Usage is simple:

        <property.import
            name        = "launch4j.home"
            verbose     = "0"
        />

The property.import task looks for variants of the named property suffixed with user.name, os.name or both. For the above import of launch4j.home the property.import task when run by user "preston" on Windows gets the value from the first of:

    launch4j.home.win32.preston
    launch4j.home.win32
    launch4j.home.preston

This allows checkin of build.properties while picking up appropriate per-user and per-platform property values when run.