Java::Build::Tasks - collects common Java build tasks in one place: jar, jarsigner, etc.


    use Java::Build::Tasks;


    copy_file('source', 'dest');
    copy_file('list', 'of', 'sources', 'dest');
    copy_file('-r', 'list', 'of', 'sources', 'with', 'flags', 'dest');
    copy_file([ 'list', 'of', 'sources' ], 'dest');
    copy_file([ '-r', 'list', 'of', 'sources', 'with', 'flags' ], 'dest');

    my $file_list = build_file_list(
        BASE_DIR         => 'where/to/start',
        EXCLUDE_PATTERNS => [ qr/leave/, qr/these/, qr/out/ ],
        INCLUDE_PATTERNS => [ qr/.*include/, qr/these.*/    ],
        EXCLUDE_DEFAULTS => 1,
        STRIP_BASE_DIR   => 1,
        QUOTE_DOLLARS    => 1,

        JAR_FILE  => 'some/full/path/ending/in/a.jar',
        FILE_LIST => $file_list;
        MANIFEST  => 'location/of/manifest/to/put/in/jar',
        BASE_DIR  => 'path/to/change/to/before/building/jar',
        APPEND    => 1,

        JAR_FILE         => 'what/to/sign',
        KEYSTORE         => 'path/to/your/keystore',
        ALIAS            => $your_alias,
        STOREPASS        => $your_keystore_pass,

    my $config_hash = read_prop_file($prop_file_name);

        NAME      => '/optional/path/and/',
        NEW_PROPS => \%values_to_add_or_update,

        INPUT   => 't/file1',
        OUTPUT  => 't/file2',
        FILTERS => [
            sub { my $string = shift; $string =~ s/Happy/Joyous/g; $_;}

    my $dirties = what_needs_compiling(
        SOURCE_FILE_LIST         => $list,
        SOURCE_DIR               => 'path/to/your/source/files',
        DEST_DIR                 => 'path/to/your/compiled/files',
        SOURCE_TO_COMPILIED_NAME => sub { ... },

    my $classpath = make_jar_classpath(
        DIRS             => [ '/path/to/some/set/of/jars',
                              '/path/to/some/other/jars' ],
        INCLUDE_PATTERNS => [ qr/.jar$/, qr/.ZIP$/ ], # optional

    purge_dirs($base_dir, qw(sub directories to remove));


There are currently six tasks in this file. Three are like Ant tasks: update_prop_file (Ant calls this propertyfile), jar and signjar. Two build lists of files: build_file_list and what_needs_compiling. One reads a config file (or properties file) into a hash which it returns.

Call all of them with their hashes as shown above. The $file_list which jar expects, can be formed using build_file_list (as shown) or by simply supplying a list of file names, as in:

    FILE_SET => [ "file1", "file2" ],


build_file_list copy_file filter_file jar make_jar_classpath read_prop_file set_logger signjar update_prop_file what_needs_compiling




Each function is described in more detail below.


This function performs a copy. The only advantages of using it are to gain error checking, file name quoting (to guard spaces), and optional logging. The last argument must be the destination. The other argument(s) can be either

    a flattened list which starts with optional flags for the cp command
    an array reference which starts with optional flags

See sample calls in the SYNOPSIS for examples.

All space in the arguments are quoted. Those in the source(s) with backslash, those in the destintation with single quotes.


Pass in the parent directory and a list of its children to vaporize.


If you want logging of the tasks, pass a logging object to this method. That object must implement a log method, which will receive two parameters (in addition to the invocant): message and level. Levels go from 0 (debug) through 100 (fatal). Typically, the tasks croak immediately after sending fatal log messages. Most message are informational an have level 40. Only 0, 20, 40, 60, 80, and 100 are used.

Note that this is a class method, so only one logger can be used at any given time.

To turn off logging, call the method again with undef.


Opens the given file, reads it, and returns a hash of the var=value pairs. The config file may have blank lines or comments which start with a # at the left margin. For example:

    # This is a config file....



The method reads a properties file, updates its keys with new supplied values (adding keys when necessary) and writes the result back to the disk.

At present, it does not preserve comments or the order of the keys.

There are two parameters, both are required:


The name of the properties file, it will be created if it does not exist. This name should probably be an absolute path, though it could be relative to the directory from which the script was launched.


A hash reference with the keys you want to change or add and their new values.


The method reads a file one line at a time, filtering it according to your rules before writing it out.

There are three parameters, two are required: INPUT and FILTERS. OUTPUT is optional, if it is omitted, the result will overwrite the INPUT.

Note Well: This function is line oriented. It won't work on multi-line patterns. Suggestions for a more general approach are welcome.


The name of a file to filter.


A list of filtering functions. The function receives one line at a time. It should modify the received line (change $_[0]) if needed. It is fine to leave the parameter unchanged.


The name of the filtered file. If this is omitted, or is the same as INPUT, the result will overwrite the original. (A temporarly file is used so that data is not lost.)


This returns a list of files (in an array reference).

There are several arguments to build_file_list, only BASE_DIR is required.

Note that this function does not include directories in its lists. If this is a problem, someone should add an INCLUDE_DIRS parameter which callers can give a true value to receive directories. For now, directories are omitted.


A path where all the files in the set live. If you need more than one BASE_DIR, you can call the method again, then combine the resulting lists as in:

    my $combined_list = [ @$list1, @$list2 ];

where $list1 and $list2 are lists you built with this method or by hand.


This is a list of regular expressions which a file must not match. If it matches one of these, it is left out of the list.


If this argument is true, a standard set of patterns will be added to the EXCLUDE_PATTERNS. The default excluded patterns are the same ones Ant uses:

    Files ending with ~
    Files which begin and end with #
    Files which start with .#
    Files which begin and end with %
    Files with CVS as a path element
    Files called .cvsignore
    Files with SCCS as a path element
    Files called vssver.scc

At this time, there is no way to change this list without a code change in Java::Build::Tasks.


This is a list of regular expressions to include in the archive. Any file not excluded by matching something in EXCLUDE_PATTERNS (or the default excluded patterns) will be included, if it matches any of these patterns.


If this argument is true, the BASE_DIR will be removed from each file name before it goes into the result list. This makes all file names relative to BASE_DIR.

Defaults to false.


If this argument is true, all slashes in the file name will be replaced with dots. I'm not sure this is useful, but it was easy to include.

Defaults to false.


If this argument is true, all dollar signs in the file name will be replaced with \$. This helps, since functions like jar pass the names to the shell which doesn't treat the dollars literally.

Defaults to false.


This function makes a valid class path of all the jars in the supplied list of directories. It has two parameters. DIRS is the list of directories in which to look for jars, it is required. INCLUDE_PATTERNS works like it does in build_file_list. Give an anonymous array of regexes. By default this list is just [ qr/.jar$/ ]. You might need to set it to [ qr/.jar$/, qr/.ZIP$/ ].


This method takes a list of source files and returns a new list which includes source files only if they are newer than their compiled forms (or if their compiled form is absent).

There are four paramters to this method, only SOURCE_FILE_LIST is required.


An array reference storing paths to source code files. If SOURCE_DIR is omitted, paths must be absolute or they will be relative the starting directory of the script.


A path to add to each name in the SOURCE_FILE_LIST (i.e. a parent directory for all of the source files).


A path to use in place of SOURCE_DIR for compiled files (i.e. a parent directory for all the compiled files).


A code reference. The function must take a source file name and return its compiled name. A good choice might be:

    sub {
        my $file = shift;
        $file    =~ s/\.java/.class/;
        return $file;

In fact, this is the default. What a lucky coincidence. If your source and compiled files live under different base directories, it may be convenient to leave out SOURCE_DIR and DEST_DIR, using a method to perform the conversion from one to the other.

If you have suggestions for the interface to this method, send them in. It still doesn't feel right to me.


jar uses the Sun supplied jar tool to package a list of files. You may want to construct the list by calling build_file_list above, but you may produce it in any way you like. The names in the list should be relative to the BASE_DIR of the jar.

There are five arguments to jar, JAR_FILE, BASE_DIR and FILE_SET are required. MANIFEST and APPEND are optional.


The name of the destination file.


A list of files to put in the jar.


A directory to move to before issuing the jar command. This might be the same BASE_DIR you used to build the file list.


The name of the manifest file to put in the jar. If you omit this, jar will do its default thing. See the docs for jar to know what that default thing is, and what to put in your MANIFEST if you choose to supply one.


If this is true, files will be added to an existing jar. Bad things will happen if the file does not exist.

Defaults to false.


The only difference between a jar and a WebSphere ear is the application.xml which must be in META-INF/application.xml. This is a convenience routine for making these.

There are four parameters to ear. All are required.


The name of the output file.


The regular files to put in the ear.


The parent directory of the regular files.


The parent directory of META-INF/application.xml.


There are four named attributes to signjar. JAR_FILE and ALIAS are required KEYSTORE and STOREPASS are not (but if you use KEYSTORE, you must use STOREPASS or unexpected bad things may happen).


The name of the jar file to be signed.


The alias under which the JAR_FILE will be signed.


The location of your key store file. The default is to leave out this parameter when calling jarsigner. See its documentation for where the default location is.


The password which locks your keystore.