From d2fbfd11cf8df27a028dc809bb0b3561660b986c Mon Sep 17 00:00:00 2001 From: mdb Date: Thu, 11 Apr 2002 07:23:59 +0000 Subject: [PATCH] Beginnings of automated Java library publishing, dependency tracking and downloading system. git-svn-id: https://samskivert.googlecode.com/svn/trunk@702 6335cc39-0255-0410-8fd6-9bcaacd3b74c --- projects/depends/build.xml | 69 +++++ projects/depends/docs/depends.xml | 13 + projects/depends/docs/descriptor.xml | 54 ++++ projects/depends/docs/design.txt | 33 +++ projects/depends/docs/notes.txt | 8 + projects/depends/docs/spec.txt | 177 +++++++++++++ .../com/samskivert/depends/Dependency.java | 235 ++++++++++++++++++ .../samskivert/depends/DependencyParser.java | 122 +++++++++ .../samskivert/depends/FormatException.java | 15 ++ .../samskivert/depends/LibraryDescriptor.java | 61 +++++ .../depends/LibraryDescriptorParser.java | 97 ++++++++ .../src/java/com/samskivert/depends/Log.java | 66 +++++ .../java/com/samskivert/depends/Release.java | 43 ++++ .../samskivert/depends/ReleaseDescriptor.java | 11 + .../java/com/samskivert/depends/Version.java | 48 ++++ .../depends/tasks/CheckDependsTask.java | 46 ++++ .../samskivert/depends/tasks/DependsTask.java | 103 ++++++++ .../depends/tasks/IncludeDependsTask.java | 11 + .../depends/tasks/UpdateDependsTask.java | 11 + 19 files changed, 1223 insertions(+) create mode 100644 projects/depends/build.xml create mode 100644 projects/depends/docs/depends.xml create mode 100644 projects/depends/docs/descriptor.xml create mode 100644 projects/depends/docs/design.txt create mode 100644 projects/depends/docs/notes.txt create mode 100644 projects/depends/docs/spec.txt create mode 100644 projects/depends/src/java/com/samskivert/depends/Dependency.java create mode 100644 projects/depends/src/java/com/samskivert/depends/DependencyParser.java create mode 100644 projects/depends/src/java/com/samskivert/depends/FormatException.java create mode 100644 projects/depends/src/java/com/samskivert/depends/LibraryDescriptor.java create mode 100644 projects/depends/src/java/com/samskivert/depends/LibraryDescriptorParser.java create mode 100644 projects/depends/src/java/com/samskivert/depends/Log.java create mode 100644 projects/depends/src/java/com/samskivert/depends/Release.java create mode 100644 projects/depends/src/java/com/samskivert/depends/ReleaseDescriptor.java create mode 100644 projects/depends/src/java/com/samskivert/depends/Version.java create mode 100644 projects/depends/src/java/com/samskivert/depends/tasks/CheckDependsTask.java create mode 100644 projects/depends/src/java/com/samskivert/depends/tasks/DependsTask.java create mode 100644 projects/depends/src/java/com/samskivert/depends/tasks/IncludeDependsTask.java create mode 100644 projects/depends/src/java/com/samskivert/depends/tasks/UpdateDependsTask.java diff --git a/projects/depends/build.xml b/projects/depends/build.xml new file mode 100644 index 00000000..4241d51f --- /dev/null +++ b/projects/depends/build.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copyright © 2000-${year} ${copyright.holder}. + All Rights Reserved. + + + + + + + + + + + + + diff --git a/projects/depends/docs/depends.xml b/projects/depends/docs/depends.xml new file mode 100644 index 00000000..8460f6a3 --- /dev/null +++ b/projects/depends/docs/depends.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/projects/depends/docs/descriptor.xml b/projects/depends/docs/descriptor.xml new file mode 100644 index 00000000..8cc693cc --- /dev/null +++ b/projects/depends/docs/descriptor.xml @@ -0,0 +1,54 @@ + + + + samskivert + + + 2000-2002, Michael Bayne + + + mdb@samskivert.com + + + http://www.waywardgeeks.org/code/samskivert/ + + + samskivert.ldf + + + + + 1.1 + 2001-12-03 + + releases/samskivert-1.1.jar + + + + + + + + + + 1.01 + 2001-08-13 + releases/samskivert-1.01.jar + + + + + + diff --git a/projects/depends/docs/design.txt b/projects/depends/docs/design.txt new file mode 100644 index 00000000..69b27bce --- /dev/null +++ b/projects/depends/docs/design.txt @@ -0,0 +1,33 @@ +Dependency system design +------------------------ + +- Two interfaces: Java object interface and ANT wrapper + +- If possible, use no external libraries to avoid bootstrapping problems + (can't use depends to download depends for depends): + + make use of built-in Java XML parsing services + + make use of built-in Java logging services + + will have to "depend" on ant + +- Object interface available via the following classes: + + public class Dependency + { + public String getLibraryName (); + + public File getLocalJar (); + + public boolean isUpToDate (); + + public void bringUpToDate (); + } + + public class DependencyParser + { + public List parseDependencies ( + File definition, File repository); + } + + public class LibraryDescriptor + { + } diff --git a/projects/depends/docs/notes.txt b/projects/depends/docs/notes.txt new file mode 100644 index 00000000..499e3e55 --- /dev/null +++ b/projects/depends/docs/notes.txt @@ -0,0 +1,8 @@ +Dependency system notes +----------------------- + +- Will need tool (ant task) for "stamping" a jar file (inserting the + library descriptor). + +- Will want tool that dumps library descriptor information from an + existing jar file (both in XML and formatted text). diff --git a/projects/depends/docs/spec.txt b/projects/depends/docs/spec.txt new file mode 100644 index 00000000..1c7c37cd --- /dev/null +++ b/projects/depends/docs/spec.txt @@ -0,0 +1,177 @@ +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: + + + + + samskivert + + + 2000-2002, Michael Bayne + + + mdb@samskivert.com + + + http://www.waywardgeeks.org/code/samskivert/ + + + samskivert.ldf + + + + + 1.1 + 2001-12-03 + + releases/samskivert-1.1.jar + + + + + + + + + + 1.01 + 2001-08-13 + releases/samskivert-1.01.jar + + + + + + + + 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: + + + + samskivert + 2000-2002, Michael Bayne + http://www.waywardgeeks.org/code/samskivert/ + samskivert.ldf + + 1.1 + 2001-12-03 + releases/samskivert-1.1.jar + + + + + + + + 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: + + + + + + + build.xml: + + + + + + + + + + + + + + + + + + + + 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: + + + + --> + url="file:/home/mdb/projects/samskivert/target/samskivert.ldf"/> + + + 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. diff --git a/projects/depends/src/java/com/samskivert/depends/Dependency.java b/projects/depends/src/java/com/samskivert/depends/Dependency.java new file mode 100644 index 00000000..12e6a11e --- /dev/null +++ b/projects/depends/src/java/com/samskivert/depends/Dependency.java @@ -0,0 +1,235 @@ +// +// $Id: Dependency.java,v 1.1 2002/04/11 07:23:59 mdb Exp $ + +package com.samskivert.depends; + +import java.io.File; +import java.io.IOException; + +import java.net.URL; +import java.net.URLConnection; + +/** + * Describes a particular library dependency. + */ +public class Dependency +{ + /** + * Constructs a dependency from its specification criterion. + */ + public Dependency (String libraryName, + Version requiredVersion, + URL descriptorURL) + { + _libraryName = libraryName; + _requiredVersion = requiredVersion; + _descriptorURL = descriptorURL; + } + + /** + * Informs this dependency of the location of our local library + * repository. + */ + public void setLocalRepository (File repository) + { + _repository = repository; + } + + /** + * Returns the human-readable library identifier. + */ + public String getLibraryName () + { + return _libraryName; + } + + /** + * Returns the library version required by this dependency + * specification. + */ + public Version getRequiredVersion () + { + return _requiredVersion; + } + + /** + * Returns the descriptor URL for the library referenced by this + * dependency. + */ + public URL getDescriptorURL () + { + return _descriptorURL; + } + + /** + * Returns the version of our local copy of the library referenced by + * this dependency, or null if we have no local copy of the library. + * + * @exception IllegalStateException thrown if the dependency has not + * yet been configured with the path to the local library repository. + */ + public Version getLocalVersion () + throws IOException, FormatException + { + if (_localVersion == null) { + resolveLocalVersion(); + } + return _localVersion; + } + + /** + * Returns a file object referencing our local copy of the library + * referenced by this dependency, or null if the dependency hasn't + * been resolved. + * + * @exception IllegalStateException thrown if the dependency has not + * yet been configured with the path to the local library repository. + */ + public File getLocalJar () + { + if (_repository == null) { + String errmsg = "Dependency has not yet been configured " + + "with path to local library repository."; + throw new IllegalStateException(errmsg); + } + return new File(_repository, constructJarName()); + } + + /** + * Returns true if we have a local copy of the library referenced by + * this dependency that satisfies the dependency's version constraints + * and that we have local copies with satisfactory versions + * of all libraries upon which this library depends, ad infinitum. If + * we have no local copy of the library or the version of the local + * copy is older than the version specified by the dependency or same + * for any derived dependencies, this method returns false. + * + *

Note that this method caches its results once they are computed + * in the expectation that it will be used in a "one shot" manner + * (meaning the JVM that instantiates and uses this class is not long + * lived). Once a dependency is resolved, it does not go back and + * reresolve it, thus it could become out of date if the library (or + * its dependencies) is updated between the time that this method is + * called and the time that the calling JVM exits. + */ + public boolean isSatisified () + { + // TBD + return false; + } + + /** + * Returns true if we have a local copy of the library and it is the + * most recent release of that library. This method results in an HTTP + * request being issued to download the latest library descriptor for + * the library + * + *

Note that this method caches its results once they are computed + * in the expectation that it will be used in a "one shot" manner + * (meaning the JVM that instantiates and uses this class is not long + * lived). Once a dependency is resolved, it does not go back and + * reresolve it, thus it could become out of date if the library (or + * its dependencies) is updated between the time that this method is + * called and the time that the calling JVM exits. + */ + public boolean isUpToDate () + throws IOException + { + // TBD + return false; + } + + /** + * Downloads the library descriptor for the library referenced by this + * dependency and returns it. Note that once the descriptor has been + * downloaded once, it is cached for the remainder of the lifetime of + * the JVM, hiding updates that take place between the time that this + * method is called and the time that the calling JVM exists. This is + * considered to be more desirable than making an HTTP request every + * time this method is called. + */ + public LibraryDescriptor getLibraryDescriptor () + throws IOException, FormatException + { + if (_remoteDescriptor != null) { + return _remoteDescriptor; + } + + // download the descriptor data from the publishing site + URLConnection uconn = _descriptorURL.openConnection(); + _remoteDescriptor = LibraryDescriptorParser.parseLibraryDescriptor( + uconn.getInputStream()); + return _remoteDescriptor; + } + + /** + * Downloads the library descriptor for the library referenced by this + * dependency and reports the most recent version available of said + * library. + * + * @see #getLibraryDescriptor + */ + public Version getRemoteVersion () + throws IOException, FormatException + { + LibraryDescriptor descriptor = getLibraryDescriptor(); + return descriptor.getLatestRelease().getVersion(); + } + + /** + * Returns a string representation of this instance. + */ + public String toString () + { + return "[name=" + _libraryName + ", version=" + _requiredVersion + + ", url=" + _descriptorURL + "]"; + } + + /** + * Constructs the file name of our local copy of the jar file. + */ + protected String constructJarName () + { + return _libraryName + LIBRARY_SUFFIX; + } + + /** + * Loads up the library stamp from our local copy of the library and + * extracts the version information from it. + */ + protected Version resolveLocalVersion () + throws IOException, FormatException + { + File jar = getLocalJar(); + // TBD + return null; + } + + /** The name of the library referenced by this dependency. */ + protected String _libraryName; + + /** The version required by this dependency. */ + protected Version _requiredVersion; + + /** The URL for the descriptor of the library referenced by this + * dependency. */ + protected URL _descriptorURL; + + /** The path to our local library repository. */ + protected File _repository; + + /** The version of our local copy of the library or null if we have no + * local copy. */ + protected Version _localVersion; + + /** A parsed library descriptor, obtained from our local copy of the + * library. */ + protected LibraryDescriptor _localDescriptor; + + /** A parsed library descriptor, downloaded from the site that + * publishes this library. */ + protected LibraryDescriptor _remoteDescriptor; + + /** All libraries end with this suffix: .jar */ + protected static final String LIBRARY_SUFFIX = ".jar"; +} diff --git a/projects/depends/src/java/com/samskivert/depends/DependencyParser.java b/projects/depends/src/java/com/samskivert/depends/DependencyParser.java new file mode 100644 index 00000000..e4b960f5 --- /dev/null +++ b/projects/depends/src/java/com/samskivert/depends/DependencyParser.java @@ -0,0 +1,122 @@ +// +// $Id: DependencyParser.java,v 1.1 2002/04/11 07:23:59 mdb Exp $ + +package com.samskivert.depends; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.parsers.ParserConfigurationException; + +import java.io.File; +import java.io.IOException; + +import java.net.URL; +import java.net.MalformedURLException; + +import java.util.ArrayList; +import java.util.List; + +/** + * Parses XML dependency definitions. + */ +public class DependencyParser +{ + /** + * Parses the specified dependency definition file into a list of + * {@link Dependency} instances. + */ + public static List parseDependencies (File definition) + throws FormatException, IOException + { + try { + ArrayList list = new ArrayList(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + SAXParser parser = factory.newSAXParser(); + DependencyHandler handler = new DependencyHandler(list); + parser.parse(definition, handler); + return list; + + } catch (SAXException saxe) { + throw new FormatException(saxe.getMessage()); + + } catch (ParserConfigurationException pce) { + throw new FormatException( + "Unable to load parser: " + pce.getMessage()); + } + } + + public static void main (String[] args) + { + try { + parseDependencies(new File(args[0])); + } catch (Exception e) { + Log.warning("Chokey choke-opolis", e); + } + } + + /** + * Used to parse the dependency specification. + */ + protected static class DependencyHandler extends DefaultHandler + { + public DependencyHandler (List list) + { + _list = list; + } + + public void startElement (String namespaceURI, String localName, + String qName, Attributes attrs) + { + if (qName.equals("library")) { + String name = null; + String version = null; + String url = null; + + for (int i = 0; i < attrs.getLength(); i++) { + String attrName = attrs.getQName(i); + if (attrName.equals("name")) { + name = attrs.getValue(i); + } else if (attrName.equals("version")) { + version = attrs.getValue(i); + } else if (attrName.equals("url")) { + url = attrs.getValue(i); + } + } + + if (!validateAttribute("name", name) || + !validateAttribute("version", version) || + !validateAttribute("url", url)) { + return; + } + + try { + Dependency dep = new Dependency( + name, new Version(version), new URL(url)); + Log.info("Parsed dependency " + dep + "."); + _list.add(dep); + + } catch (MalformedURLException mue) { + Log.warning("Skipping dependency with invalid 'url' " + + "specification [url=" + url + "]: " + mue); + } + } + } + + protected boolean validateAttribute (String name, String value) + { + if (value == null || value.length() == 0) { + Log.warning("Skipping dependency declaration that is " + + "missing required attribute '" + name + "'."); + return false; + } else { + return true; + } + } + + protected List _list; + } +} diff --git a/projects/depends/src/java/com/samskivert/depends/FormatException.java b/projects/depends/src/java/com/samskivert/depends/FormatException.java new file mode 100644 index 00000000..1c319067 --- /dev/null +++ b/projects/depends/src/java/com/samskivert/depends/FormatException.java @@ -0,0 +1,15 @@ +// +// $Id: FormatException.java,v 1.1 2002/04/11 07:23:59 mdb Exp $ + +package com.samskivert.depends; + +/** + * Used to communicate file format exceptions. + */ +public class FormatException extends Exception +{ + public FormatException (String message) + { + super(message); + } +} diff --git a/projects/depends/src/java/com/samskivert/depends/LibraryDescriptor.java b/projects/depends/src/java/com/samskivert/depends/LibraryDescriptor.java new file mode 100644 index 00000000..44cd320b --- /dev/null +++ b/projects/depends/src/java/com/samskivert/depends/LibraryDescriptor.java @@ -0,0 +1,61 @@ +// +// $Id: LibraryDescriptor.java,v 1.1 2002/04/11 07:23:59 mdb Exp $ + +package com.samskivert.depends; + +import java.net.URL; + +import java.util.List; + +/** + * Describes a library. + */ +public class LibraryDescriptor +{ + public String getLibraryName () + { + return _libraryName; + } + + public String getCopyright () + { + return _copyright; + } + + public String getContact () + { + return _contact; + } + + public URL getLibraryURL () + { + return _libraryURL; + } + + public URL getDescriptorURL () + { + return _descriptorURL; + } + + public List getReleases () + { + return _releases; + } + + public Release getLatestRelease () + { + return null; + } + + protected String _libraryName; + + protected String _copyright; + + protected String _contact; + + protected URL _libraryURL; + + protected URL _descriptorURL; + + protected List _releases; +} diff --git a/projects/depends/src/java/com/samskivert/depends/LibraryDescriptorParser.java b/projects/depends/src/java/com/samskivert/depends/LibraryDescriptorParser.java new file mode 100644 index 00000000..41c4b1ff --- /dev/null +++ b/projects/depends/src/java/com/samskivert/depends/LibraryDescriptorParser.java @@ -0,0 +1,97 @@ +// +// $Id: LibraryDescriptorParser.java,v 1.1 2002/04/11 07:23:59 mdb Exp $ + +package com.samskivert.depends; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.parsers.ParserConfigurationException; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import java.net.URL; +import java.net.MalformedURLException; + +/** + * Parses XML library descriptor definitions. + */ +public class LibraryDescriptorParser +{ + /** + * Parses the specified library descriptor file. + */ + public static LibraryDescriptor parseLibraryDescriptor (File descriptor) + throws FormatException, IOException + { + return parseLibraryDescriptor(new FileInputStream(descriptor)); + } + + /** + * Parses the library descriptor definition provided via the supplied + * input stream. + */ + public static LibraryDescriptor parseLibraryDescriptor (InputStream source) + throws FormatException, IOException + { + try { + LibraryDescriptor ld = new LibraryDescriptor(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + SAXParser parser = factory.newSAXParser(); + DescriptorHandler handler = new DescriptorHandler(ld); + parser.parse(source, handler); + return ld; + + } catch (SAXException saxe) { + throw new FormatException(saxe.getMessage()); + + } catch (ParserConfigurationException pce) { + throw new FormatException( + "Unable to load parser: " + pce.getMessage()); + } + } + + public static void main (String[] args) + { + try { + parseLibraryDescriptor(new File(args[0])); + } catch (Exception e) { + Log.warning("Chokey choke-opolis", e); + } + } + + /** + * Used to parse a library descriptor specification. + */ + protected static class DescriptorHandler extends DefaultHandler + { + public DescriptorHandler (LibraryDescriptor descriptor) + { + _descriptor = descriptor; + } + + public void startElement (String namespaceURI, String localName, + String qName, Attributes attrs) + { + } + + protected boolean validateAttribute (String name, String value) + { + if (value == null || value.length() == 0) { + Log.warning("Skipping dependency declaration that is " + + "missing required attribute '" + name + "'."); + return false; + } else { + return true; + } + } + + protected LibraryDescriptor _descriptor; + } +} diff --git a/projects/depends/src/java/com/samskivert/depends/Log.java b/projects/depends/src/java/com/samskivert/depends/Log.java new file mode 100644 index 00000000..04a5923d --- /dev/null +++ b/projects/depends/src/java/com/samskivert/depends/Log.java @@ -0,0 +1,66 @@ +// +// $Id: Log.java,v 1.1 2002/04/11 07:23:59 mdb Exp $ + +package com.samskivert.depends; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Provides convenient access to our logging instance. + */ +public class Log +{ + /** A reference to our logger. */ + public static Logger log = Logger.getLogger("com.samskivert.depends"); + + /** + * Passes through to {@link Logger#fine(String)}. + */ + public static void fine (String message) + { + log.fine(message); + } + + /** + * Passes through to {@link Logger#info(String)}. + */ + public static void info (String message) + { + log.info(message); + } + + /** + * Passes through to {@link Logger#warning(String)}. + */ + public static void warning (String message) + { + log.warning(message); + } + + /** + * Passes through to {@link Logger#log} with level + * WARNING. + */ + public static void warning (String message, Exception e) + { + log.log(Level.WARNING, message, e); + } + + /** + * Passes through to {@link Logger#severe(String)}. + */ + public static void severe (String message) + { + log.severe(message); + } + + /** + * Passes through to {@link Logger#log} with level + * SEVERE. + */ + public static void severe (String message, Exception e) + { + log.log(Level.SEVERE, message, e); + } +} diff --git a/projects/depends/src/java/com/samskivert/depends/Release.java b/projects/depends/src/java/com/samskivert/depends/Release.java new file mode 100644 index 00000000..1129536a --- /dev/null +++ b/projects/depends/src/java/com/samskivert/depends/Release.java @@ -0,0 +1,43 @@ +// +// $Id: Release.java,v 1.1 2002/04/11 07:23:59 mdb Exp $ + +package com.samskivert.depends; + +import java.net.URL; + +import java.util.Date; +import java.util.List; + +/** + * Describes a particular release of a library. + */ +public class Release +{ + public Version getVersion () + { + return _version; + } + + public Date getDate () + { + return _date; + } + + public URL getJarURL () + { + return _jarURL; + } + + public List getDependencies () + { + return _dependencies; + } + + protected Version _version; + + protected Date _date; + + protected URL _jarURL; + + protected List _dependencies; +} diff --git a/projects/depends/src/java/com/samskivert/depends/ReleaseDescriptor.java b/projects/depends/src/java/com/samskivert/depends/ReleaseDescriptor.java new file mode 100644 index 00000000..5a889c85 --- /dev/null +++ b/projects/depends/src/java/com/samskivert/depends/ReleaseDescriptor.java @@ -0,0 +1,11 @@ +// +// $Id: ReleaseDescriptor.java,v 1.1 2002/04/11 07:23:59 mdb Exp $ + +package com.samskivert.depends; + +/** + * Does something extraordinary. + */ +public class ReleaseDescriptor +{ +} diff --git a/projects/depends/src/java/com/samskivert/depends/Version.java b/projects/depends/src/java/com/samskivert/depends/Version.java new file mode 100644 index 00000000..b60118a4 --- /dev/null +++ b/projects/depends/src/java/com/samskivert/depends/Version.java @@ -0,0 +1,48 @@ +// +// $Id: Version.java,v 1.1 2002/04/11 07:23:59 mdb Exp $ + +package com.samskivert.depends; + +/** + * Represents a library version. Version strings are not constrained to a + * particular format, but must meet a couple of criterion: first, they + * must contain only valid filename characters as they will be used to + * create the filename of our local copy of the library's jar file. + * Second, if a dependency's version specification ends with a + * '+', the dependency is considered satisfied by any library + * release newer than the specified version. Thus, if a version string + * ends in plus, wackiness ensues. Fortunately, we can issue a warning if + * anyone tries to stamp a library with a descriptor that declares its + * version to end with a plus. + */ +public class Version +{ + /** + * Constructs a version instance from the supplied version + * specification string. + */ + public Version (String version) + { + _version = version; + } + + /** + * Returns true if this version specification allows replacement by + * newer versions, false otherwise. + */ + public boolean openEnded () + { + return _version.endsWith("+"); + } + + /** + * Returns a string representation of this instance. + */ + public String toString () + { + return _version; + } + + /** Our version specification string. */ + protected String _version; +} diff --git a/projects/depends/src/java/com/samskivert/depends/tasks/CheckDependsTask.java b/projects/depends/src/java/com/samskivert/depends/tasks/CheckDependsTask.java new file mode 100644 index 00000000..5c5690da --- /dev/null +++ b/projects/depends/src/java/com/samskivert/depends/tasks/CheckDependsTask.java @@ -0,0 +1,46 @@ +// +// $Id: CheckDependsTask.java,v 1.1 2002/04/11 07:23:59 mdb Exp $ + +package com.samskivert.depends.tasks; + +import java.util.List; + +import org.apache.tools.ant.BuildException; + +import com.samskivert.depends.Dependency; + +/** + * An ant task for checking that a set of dependencies are satisfied by + * the jar files that currently exist in our local library repository. + */ +public class CheckDependsTask extends DependsTask +{ + /** + * Performs the actual work of the task. + */ + public void execute () + throws BuildException + { + // load and resolve our dependencies + List depends = loadDependencies(); + resolveDependencies(depends); + + int dcount = depends.size(); + for (int i = 0; i < dcount; i++) { + Dependency dep = (Dependency)depends.get(i); + try { + if (!dep.isUpToDate()) { + System.out.println("Library '" + dep.getLibraryName() + + "' has newer version " + + "[have=" + dep.getLocalVersion() + + ", latest=" + dep.getRemoteVersion() + + "]."); + } + + } catch (Exception e) { + System.err.println("Error checking dependency " + + "[dep=" + dep + ", error=" + e + "]."); + } + } + } +} diff --git a/projects/depends/src/java/com/samskivert/depends/tasks/DependsTask.java b/projects/depends/src/java/com/samskivert/depends/tasks/DependsTask.java new file mode 100644 index 00000000..8e7d8e65 --- /dev/null +++ b/projects/depends/src/java/com/samskivert/depends/tasks/DependsTask.java @@ -0,0 +1,103 @@ +// +// $Id: DependsTask.java,v 1.1 2002/04/11 07:23:59 mdb Exp $ + +package com.samskivert.depends.tasks; + +import java.io.File; +import java.util.List; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; + +import com.samskivert.depends.Dependency; +import com.samskivert.depends.DependencyParser; + +/** + * A base class that handles functionality common to all dependency + * related ant tasks. + */ +public abstract class DependsTask extends Task +{ + /** + * Called by ant to set the 'deps' attribute. + */ + public void setDeps (File deps) + { + _deps = deps; + } + + /** + * Called by ant to set the 'repository' attribute. + */ + public void setRepository (File repository) + { + _repository = repository; + } + + /** + * Throws a build exception using the supplied error message if the + * supplied value is null. + */ + protected void ensureSet (Object value, String errmsg) + throws BuildException + { + if (value == null) { + throw new BuildException(errmsg); + } + } + + /** + * Loads up a set of dependencies from the dependency file specified + * via the 'deps' task attribute. + */ + protected List loadDependencies () + throws BuildException + { + ensureSet(_deps, "Missing 'deps' attribute which should " + + "reference the dependency definition file."); + try { + return DependencyParser.parseDependencies(_deps); + } catch (Exception e) { + throw new BuildException("Error parsing dependency " + + "definition file.", e); + } + } + + /** + * Configures the supplied set of dependencies with the local library + * repository specified via the 'repository' task attribute. + */ + protected void resolveDependencies (List depends) + throws BuildException + { + // make sure the repository directory was specified... + ensureSet(_repository, "Missing 'repository' attribute which should " + + "reference the local library repository directory."); + + // ...exists... + if (!_repository.exists()) { + String errmsg = "Local library repository directory '" + + _repository.getPath() + "' does not exist."; + throw new BuildException(errmsg); + } + + // ...and is actually a directory + if (!_repository.isDirectory()) { + String errmsg = "Specified local library repository '" + + _repository.getPath() + "' is not a directory."; + throw new BuildException(errmsg); + } + + int dcount = depends.size(); + for (int i = 0; i < dcount; i++) { + Dependency dep = (Dependency)depends.get(i); + dep.setLocalRepository(_repository); + } + } + + /** The dependency definition file. */ + protected File _deps; + + /** The local library repository directory. */ + protected File _repository; +} diff --git a/projects/depends/src/java/com/samskivert/depends/tasks/IncludeDependsTask.java b/projects/depends/src/java/com/samskivert/depends/tasks/IncludeDependsTask.java new file mode 100644 index 00000000..3b738eca --- /dev/null +++ b/projects/depends/src/java/com/samskivert/depends/tasks/IncludeDependsTask.java @@ -0,0 +1,11 @@ +// +// $Id: IncludeDependsTask.java,v 1.1 2002/04/11 07:23:59 mdb Exp $ + +package com.samskivert.depends.tasks; + +/** + * Does something extraordinary. + */ +public class IncludeDependsTask +{ +} diff --git a/projects/depends/src/java/com/samskivert/depends/tasks/UpdateDependsTask.java b/projects/depends/src/java/com/samskivert/depends/tasks/UpdateDependsTask.java new file mode 100644 index 00000000..b8d43fe8 --- /dev/null +++ b/projects/depends/src/java/com/samskivert/depends/tasks/UpdateDependsTask.java @@ -0,0 +1,11 @@ +// +// $Id: UpdateDependsTask.java,v 1.1 2002/04/11 07:23:59 mdb Exp $ + +package com.samskivert.depends.tasks; + +/** + * Does something extraordinary. + */ +public class UpdateDependsTask +{ +}