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

(-)src/main/org/apache/tools/ant/UnknownElement.java (-44 / +62 lines)
Lines 180-199 Link Here
180
            if (getWrapper().getId() != null) {
180
            if (getWrapper().getId() != null) {
181
                this.getOwningTarget().replaceChild(this, (Task) realThing);
181
                this.getOwningTarget().replaceChild(this, (Task) realThing);
182
            }
182
            }
183
       }
183
        }
184
184
185
186
        // configure attributes of the object and it's children. If it is
187
        // a task container, defer the configuration till the task container
188
        // attempts to use the task
189
190
        if (task != null) {
185
        if (task != null) {
191
            task.maybeConfigure();
186
            task.maybeConfigure();
192
        } else {
187
        } else {
193
            getWrapper().maybeConfigure(getProject());
188
            getWrapper().maybeConfigure(getProject());
194
        }
189
        }
195
190
196
        handleChildren(realThing, getWrapper());
191
        handleChildren(realThing, null);
197
    }
192
    }
198
193
199
    /**
194
    /**
Lines 301-306 Link Here
301
        children.add(child);
296
        children.add(child);
302
    }
297
    }
303
298
299
    private void recurHandleChild(
300
        ComponentHelper helper, Object parent, UnknownElement child) {
301
        // MacroFragment ?
302
        if (child.getTag().indexOf('-') != -1) {
303
            Class componentClass = helper.getComponentClass(
304
                child.getComponentName());
305
            if ((componentClass != null) &&
306
                (MacroFragment.class.isAssignableFrom(componentClass))) {
307
                child.maybeConfigure();
308
                
309
                MacroFragment macroFragment = (MacroFragment) child.realThing;
310
                
311
                List replaced = macroFragment.getUnknownElements(child);
312
                for (Iterator i = replaced.iterator(); i.hasNext();) {
313
                    recurHandleChild(
314
                        helper, parent, (UnknownElement) i.next());
315
                }
316
                return;
317
            }
318
        }
319
        // not a macro fragment - a "Normal" element
320
        IntrospectionHelper ih = IntrospectionHelper.getHelper(
321
            getProject(), parent.getClass());
322
        try {
323
            if (!handleChild(
324
                    getNamespace(), ih, parent, child)) {
325
                if (!(parent instanceof TaskContainer)) {
326
                    ih.throwNotSupported(getProject(), parent,
327
                                         child.getTag());
328
                } else {
329
                    // a task container - anything could happen
330
                    // - just add the child to the container
331
                    TaskContainer container = (TaskContainer) parent;
332
                    container.addTask(child);
333
                }
334
            }
335
        } catch (UnsupportedElementException ex) {
336
            throw new BuildException(
337
                getWrapper().getElementTag()
338
                + " doesn't support the nested \"" + ex.getElement()
339
                + "\" element.", ex);
340
        }
341
    }
342
    
304
    /**
343
    /**
305
     * Creates child elements, creates children of the children
344
     * Creates child elements, creates children of the children
306
     * (recursively), and sets attributes of the child elements.
345
     * (recursively), and sets attributes of the child elements.
Lines 308-357 Link Here
308
     * @param parent The configured object for the parent.
347
     * @param parent The configured object for the parent.
309
     *               Must not be <code>null</code>.
348
     *               Must not be <code>null</code>.
310
     *
349
     *
311
     * @param parentWrapper The wrapper containing child wrappers
350
     * @param notUsed Not used.
312
     *                      to be configured. Must not be <code>null</code>
313
     *                      if there are any children.
314
     *
351
     *
315
     * @exception BuildException if the children cannot be configured.
352
     * @exception BuildException if the children cannot be configured.
316
     */
353
     */
317
    protected void handleChildren(
354
    protected void handleChildren(
318
        Object parent,
355
        Object parent,
319
        RuntimeConfigurable parentWrapper)
356
        RuntimeConfigurable notUsed)
320
        throws BuildException {
357
        throws BuildException {
358
        if (children == null) {
359
            return;
360
        }
361
            
362
        ComponentHelper helper = ComponentHelper.getComponentHelper(
363
            getProject());
364
321
        if (parent instanceof TypeAdapter) {
365
        if (parent instanceof TypeAdapter) {
322
            parent = ((TypeAdapter) parent).getProxy();
366
            parent = ((TypeAdapter) parent).getProxy();
323
        }
367
        }
324
368
325
        String parentUri = getNamespace();
369
        for (Iterator i = children.iterator(); i.hasNext();) {
326
        Class parentClass = parent.getClass();
370
            recurHandleChild(helper, parent, (UnknownElement) i.next());
327
        IntrospectionHelper ih = IntrospectionHelper.getHelper(getProject(), parentClass);
328
329
330
        if (children != null) {
331
            Iterator it = children.iterator();
332
            for (int i = 0; it.hasNext(); i++) {
333
                RuntimeConfigurable childWrapper = parentWrapper.getChild(i);
334
                UnknownElement child = (UnknownElement) it.next();
335
                try {
336
                    if (!handleChild(
337
                            parentUri, ih, parent, child, childWrapper)) {
338
                        if (!(parent instanceof TaskContainer)) {
339
                            ih.throwNotSupported(getProject(), parent,
340
                                                 child.getTag());
341
                        } else {
342
                            // a task container - anything could happen - just add the
343
                            // child to the container
344
                            TaskContainer container = (TaskContainer) parent;
345
                            container.addTask(child);
346
                        }
347
                    }
348
                } catch (UnsupportedElementException ex) {
349
                    throw new BuildException(
350
                        parentWrapper.getElementTag()
351
                        + " doesn't support the nested \"" + ex.getElement()
352
                        + "\" element.", ex);
353
                }
354
            }
355
        }
371
        }
356
    }
372
    }
357
373
Lines 528-537 Link Here
528
    private boolean handleChild(
544
    private boolean handleChild(
529
        String parentUri,
545
        String parentUri,
530
        IntrospectionHelper ih,
546
        IntrospectionHelper ih,
531
        Object parent, UnknownElement child,
547
        Object parent, UnknownElement child) {
532
        RuntimeConfigurable childWrapper) {
548
        RuntimeConfigurable childWrapper = child.getWrapper();
549
533
        String childName = ProjectHelper.genComponentName(
550
        String childName = ProjectHelper.genComponentName(
534
            child.getNamespace(), child.getTag());
551
            child.getNamespace(), child.getTag());
552
        
535
        if (ih.supportsNestedElement(parentUri, childName)) {
553
        if (ih.supportsNestedElement(parentUri, childName)) {
536
            IntrospectionHelper.Creator creator =
554
            IntrospectionHelper.Creator creator =
537
                ih.getElementCreator(
555
                ih.getElementCreator(
Lines 556-562 Link Here
556
                ((ProjectComponent) realChild).setLocation(child.getLocation());
574
                ((ProjectComponent) realChild).setLocation(child.getLocation());
557
            }
575
            }
558
            childWrapper.maybeConfigure(getProject());
576
            childWrapper.maybeConfigure(getProject());
559
            child.handleChildren(realChild, childWrapper);
577
            child.handleChildren(realChild, null);
560
            creator.store();
578
            creator.store();
561
            return true;
579
            return true;
562
        }
580
        }
(-)src/main/org/apache/tools/ant/MacroFragment.java (+7 lines)
Line 0 Link Here
1
package org.apache.tools.ant;
2
3
import java.util.List;
4
5
public interface MacroFragment {
6
    public List getUnknownElements(UnknownElement el);
7
}
(-)src/main/org/apache/tools/ant/taskdefs/MacroDef.java (-5 / +34 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-55 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
    /**
55
     * Name of the definition
56
     * Name of the definition
Lines 122-135 Link Here
122
     * @return a sequential element to be configured.
123
     * @return a sequential element to be configured.
123
     */
124
     */
124
    public NestedSequential createSequential() {
125
    public NestedSequential createSequential() {
125
        if (this.nestedSequential != null) {
126
        if (nestedSequential != null) {
126
            throw new BuildException("Only one sequential allowed");
127
            throw new BuildException(
128
                "Only one sequential or fragment allowed");
127
        }
129
        }
128
        this.nestedSequential = new NestedSequential();
130
        this.nestedSequential = new NestedSequential();
129
        return this.nestedSequential;
131
        return this.nestedSequential;
130
    }
132
    }
131
133
134
132
    /**
135
    /**
136
     * This is the fragment nested element of the macrodef.
137
     *
138
     * @return a sequential element to be configured.
139
     */
140
    public NestedSequential createFragment() {
141
        if (nestedSequential != null) {
142
            throw new BuildException(
143
                "Only one sequential or fragment allowed");
144
        }
145
        fragment = true;
146
        this.nestedSequential = new NestedSequential();
147
        return this.nestedSequential;
148
    }
149
150
    /**
133
     * The class corresponding to the sequential nested element.
151
     * The class corresponding to the sequential nested element.
134
     * This is a simple task container.
152
     * This is a simple task container.
135
     */
153
     */
Lines 329-345 Link Here
329
     */
347
     */
330
    public void execute() {
348
    public void execute() {
331
        if (nestedSequential == null) {
349
        if (nestedSequential == null) {
332
            throw new BuildException("Missing sequential element");
350
            throw new BuildException("Missing sequential or fragment element");
333
        }
351
        }
334
        if (name == null) {
352
        if (name == null) {
335
            throw new BuildException("Name not specified");
353
            throw new BuildException("Name not specified");
336
        }
354
        }
337
355
356
        if (fragment) {
357
            if (name.indexOf('-') == -1) {
358
                throw new BuildException(
359
                    "fragment macro name must contain a '-'");
360
            }
361
        }
362
338
        name = ProjectHelper.genComponentName(getURI(), name);
363
        name = ProjectHelper.genComponentName(getURI(), name);
339
364
340
        MyAntTypeDefinition def = new MyAntTypeDefinition(this);
365
        MyAntTypeDefinition def = new MyAntTypeDefinition(this);
341
        def.setName(name);
366
        def.setName(name);
342
        def.setClass(MacroInstance.class);
367
        if (fragment) {
368
            def.setClass(MacroFragmentTask.class);
369
        } else {
370
            def.setClass(MacroInstance.class);
371
        }
343
372
344
        ComponentHelper helper = ComponentHelper.getComponentHelper(
373
        ComponentHelper helper = ComponentHelper.getComponentHelper(
345
            getProject());
374
            getProject());
(-)src/main/org/apache/tools/ant/taskdefs/MacroInstance.java (-11 / +18 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
    protected UnknownElement copy(UnknownElement ue) {
246
        UnknownElement ret = new UnknownElement(ue.getTag());
246
        UnknownElement ret = new UnknownElement(ue.getTag());
247
        ret.setNamespace(ue.getNamespace());
247
        ret.setNamespace(ue.getNamespace());
248
        ret.setProject(getProject());
248
        ret.setProject(getProject());
Lines 327-339 Link Here
327
        return ret;
327
        return ret;
328
    }
328
    }
329
329
330
    /**
330
    protected void doParams() {
331
     * Execute the templates instance.
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();
331
        presentElements = new HashMap();
338
        getNsElements();
332
        getNsElements();
339
        processTasks();
333
        processTasks();
Lines 386-392 Link Here
386
                "Unknown attribute" + (copyKeys.size() > 1 ? "s " : " ")
380
                "Unknown attribute" + (copyKeys.size() > 1 ? "s " : " ")
387
                + copyKeys);
381
                + copyKeys);
388
        }
382
        }
389
383
    }
384
    
385
    protected void clearParams() {
386
        presentElements = null;
387
        localAttributes = null;
388
    }
389
    
390
    /**
391
     * Execute the templates instance.
392
     * Copies the unknown element, substitutes the attributes,
393
     * and calls perform on the unknown element.
394
     *
395
     */
396
    public void execute() {
397
        doParams();
390
        // need to set the project on unknown element
398
        // need to set the project on unknown element
391
        UnknownElement c = copy(macroDef.getNestedTask());
399
        UnknownElement c = copy(macroDef.getNestedTask());
392
        c.init();
400
        c.init();
Lines 401-408 Link Here
401
                throw ex;
409
                throw ex;
402
            }
410
            }
403
        } finally {
411
        } finally {
404
            presentElements = null;
412
            clearParams();
405
            localAttributes = null;
406
        }
413
        }
407
    }
414
    }
408
}
415
}
(-)src/main/org/apache/tools/ant/taskdefs/MacroFragmentTask.java (+16 lines)
Line 0 Link Here
1
package org.apache.tools.ant.taskdefs;
2
import java.util.List;
3
import org.apache.tools.ant.MacroFragment;
4
import org.apache.tools.ant.UnknownElement;
5
6
public class MacroFragmentTask extends MacroInstance
7
    implements MacroFragment {
8
    public List getUnknownElements(UnknownElement el) {
9
        try {
10
            doParams();
11
            return copy(getMacroDef().getNestedTask()).getChildren();
12
        } finally {
13
            clearParams();
14
        }
15
    }
16
}

Return to bug 40678