The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

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

SYNOPSIS

    use Java::Build::Tasks;

    set_logger($log_object);

    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(
        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,
    );

    signjar(
        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);

    update_prop_file(
        NAME      => '/optional/path/and/file.properties',
        NEW_PROPS => \%values_to_add_or_update,
    );

    filter_file(
        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));

DESCRIPTION

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" ],

EXPORT

build_file_list copy_file filter_file jar make_jar_classpath read_prop_file set_logger signjar update_prop_file what_needs_compiling

DEPENDENCIES

    Carp
    Exporter
    Cwd
    File::Find
    File::Temp

FUNCTIONS

Each function is described in more detail below.

copy_file

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
    or
    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.

purge_dirs

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

set_logger

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.

read_prop_file

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....

    base_dir=/some/path

update_prop_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:

NAME

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.

NEW_PROPS

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

filter_file

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.

INPUT

The name of a file to filter.

FILTERS

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.

OUTPUT

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.)

build_file_list

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.

BASE_DIR

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.

EXCLUDE_PATTERNS

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.

EXCLUDE_DEFAULTS => 1,

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.

INCLUDE_PATTERNS

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.

STRIP_BASE_DIR

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.

DOTTIFY_NAMES

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.

QUOTE_DOLLARS

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.

make_jar_classpath

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$/ ].

what_needs_compiling

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.

SOURCE_FILE_LIST

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.

SOURCE_DIR

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

DEST_DIR

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

SOURCE_TO_COMPILIED_NAME

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

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.

JAR_FILE

The name of the destination file.

FILE_LIST

A list of files to put in the jar.

BASE_DIR

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

MANIFEST

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.

APPEND

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.

ear

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.

EAR_FILE

The name of the output file.

FILE_LIST

The regular files to put in the ear.

BASE_DIR

The parent directory of the regular files.

XML_BASE_DIR

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

signjar

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).

JAR_FILE

The name of the jar file to be signed.

ALIAS

The alias under which the JAR_FILE will be signed.

KEYSTORE

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.

STOREPASS

The password which locks your keystore.