View | Details | Raw Unified | Return to bug 40678
Collapse All | Expand All

(-)src/tests/antunit/taskdefs/fragmentdef-test.xml (+41 lines)
Line 0 Link Here
1
<project default="antunit" xmlns:au="antlib:org.apache.ant.antunit">
2
  <import file="../antunit-base.xml" />
3
4
  <target name="test-simple">
5
    <fragmentdef name="attrlist">
6
      <sequential>
7
        <attribute name="a"/>
8
        <attribute name="b"/>
9
      </sequential>
10
    </fragmentdef>
11
    <macrodef name="use-attrlist">
12
      <attrlist/>
13
      <sequential>
14
        <property name="simple-prop" value="@{a}:@{b}"/>
15
      </sequential>
16
    </macrodef>
17
    <use-attrlist a="a" b="B"/>
18
    <au:assertTrue>
19
      <equals arg1="a:B" arg2="${simple-prop}"/>
20
    </au:assertTrue>
21
  </target>
22
23
  <target name="test-path">
24
    <fragmentdef name="fs-list">
25
      <sequential>
26
        <fileset dir="truncate" includes="*.xml"/>
27
        <fileset dir="exec" includes="*.xml"/>
28
      </sequential>
29
    </fragmentdef>
30
    <path id="d-path">
31
      <fs-list/>
32
    </path>
33
    <path id="e-path">
34
      <fileset dir="truncate" includes="*.xml"/>
35
      <fileset dir="exec" includes="*.xml"/>
36
    </path>
37
    <au:assertTrue>
38
      <equals arg1="${toString:d-path}" arg2="${toString:e-path}"/>
39
    </au:assertTrue>
40
  </target>
41
</project>
0
  + native
42
  + native
(-)src/main/org/apache/tools/ant/IntrospectionHelper.java (+13 lines)
Lines 647-652 Link Here
647
        if (isDynamic() || addTypeMethods.size() > 0) {
647
        if (isDynamic() || addTypeMethods.size() > 0) {
648
            return true;
648
            return true;
649
        }
649
        }
650
        return supportsReflectElement(parentUri, elementName);
651
    }
652
653
    /**
654
     * Check if this element supports a nested element from refection.
655
     *
656
     * @param parentUri   the uri of the parent
657
     * @param elementName the name of the nested element being checked
658
     *
659
     * @return true if the given nested element is supported
660
     */
661
    public boolean supportsReflectElement(
662
        String parentUri, String elementName) {
650
        String name = ProjectHelper.extractNameFromComponentName(elementName);
663
        String name = ProjectHelper.extractNameFromComponentName(elementName);
651
        if (!nestedCreators.containsKey(name.toLowerCase(Locale.US))) {
664
        if (!nestedCreators.containsKey(name.toLowerCase(Locale.US))) {
652
            return false;
665
            return false;
(-)src/main/org/apache/tools/ant/UnknownElement.java (-44 / +63 lines)
Lines 182-201 Link Here
182
            if (getWrapper().getId() != null) {
182
            if (getWrapper().getId() != null) {
183
                this.getOwningTarget().replaceChild(this, (Task) realThing);
183
                this.getOwningTarget().replaceChild(this, (Task) realThing);
184
            }
184
            }
185
       }
185
        }
186
186
187
188
        // configure attributes of the object and it's children. If it is
189
        // a task container, defer the configuration till the task container
190
        // attempts to use the task
191
192
        if (task != null) {
187
        if (task != null) {
193
            task.maybeConfigure();
188
            task.maybeConfigure();
194
        } else {
189
        } else {
195
            getWrapper().maybeConfigure(getProject());
190
            getWrapper().maybeConfigure(getProject());
196
        }
191
        }
197
192
198
        handleChildren(realThing, getWrapper());
193
        handleChildren(realThing, null);
199
    }
194
    }
200
195
201
    /**
196
    /**
Lines 308-313 Link Here
308
        children.add(child);
303
        children.add(child);
309
    }
304
    }
310
305
306
    private void recurHandleChild(
307
        ComponentHelper helper, Object parent, UnknownElement child) {
308
        IntrospectionHelper ih = IntrospectionHelper.getHelper(
309
            getProject(), parent.getClass());
310
311
        if (!ih.supportsReflectElement(getNamespace(), child.getComponentName())
312
            && helper.getDefinition(child.getComponentName()) != null) {
313
            Class componentClass = helper.getComponentClass(
314
                child.getComponentName());
315
            if ((componentClass != null)
316
                && (MacroFragment.class.isAssignableFrom(componentClass))) {
317
                child.maybeConfigure();
318
319
                MacroFragment macroFragment = (MacroFragment) child.realThing;
320
321
                List replaced = macroFragment.getUnknownElements(child);
322
                for (Iterator i = replaced.iterator(); i.hasNext();) {
323
                    recurHandleChild(
324
                        helper, parent, (UnknownElement) i.next());
325
                }
326
                return;
327
            }
328
        }
329
        // not a macro fragment - a "Normal" element
330
        try {
331
            if (!handleChild(
332
                    getNamespace(), ih, parent, child)) {
333
                if (!(parent instanceof TaskContainer)) {
334
                    ih.throwNotSupported(getProject(), parent,
335
                                         child.getTag());
336
                } else {
337
                    // a task container - anything could happen
338
                    // - just add the child to the container
339
                    TaskContainer container = (TaskContainer) parent;
340
                    container.addTask(child);
341
                }
342
            }
343
        } catch (UnsupportedElementException ex) {
344
            throw new BuildException(
345
                getWrapper().getElementTag()
346
                + " doesn't support the nested \"" + ex.getElement()
347
                + "\" element.", ex);
348
        }
349
    }
350
311
    /**
351
    /**
312
     * Creates child elements, creates children of the children
352
     * Creates child elements, creates children of the children
313
     * (recursively), and sets attributes of the child elements.
353
     * (recursively), and sets attributes of the child elements.
Lines 315-364 Link Here
315
     * @param parent The configured object for the parent.
355
     * @param parent The configured object for the parent.
316
     *               Must not be <code>null</code>.
356
     *               Must not be <code>null</code>.
317
     *
357
     *
318
     * @param parentWrapper The wrapper containing child wrappers
358
     * @param notUsed Not used.(kept for BC reasons)
319
     *                      to be configured. Must not be <code>null</code>
320
     *                      if there are any children.
321
     *
359
     *
322
     * @exception BuildException if the children cannot be configured.
360
     * @exception BuildException if the children cannot be configured.
323
     */
361
     */
324
    protected void handleChildren(
362
    protected void handleChildren(
325
        Object parent,
363
        Object parent,
326
        RuntimeConfigurable parentWrapper)
364
        RuntimeConfigurable notUsed)
327
        throws BuildException {
365
        throws BuildException {
366
        if (children == null) {
367
            return;
368
        }
369
370
        ComponentHelper helper = ComponentHelper.getComponentHelper(
371
            getProject());
372
328
        if (parent instanceof TypeAdapter) {
373
        if (parent instanceof TypeAdapter) {
329
            parent = ((TypeAdapter) parent).getProxy();
374
            parent = ((TypeAdapter) parent).getProxy();
330
        }
375
        }
331
376
332
        String parentUri = getNamespace();
377
        for (Iterator i = children.iterator(); i.hasNext();) {
333
        Class parentClass = parent.getClass();
378
            recurHandleChild(helper, parent, (UnknownElement) i.next());
334
        IntrospectionHelper ih = IntrospectionHelper.getHelper(getProject(), parentClass);
335
336
337
        if (children != null) {
338
            Iterator it = children.iterator();
339
            for (int i = 0; it.hasNext(); i++) {
340
                RuntimeConfigurable childWrapper = parentWrapper.getChild(i);
341
                UnknownElement child = (UnknownElement) it.next();
342
                try {
343
                    if (!handleChild(
344
                            parentUri, ih, parent, child, childWrapper)) {
345
                        if (!(parent instanceof TaskContainer)) {
346
                            ih.throwNotSupported(getProject(), parent,
347
                                                 child.getTag());
348
                        } else {
349
                            // a task container - anything could happen - just add the
350
                            // child to the container
351
                            TaskContainer container = (TaskContainer) parent;
352
                            container.addTask(child);
353
                        }
354
                    }
355
                } catch (UnsupportedElementException ex) {
356
                    throw new BuildException(
357
                        parentWrapper.getElementTag()
358
                        + " doesn't support the nested \"" + ex.getElement()
359
                        + "\" element.", ex);
360
                }
361
            }
362
        }
379
        }
363
    }
380
    }
364
381
Lines 535-544 Link Here
535
    private boolean handleChild(
552
    private boolean handleChild(
536
        String parentUri,
553
        String parentUri,
537
        IntrospectionHelper ih,
554
        IntrospectionHelper ih,
538
        Object parent, UnknownElement child,
555
        Object parent, UnknownElement child) {
539
        RuntimeConfigurable childWrapper) {
556
        RuntimeConfigurable childWrapper = child.getWrapper();
557
540
        String childName = ProjectHelper.genComponentName(
558
        String childName = ProjectHelper.genComponentName(
541
            child.getNamespace(), child.getTag());
559
            child.getNamespace(), child.getTag());
560
542
        if (ih.supportsNestedElement(parentUri, childName)) {
561
        if (ih.supportsNestedElement(parentUri, childName)) {
543
            IntrospectionHelper.Creator creator =
562
            IntrospectionHelper.Creator creator =
544
                ih.getElementCreator(
563
                ih.getElementCreator(
Lines 563-569 Link Here
563
                ((ProjectComponent) realChild).setLocation(child.getLocation());
582
                ((ProjectComponent) realChild).setLocation(child.getLocation());
564
            }
583
            }
565
            childWrapper.maybeConfigure(getProject());
584
            childWrapper.maybeConfigure(getProject());
566
            child.handleChildren(realChild, childWrapper);
585
            child.handleChildren(realChild, null);
567
            creator.store();
586
            creator.store();
568
            return true;
587
            return true;
569
        }
588
        }
(-)src/main/org/apache/tools/ant/MacroFragment.java (+34 lines)
Line 0 Link Here
1
/*
2
 *  Licensed to the Apache Software Foundation (ASF) under one or more
3
 *  contributor license agreements.  See the NOTICE file distributed with
4
 *  this work for additional information regarding copyright ownership.
5
 *  The ASF licenses this file to You under the Apache License, Version 2.0
6
 *  (the "License"); you may not use this file except in compliance with
7
 *  the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 *  Unless required by applicable law or agreed to in writing, software
12
 *  distributed under the License is distributed on an "AS IS" BASIS,
13
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 *  See the License for the specific language governing permissions and
15
 *  limitations under the License.
16
 *
17
 */
18
19
package org.apache.tools.ant;
20
21
import java.util.List;
22
23
/**
24
 * An interface for a task/type that can be used to
25
 * inject a list of unknown elements into a build file.
26
 */
27
public interface MacroFragment {
28
    /**
29
     * Convert the unknown element into a list of ues.
30
     * @param el the unknown element to convert.
31
     * @return the list of unknown elements.
32
     */
33
    List getUnknownElements(UnknownElement el);
34
}
(-)src/main/org/apache/tools/ant/taskdefs/MacroDef.java (-6 / +19 lines)
Lines 40-46 Link Here
40
 *
40
 *
41
 * @since Ant 1.6
41
 * @since Ant 1.6
42
 */
42
 */
43
public class MacroDef extends AntlibDefinition  {
43
public class MacroDef extends AntlibDefinition {
44
44
45
    private NestedSequential nestedSequential;
45
    private NestedSequential nestedSequential;
46
    private String     name;
46
    private String     name;
Lines 50-57 Link Here
50
    private String     textName   = null;
50
    private String     textName   = null;
51
    private Text       text       = null;
51
    private Text       text       = null;
52
    private boolean    hasImplicitElement = false;
52
    private boolean    hasImplicitElement = false;
53
    private boolean    fragment   = false;
53
54
54
    /**
55
    /**
56
     * Called by the fragmentdef subclass.
57
     * @param fragment the value to use (true).
58
     */
59
    protected void setFragment(boolean fragment) {
60
        this.fragment = true;
61
    }
62
63
    /**
55
     * Name of the definition
64
     * Name of the definition
56
     * @param name the name of the definition
65
     * @param name the name of the definition
57
     */
66
     */
Lines 122-129 Link Here
122
     * @return a sequential element to be configured.
131
     * @return a sequential element to be configured.
123
     */
132
     */
124
    public NestedSequential createSequential() {
133
    public NestedSequential createSequential() {
125
        if (this.nestedSequential != null) {
134
        if (nestedSequential != null) {
126
            throw new BuildException("Only one sequential allowed");
135
            throw new BuildException(
136
                "Only one sequential allowed");
127
        }
137
        }
128
        this.nestedSequential = new NestedSequential();
138
        this.nestedSequential = new NestedSequential();
129
        return this.nestedSequential;
139
        return this.nestedSequential;
Lines 300-316 Link Here
300
     */
310
     */
301
    public void execute() {
311
    public void execute() {
302
        if (nestedSequential == null) {
312
        if (nestedSequential == null) {
303
            throw new BuildException("Missing sequential element");
313
            throw new BuildException("Missing sequential or fragment element");
304
        }
314
        }
305
        if (name == null) {
315
        if (name == null) {
306
            throw new BuildException("Name not specified");
316
            throw new BuildException("Name not specified");
307
        }
317
        }
308
309
        name = ProjectHelper.genComponentName(getURI(), name);
318
        name = ProjectHelper.genComponentName(getURI(), name);
310
319
311
        MyAntTypeDefinition def = new MyAntTypeDefinition(this);
320
        MyAntTypeDefinition def = new MyAntTypeDefinition(this);
312
        def.setName(name);
321
        def.setName(name);
313
        def.setClass(MacroInstance.class);
322
        if (fragment) {
323
            def.setClass(MacroFragmentTask.class);
324
        } else {
325
            def.setClass(MacroInstance.class);
326
        }
314
327
315
        ComponentHelper helper = ComponentHelper.getComponentHelper(
328
        ComponentHelper helper = ComponentHelper.getComponentHelper(
316
            getProject());
329
            getProject());
(-)src/main/org/apache/tools/ant/taskdefs/MacroInstance.java (-10 / +24 lines)
Lines 242-248 Link Here
242
        this.text = text;
242
        this.text = text;
243
    }
243
    }
244
244
245
    private UnknownElement copy(UnknownElement ue) {
245
    /**
246
     * Copy an unknown element, substituting in macro attributes.
247
     * @param ue the unknown element to replace.
248
     * @return the copied unknown element.
249
     */
250
    protected UnknownElement copy(UnknownElement ue) {
246
        UnknownElement ret = new UnknownElement(ue.getTag());
251
        UnknownElement ret = new UnknownElement(ue.getTag());
247
        ret.setNamespace(ue.getNamespace());
252
        ret.setNamespace(ue.getNamespace());
248
        ret.setProject(getProject());
253
        ret.setProject(getProject());
Lines 327-339 Link Here
327
        return ret;
332
        return ret;
328
    }
333
    }
329
334
330
    /**
335
    /** setup parameters */
331
     * Execute the templates instance.
336
    protected void doParams() {
332
     * Copies the unknown element, substitutes the attributes,
333
     * and calls perform on the unknown element.
334
     *
335
     */
336
    public void execute() {
337
        presentElements = new HashMap();
337
        presentElements = new HashMap();
338
        getNsElements();
338
        getNsElements();
339
        processTasks();
339
        processTasks();
Lines 384-390 Link Here
384
                "Unknown attribute" + (copyKeys.size() > 1 ? "s " : " ")
384
                "Unknown attribute" + (copyKeys.size() > 1 ? "s " : " ")
385
                + copyKeys);
385
                + copyKeys);
386
        }
386
        }
387
    }
387
388
389
    /** Clear the parameters */
390
    protected void clearParams() {
391
        presentElements = null;
392
        localAttributes = null;
393
    }
394
395
    /**
396
     * Execute the templates instance.
397
     * Copies the unknown element, substitutes the attributes,
398
     * and calls perform on the unknown element.
399
     *
400
     */
401
    public void execute() {
402
        doParams();
388
        // need to set the project on unknown element
403
        // need to set the project on unknown element
389
        UnknownElement c = copy(macroDef.getNestedTask());
404
        UnknownElement c = copy(macroDef.getNestedTask());
390
        c.init();
405
        c.init();
Lines 399-406 Link Here
399
                throw ex;
414
                throw ex;
400
            }
415
            }
401
        } finally {
416
        } finally {
402
            presentElements = null;
417
            clearParams();
403
            localAttributes = null;
404
        }
418
        }
405
    }
419
    }
406
}
420
}
(-)src/main/org/apache/tools/ant/taskdefs/FragmentDef.java (+30 lines)
Line 0 Link Here
1
/*
2
 *  Licensed to the Apache Software Foundation (ASF) under one or more
3
 *  contributor license agreements.  See the NOTICE file distributed with
4
 *  this work for additional information regarding copyright ownership.
5
 *  The ASF licenses this file to You under the Apache License, Version 2.0
6
 *  (the "License"); you may not use this file except in compliance with
7
 *  the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 *  Unless required by applicable law or agreed to in writing, software
12
 *  distributed under the License is distributed on an "AS IS" BASIS,
13
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 *  See the License for the specific language governing permissions and
15
 *  limitations under the License.
16
 *
17
 */
18
19
package org.apache.tools.ant.taskdefs;
20
21
/**
22
 * The fragmentdef task.
23
 * This is the same as macrodef, exception that the
24
 * protected attribute fragment is set to true.
25
 */
26
public class FragmentDef extends MacroDef {
27
    {
28
        setFragment(true);
29
    }
30
}
(-)src/main/org/apache/tools/ant/taskdefs/MacroFragmentTask.java (+43 lines)
Line 0 Link Here
1
/*
2
 *  Licensed to the Apache Software Foundation (ASF) under one or more
3
 *  contributor license agreements.  See the NOTICE file distributed with
4
 *  this work for additional information regarding copyright ownership.
5
 *  The ASF licenses this file to You under the Apache License, Version 2.0
6
 *  (the "License"); you may not use this file except in compliance with
7
 *  the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 *  Unless required by applicable law or agreed to in writing, software
12
 *  distributed under the License is distributed on an "AS IS" BASIS,
13
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 *  See the License for the specific language governing permissions and
15
 *  limitations under the License.
16
 *
17
 */
18
19
package org.apache.tools.ant.taskdefs;
20
21
import java.util.List;
22
import org.apache.tools.ant.MacroFragment;
23
import org.apache.tools.ant.UnknownElement;
24
25
/**
26
 * A sub-class of a macroinstance that can be used (nearly) anywhere
27
 * in a build file.
28
 */
29
public class MacroFragmentTask extends MacroInstance implements MacroFragment {
30
    /**
31
     * Get the unknown elements to inject into the build document.
32
     * @param el the unknown element this is this fragment.
33
     * @return the replacement list of unknown elements.
34
     */
35
    public List getUnknownElements(UnknownElement el) {
36
        try {
37
            doParams();
38
            return copy(getMacroDef().getNestedTask()).getChildren();
39
        } finally {
40
            clearParams();
41
        }
42
    }
43
}
(-)src/main/org/apache/tools/ant/taskdefs/defaults.properties (+1 lines)
Lines 32-37 Link Here
32
fail=org.apache.tools.ant.taskdefs.Exit
32
fail=org.apache.tools.ant.taskdefs.Exit
33
filter=org.apache.tools.ant.taskdefs.Filter
33
filter=org.apache.tools.ant.taskdefs.Filter
34
fixcrlf=org.apache.tools.ant.taskdefs.FixCRLF
34
fixcrlf=org.apache.tools.ant.taskdefs.FixCRLF
35
fragmentdef=org.apache.tools.ant.taskdefs.FragmentDef
35
genkey=org.apache.tools.ant.taskdefs.GenerateKey
36
genkey=org.apache.tools.ant.taskdefs.GenerateKey
36
get=org.apache.tools.ant.taskdefs.Get
37
get=org.apache.tools.ant.taskdefs.Get
37
gunzip=org.apache.tools.ant.taskdefs.GUnzip
38
gunzip=org.apache.tools.ant.taskdefs.GUnzip
(-)docs/manual/CoreTasks/fragmentdef.html (+63 lines)
Line 0 Link Here
1
<!--
2
   Licensed to the Apache Software Foundation (ASF) under one or more
3
   contributor license agreements.  See the NOTICE file distributed with
4
   this work for additional information regarding copyright ownership.
5
   The ASF licenses this file to You under the Apache License, Version 2.0
6
   (the "License"); you may not use this file except in compliance with
7
   the License.  You may obtain a copy of the License at
8
9
       http://www.apache.org/licenses/LICENSE-2.0
10
11
   Unless required by applicable law or agreed to in writing, software
12
   distributed under the License is distributed on an "AS IS" BASIS,
13
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
   See the License for the specific language governing permissions and
15
   limitations under the License.
16
-->
17
<html>
18
19
  <head>
20
    <meta http-equiv="Content-Language" content="en-us"></meta>
21
    <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
22
    <title>FragmentDef Task</title>
23
  </head>
24
25
  <body>
26
27
    <h2><a name="fragmentdef">FragmentDef</a></h2>
28
    <h3>Description</h3>
29
    <p>
30
      This defines a new task using a <code>&lt;sequential&gt;</code>
31
      nested list of elements. This task is similar to
32
      <a href="macrodef.html">&lt;macrodef&gt;</a> except that
33
      arbitary element sequences may be placed within tasks or types.
34
    </p>
35
    <p>
36
      The parameters and nested elements are same as 
37
      <a href="macrodef.html">&lt;macrodef&gt;</a> - see that task for
38
      them. This description will just contain examples.
39
    <h3>Examples</h3>
40
    <p>
41
      The following defines two filesets and then places them in
42
      two different copy tasks.
43
    </p>
44
    <blockquote>
45
<pre class=code>
46
&lt;fragmentdef name="sourcefiles"&gt;
47
   &lt;sequential&gt;
48
     &lt;fileset dir="src/main/java" includes="**/*.java"&gt;
49
     &lt;fileset dir="src/main/resources"/&gt;
50
   &lt;/sequential&gt;
51
&lt;/fragmentdef&gt;
52
53
&lt;copy todir="allsource"&gt;
54
   &lt;sourcefiles/&gt;
55
&lt;/copy&gt;
56
57
&lt;m:remote-copy remotedir="wr0t@billy:backups"&gt;
58
   &lt;sourcefiles/&gt;
59
&lt;/m:remote-copy&gt;
60
</pre>
61
    </blockquote>
62
</body>
63
</html>
(-)docs/manual/coretasklist.html (+1 lines)
Lines 72-77 Link Here
72
<a href="CoreTasks/fail.html">Fail</a><br/>
72
<a href="CoreTasks/fail.html">Fail</a><br/>
73
<a href="CoreTasks/filter.html">Filter</a><br/>
73
<a href="CoreTasks/filter.html">Filter</a><br/>
74
<a href="CoreTasks/fixcrlf.html">FixCRLF</a><br/>
74
<a href="CoreTasks/fixcrlf.html">FixCRLF</a><br/>
75
<a href="CoreTasks/fragmentdef.html">FragmentDef</a><br/>
75
<a href="CoreTasks/genkey.html">GenKey</a><br/>
76
<a href="CoreTasks/genkey.html">GenKey</a><br/>
76
<a href="CoreTasks/get.html">Get</a><br/>
77
<a href="CoreTasks/get.html">Get</a><br/>
77
<a href="CoreTasks/unpack.html">GUnzip</a><br/>
78
<a href="CoreTasks/unpack.html">GUnzip</a><br/>

Return to bug 40678