Bug 32142 - [PROPOSAL, PATCH] External public entity and new system entity IDs.
Summary: [PROPOSAL, PATCH] External public entity and new system entity IDs.
Status: NEW
Alias: None
Product: Ant
Classification: Unclassified
Component: Core (show other bugs)
Version: 1.7.0
Hardware: Other other
: P3 enhancement with 1 vote (vote)
Target Milestone: ---
Assignee: Ant Notifications List
URL:
Keywords: PatchAvailable
Depends on:
Blocks:
 
Reported: 2004-11-10 06:08 UTC by Kevin Greiner
Modified: 2009-07-31 05:48 UTC (History)
0 users



Attachments
Install using 'patch -p 0 -i patch.txt' in ant directory (86.23 KB, patch)
2004-11-10 06:10 UTC, Kevin Greiner
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Kevin Greiner 2004-11-10 06:08:59 UTC
Add support for external public IDs and provide a new protocol such
that external system IDs may resolve to resources found in Ant's
classpath.

Public External IDs:
--------------------

The project helper has been modified to accept a Jar service that
provides Ant's entity resolver.  Anyone wishing to provide a set of
shared resources may extend the Ant entity resolver implementation to
map their custom public IDs to their resourses.  The details of how
the mapping is implemented is entirely deferred to the user.  One
possible implementation puts all of the shared resources and the
entity resolver service within the same jar file.  Deployment of these
resources is then simply a matter of copying the jar file into Ant's
class path.
Pro: Public IDs can be mapped to any input stream.  Consequently, the
     referenced resources may be deployed locally, to a common server,
     or any combination thereof.
Con: The entity resolver is deployed into the Ant installation so the
     resolver must be shared by all projects built by that Ant
     installation.


System External IDs:
--------------------

The Java URL framework provides for extensions based upon new protocol
names (i.e. ftp, http, file).  The introduction of the 'resource'
protocol provides for a URL similar to the jar protocol.  The
difference is that the 'resource' protocol does not require naming the
actual jar file.  Therefore, the URL resource:foo/bar.ext is
functionally equivalent to calling
LoaderUtils.getContextClassLoader().getResourceAsStream("foo/bar.ext").
Pro: Any number of jar files can be deployed to the ant classloader so
     long as each uniquely scopes it own resource names.
Con: All of the resources must be deployed into the Ant class path.


Justification
-------------
The rationale for these changes basically reflects on the fact that I
use Ant to manage a growing number of independent projects.  When I
first started using Ant, my build scripts were quite simple.  With
each new project, new features were added until I had a
parameter-driven script that could easily be customized to most of my
projects.  The only problem was that I also had numerous older
versions of the script associated with various legacy projects.  What
was obviously needed was a way to re-use large parts of a build script
across multiple projects.  So I moved most of my latest script into a
shared file that I then included into each projects script.  An
example being:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE project [
<!ENTITY standard_rules SYSTEM "file:../../rules.xml">
]>

<project basedir="." default="all" name="Build this project">
  &standard_rules;
</project>

This worked very well except that the relative path in the external
entity declaration was a problem when I tried to clone an existing
project to a new location.  I then switched to using absolute paths in
the URLs but that was a problem for co-workers who used the same
project but didn't share my directory structures.  What was needed was
an abstraction layer to hide the physical location of the shared
resource from all of the scripts using it.

The two solutions where then identified, developed, and deployed to
our local copy of Ant 1.5.  They have since been re-implemented for
Ant 1.7.

The attached zip file contains:
  All source to implement both solutions.
  A new JDK1.3 service loader utility.
  New unit tests to validate the new features.
  Updates for the manual to document the new features.
Comment 1 Kevin Greiner 2004-11-10 06:10:15 UTC
Created attachment 13368 [details]
Install using 'patch -p 0 -i patch.txt' in ant directory
Comment 2 Jan Mat 2004-11-10 08:41:37 UTC
Why don´t you use <import>?
Comment 3 Kevin Greiner 2004-11-10 12:46:06 UTC
I didn't use the import task for the following reasons:
1) It uses a file path rather than a URL to identify the contents.  Right now,
I'm actually packaging and distributing my shared files as a jar.  That makes it
easy to think of the shared code as a single unit (which is how it was tested).
2) Entities give me complete control over where they are inserted into my build
file.  As I understand it from various emails, the contents of an import task is
appended to the input stream even though the import task may appear at the
beginning of the stream.
Comment 4 Steve Loughran 2004-11-10 13:28:37 UTC
patching import to handle URI paths might be interesting, especially for that
in-JAR use. It would complicate the model of knowing where things are; entity
imports are less complex there as they are at the place of their inclusion.

note that <taskdef> does work in jars, and that now lets you import declarations of 
-tasks and types
-macros and presets
-scripts
and anything else of a type that is allowed (extends AntlibDefinition)

-steve
Comment 5 Kevin Greiner 2004-11-11 03:16:58 UTC
Right, I spent a good deal of time considering whether antlib provided an
alternative implementation.  I finally decided that they are orthoginal.  The
main point being that this patch simply provides streams to a wider range of
URLs.  I use it to define external entities.  Other people may use those URLs
with any task that accepts a URL.

I also thought that it would be interesting to modify import to accept a URL. 
It's essentially a free-be as all that is needed is to add an new attribute to
the task and then open the URL provided by that attribute.

Another interesting idea is that if you embed Ant into another product, then
that product could provide an EntityResolver that resolves a set of public
entity Ids.  If your ant task uses one of these Ids as a URL, you'd get a stream
that connects to the encapsulating product rather than a physical file.

Kevin