Java Package Manager

What is it?

The Java Package Manager (JPM) is a set of class libraries and associated tools for managing bundles of distributable Java code. Inspired by the Red Hat Package Manager (RPM) distribution format, the Java Package Descriptor (JPD) format provides similar benefits to Java development.

At present, JPM provides a command-line tool that can automate the downloading, installation, and building of Java code. However, as successful use of JPM depends on having a suitable JPD for the package one wishes to use, success with the tool is limited to those few descriptors already created or descriptors created from scratch. Some of the descriptors that are available in limited form are:

Unfortunately, I do not have a tutorial on writing a JPD from scratch at this time. I suggest you look at the DTD for descriptors, then review the descriptors already available here. The best way to start a new descriptor is usually to copy one that already works for another package, then just change the names and values as appropriate. Also, comfort with Ant build files is highly suggested, since JPM just extends the features already provided by Ant.

Features

As of October 4, 2000, the 0.6.0 release of JPM included the following features:

Features planned for future releases, may include the following:

Download

The current version of JPM is available for download from the JPM project page at Sourceforge.

Installation and Usage

To use, download the JPM archive from Sourceforge and extract to a directory of choice. It is suggested you create a tree looking something like this:

$HOME
  /java
    /packages
      /jpm

where $HOME is your home directory. If cd to the ~/java/packages/jpm directory listed here and extract the archive from there, then you will have the same setup as that used to develop JPM.

As execution of JPM depends on several libraries, all libraries found in the /lib subdirectory should be added to the classpath prior to executing the main class, which is blue.tools.jpm.PackageManager. On *nix platforms, the following command executed from /jpm directory will be sufficient to start JPM (note the use of the back-tick to execute the find command):

java -cp `find lib -name *.jar -printf ':%p'` blue.tools.jpm.PackageManager

Depending on how JPM is invoked, it will either either download a JPD specified on it's command-line (through the -p option), or look for a package.xml file in the current directory. When JPM downloads a JPD, it copies the descriptor to package.xml in the current directory, so repeated invocations of JPM in the same directory do not need to specify the -p option, as the local copy in package.xml will be used. JPM does not use any hidden files in the current directory, so be aware that deleting the package.xml in the current directory will require subsequent executions to download the descriptor again using the -p option.

Here's the output of running the -usage option:

Usage: jpm [options] target(s) ...
  where valid options are
    -p      URL of the package descriptor;
                 defaults to package.xml in current
                 directory
    -b     Path to base or working directory for
                 installing the package; defaults to
                 current directory
    -terse       Print only errors from build
    -verbose     Print most messages output from build
    -extra       Print all messages output from build
    -usage       Print this message
    -user        User name for CVS access
    -password    Password for CVS access
    -checkout    Checkout the package from CVS
    -build       Build the package; this is default, but if
                 multiple 'actions' are specfied, use of this
                 option will determine where in the sequence
                 a build occurs

Note that using JPM is similar to using Ant (or make, if that is more familiar): after specifying options, all remaining arguments are treated as targets to the build process. If none is specified, then the default target will be executed. Reporting of messages is reasonably thorough, but it will not look the same as output from Ant: some bugs in the Ant toolset do not report messages with the appropriate priority level, so the JPM logger filters out some messages that Ant (incorrectly) does not.

System Requirements

Currently, all JPM development happens on the Linux platform, and as such has not been tested on any Windows operating systems, nor have any been scripts been produced to run on a Windows operating system. However, since the entire package is written in Java, JPM should work unchanged on other platforms.

Further, development of JPM currently uses JDK 1.3 from Sun. Although JPM has not been tested on early VM specifications or the VM of other vendors, JPM should run unchanged on most JDK 1.2 or greater VMs.

JPM depends on 3 other external libraries to operate, but presently those libraries are included in the distribution. No additional downloads are necessary. Those libraries are:

Background

I started creating the JPM libraries after growing frustated at the difficulty of downloading, installing, and evaluating all the open source Java products available on the Net. For each product, I needed to:

  1. To download and extract an archive or checkout the code from CVS, then optionally run an install or make script

  2. Attempt to find relevant documentation

  3. Determine the main class for any applications, if any, provided by the product

  4. Determine the CLASSPATH needed to run the application(s), including dependencies on other well-known products (e.g., IBM's Xerces XML parser)

  5. Sift through the source code when the product failed to work on my machine

Finally, I decided to create a set of classes to manage Java Package Descriptors (JPDs): a package descriptor is a small XML file that describes all of the relevant bits of a specific Java product. With this descriptor (and nothing else), the libraries should have sufficient information to:

After some early efforts, I decided to extend the Ant toolset developed for the Apache Jakarta project. The Ant toolset provides a platform-independent make facility that instead of using traditional (and cumbersome) make files uses XML-based build files. For those familiar with Ant, all of done is create code around the Ant libraries to embed Ant build information inside JPDs. Together, the ant-compliant portion of the JPD provides complete instructions for downloading, installing, building, etc., a product, while the remaining meta-info stored in the JPD is available for other functions.

The JPD approach differs from that of other distribution formats, such as RPM or the various .JAR based Java deployment formats. RPM and most .jar formats embed the meta-info and the contents of the files in the distribution directly in the distribution file. However, I realized that I didn't want to waste time or diskspace downloading, installing, packaging, and then uploading dozens or hundreds of open source packages. Further, some packages may have licensing restrictions that prohibit direct redistribution. Using a descriptor is essentially the same as "linking" to a package in the same way that hyperlinks are links to packages, but do not contain the content themselves.

As for the .JAR formats proposed by Sun (.JARs for archives and bean distribution, .WAR for web applications, etc.), unfortunately most of these formats were unsatisfactory for 2 reasons:

  1. They are targeted at production deployment instead of aiding the developer; the latter was my goal

  2. Most of the meta-info embedded in the various .JAR files (except for EJB deployment descriptors) is not stored in XML, but in very crude text files containing name-value pairs.

One more format that was considered by not included: Sun's Java Network Launch Protocol (JNLP) or Web Start. I chose not to follow Sun's conventions for 2 reasons:

  1. It was not apparent that JNLP or any libraries based on JNLP as delivered by Sun would be considered open source

  2. JNLP, like most other deployment methods, targets deployment into production, while I wanted to solve the problem of deployment to development

I did recommend to the JNLP team some changes to their format, but they politely declined at the time of my request on the basis of their need to stabilize the specification. Granted, JNLP includes semantics that support lazy-downloading, caching of resources, specifying target VMs, and even automatic downloading of VMs, but I considered those beyond the scope of my present needs.