ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stefan Bodewig <>
Subject Re: Extending path
Date Wed, 09 Jun 2010 10:06:10 GMT
[I appologize for reshuffling your post but this way my response make
mode sense, at least to me 8-)]

On 2010-06-09, Jon Stevens wrote:

> It looks like ResourceDecorator is 1.8 only and since this needs to
> work in Eclipse, I'm stuck in 1.7.x land for now.

IIUC what you do is a one-time action - or once whenever you change
dependencies - so it should be possible to use Ant outside of Eclipse
just for this.

Letting the IDE force the Ant version upon you somewhat defeats the
purpose of an IDE independent build process, doesn't it?

Anyway, yes, ResourceDecorator has been added after the 1.7.1 release.

> I guess I could add that class to my own code, but I'm not entirely
> sure how it works from your description. If you could provide some
> examples, that would be great.

It's really just the Decorator pattern implemented for the Resource
class.  The implementation is trivial.


OK.  One approach would be something like

public class SweetenedFileResource extends ResourceDecorator {
    private String src = null;
    private String scope = SweetenedScope.ALL.getScope();
    public void setSrc(String src) {
        this.src = src;
    public String getSrc() {
        return src;
    public void setScope(String scope) {
        this.scope = scope;
    public String getScope() {
        return scope;

I'm not sure how/why you need nameInner in your code, I'm trying to get
results quickly but guessing that you won't need it when using
ResourceDecorator ;-)


[BTW, I'd recommend using the <echoxml> task instead of <echo> and
looking into oato.util.XmlFragment for your <sweetenedbits> nested

Whereever you do 

            <sfile name="${ant.jar}" scope="compile" />

you'd instead use

            <sfile scope="compile">
              <file file="${ant.jar}"/>

This can be used wherever Ant accepts any kind of resource or resource
collection (since resource is a resource collection).

> The above is what I have so far, and it works pretty well, but isn't
> beautiful. It was kind of ugly since I had to implement my own <path>,
> <filelist> and <file> elements by extending the existing ones (as you
> can see from the example.xml, I just prefixed them with a 's' (ie:
> <spath>) and doing some hackery to make it all work.

I think you are doing way to much.  Embrace ResourceCollections - oh,
and don't extend MatchingTask, this is so Ant 1.1 ;-)

In you example if you'd use something like

    <union id="filelist.classpath">
      <sfile scope="compile">
        <file file="${lib.dir}/${ant.jar}"/>
      <sfile scope="runtime">
        <file file="${lib.dir}/svntask.jar"/>
      ... all the other definitions ...



will return SweetendFileResource instances that you can cast to in order
to access the scope attribute.  Any other thing you may want to know
about the file is directly available from the nested resource - and the
getName|Size... methods forward to it.

One improvement might be to extract the getters of SweetendFileResource
into an interface you could as well use instead of
hard-coded casts - Ant 1.8.x only.

Another idea would be to write a ResourceCollection implementation that
tags the scope attribute to any Resource contained.  Something like

    <union id="filelist.classpath">
      <sweetened scope="compile">
        <filelist dir="${lib.dir}">
            <file name="${ant.jar}"/>
        <filelist dir="${alexandria.dir}">
            <file name="${junit.jar}"/>
      <sweetened scope="runtime">
        <filelist dir="${lib.dir}">
            <file name="svntask.jar"/>
      <sweetened scope="runtime" src="src">
        <filelist dir="${target.dir}">
            <file name="sweetened.jar"/>

Where the sweetened ResourceCollection iterator() would return
SweetenedFileResources for all nested resources.

Inside of your task you'd get something like

    protected List<SweetenedFileResource> getJars(SweetenedScope scope) {
        List<SweetenedFileResource> jars = new ArrayList<SweetenedFileResource>();
        for (Resource r : getSweetenedBits())
            if (r instanceof SweetenedFileResource)
                SweetenedFileResource sfr = (SweetenedFileResource) r;
                SweetenedScope sfrScope = SweetenedScope.safeValueOf(sfr.getScope());
                if (sfrScope != null && (sfrScope == scope || sfrScope == SweetenedScope.ALL))
        return jars;

where I assume that getSweetenedBits returns a Union of all resource
collections rather than a list of Paths.  I'm not using the
interface/as() combination in order to make it possible to stick to Ant
1.7.1 (if you add ResourceDecorator to your own code base).

> Basically, all I want to do is be able to add a couple attributes to a
> <file> element and then get access to those attributes in my Task. I
> also want the container for those <file> elements to be able to be
> passed as a refid into a <classpath>.

What I described above should allow you to do just that.

You can also look at MappedResource and MappedResourceCollection in Ant
(1.8.x only) which adds a <mapper> to arbitrary resource(collection)s
and maps the name of the resource without changing any other attributes
as a similar example.

> All in all, I think I'm onto some new ant functionality here that is
> really useful.

The building blocks are all there inside of Ant (the ResourceDecorator).

> At this point, my head is spinning from all the layers of abstraction
> in ant.

It is a code base that has grown organically and that believes in
backwards compatibility almost dogmatically.

In your case things get worse since you come look into it with your
knowledge of a pre-ResourceCollection-era of Ant.  If you start out with
the concepts of Resource and ResourceCollection and completely do away
with Path and FileList things become more easy to follow.


To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message