Dependency system specification
-------------------------------

- Libraries publish "library descriptor file" which is a simple XML file
  describing the library's dependencies, latest release information and
  where supported releases can be downloaded:

    <?xml version="1.0"?>
    <library>
      <!-- the library identifier: case insensitive; matches ([-_A-Za-z]+) -->
      <name>samskivert</name>

      <!-- is the inclusion of copyright necessary or desirable? -->
      <copyright>2000-2002, Michael Bayne</copyright>

      <!-- contact information for this library (optional) -->
      <contact>mdb@samskivert.com</contact>

      <!-- a web page that provides information about the library and the
           base URL from which other URLs are interpreted to be relative -->
      <url>http://www.waywardgeeks.org/code/samskivert/</url>

      <!-- composed with <url> using the standard rules:
           <url> + samskivert.ldf = 
             http://www.waywardgeeks.org/code/samskivert/samskivert.ldf
           <url> + /samskivert.ldf = 
             http://www.waywardgeeks.org/samskivert.ldf
           <url> + http://foo.bar.com/samskivert.ldf = 
             http://foo.bar.com/samskivert.ldf
        -->
      <descriptor>samskivert.ldf</descriptor>

      <!-- enumerates the "supported" releases -->
      <releases>
        <release>
          <version>1.1</version>
          <date>2001-12-03</date>
          <!-- composed with <url> using the standard rules -->
          <jar>releases/samskivert-1.1.jar</jar>
          <!-- describes this release's dependencies -->
          <depends>
            <!-- version strings ending with + means automatically use the
                 latest version; versions are ordered by release date -->
            <library name="jakarta-commons-util" version="1.0+"
              url="http://jakarta.apache.org/commons/commons-util.ldf"/>
            <library name="jakarta-commons-digester" version="1.2"
              url="http://jakarta.apache.org/commons/commons-digester.ldf"/>
          </depends>
        </release>

        <release>
          <version>1.01</version>
          <date>2001-08-13</date>
          <jar>releases/samskivert-1.01.jar</jar>
          <depends>
            <library name="jakarta-commons-util" version="1.0+"
              url="http://jakarta.apache.org/commons/util/commons-util.ldf"/>
          </depends>
        </release>
      </releases>
    </library>

  This would be made available at:

    http://www.waywardgeeks.org/code/samskivert/samskivert.ldf

  Some sort of version information should be inserted into the JAR file so
  that the downloader doesn't have to maintain a cached copy of the LDF
  file it used to retrieve the JAR file. Perhaps an additional file
  included in the jar:

    META-INF/RELEASE.LDF:

    <?xml version="1.0"?>
    <library>
      <name>samskivert</name>
      <copyright>2000-2002, Michael Bayne</copyright>
      <url>http://www.waywardgeeks.org/code/samskivert/</url>
      <descriptor>samskivert.ldf</descriptor>
      <release>
        <version>1.1</version>
        <date>2001-12-03</date>
        <jar>releases/samskivert-1.1.jar</jar>
        <depends>
          <library name="jakarta-commons-util" version="1.0+"
            url="http://jakarta.apache.org/commons/commons-util.ldf"/>
          <library name="jakarta-commons-digester" version="1.2"
            url="http://jakarta.apache.org/commons/commons-digester.ldf"/>
        </depends>
      </release>
    </library>

  This would be automatically generated by the depends system and inserted
  into the jar file during the build process.

  Perhaps it is desirable to support the publishing of multiple libraries
  in a single LDF file?

- Projects reference dependencies via an ANT front-end or by other means
  (eg. Maven). Perhaps using an external file:

    depends.xml:

    <depends>
      <library name="samskivert" version="1.1+"
        url="http://www.waywardgeeks.org/code/samskivert/samskivert.ldf"/>
      <library name="jakarta-commons-collections" version="1.2+"
        url="http://jakarta.apache.org/commons/commons-collections.ldf"/>
    </depends>

    build.xml:

    <!-- includes the appropriate library files in the classpath -->
    <target name="include-depends">
      <taskdef name="include" classname="...IncludeDependsTask"/>
      <include deps="depends.xml" refid="classpath" repository="libs/"/>
    </target>

    <!-- checks for updates to the dependencies; reports newer versions,
         obsolescence, etc. -->
    <target name="check-depends">
      <taskdef name="check" classname="...CheckDependsTask"/>
      <check deps="depends.xml" repository="libs/"/>
    </target>

    <!-- downloads any newer versions of dependencies for which we have
         indicated a desire to use the latest version -->
    <target name="update-depends">
      <taskdef name="update" classname="...UpdateDependsTask"/>
      <update deps="depends.xml" repository="libs/"/>
    </target>

  Or perhaps the dependencies should be specified directly in ant's build
  file (which would probably involve more sophisticated extension of ant
  than just implementing a task). This latter approach would make it more
  difficult for external tools to inspect a project's dependencies, but
  fewer files is also good.

- A developer could override the standard library location and specify a
  dependency to a local build:

    <depends>
      <library name="samskivert" version="1.1+"
        <!-- use local build until those kooks incorporate our patches
        url="http://www.waywardgeeks.org/code/samskivert/samskivert.ldf"/>
          -->
        url="file:/home/mdb/projects/samskivert/target/samskivert.ldf"/>
    </depends>

  Because the build system would tag a library with a "release" date of
  the current date at the time of the build, it would pick up the local
  build so long as it was built more recently than any public build that
  might be referenced in the dependency hierarchy.

- KISS: place as little information as is necessary in the library
  descriptor files so as to minimize the possibility of that information
  becoming out of date.

- Facilitate build stability: don't automatically check for or download
  new libraries; provide an explicit mechanism for checking for updates
  (separate build directive), a means for specifying "use the latest
  version" and one for specifying "use a specific version".

- Facilitate the bleeding edge: a project should be able to include
  libraries from the web site where the most recent stable release is
  published, or build from CVS and reference their local build directly.

- Facilitate forward progress: report when a project depends on a version
  of a library that is no longer supported (meaning it is no longer listed
  in the library's descriptor).

- Facilitate dependency generation: check project's generated classfiles
  for references to classes not enumerated in dependencies hierarchy;
  report findings.

- Facilitate obsolete dependency removal: report dependencies that are not
  referenced by any class in the project.
