I had previously posted a question asking about macro scoping, I thought
the community might be interested in my solution, perhaps the Ant experts
can tell me how dangerous of a hack it may be? (I'm on Ant 1.7.0, and
cannot up-rev)
First, restating my question:
Subject: "scoping" for macro definitions?
Is there a way to override a macro defined from a library I cannot
control, my goal is to provide a local implementation, but not have to
change all the callers.
I got close with <presetdef/> but I couldn't find the way to call "super"
on the macro, until I used org.apache.tools.ant.ComponentHelper to add a
new macro definition with a second name. The complete working example
follows should anyone wish to comment:
<?xml version="1.0" encoding="utf-8"?>
<project name="solution" default="testcase">
<!-- would be in separate file and imported: <import
file="library.xml" /> -->
<macrodef name="routine">
<attribute name="arg" />
<sequential>
<echo>Arg is @{arg}</echo>
</sequential>
</macrodef>
<!-- utility to duplicate macro definition -->
<scriptdef name="duplicateMacroDefinition" language="groovy">
<attribute name="existingName" />
<attribute name="newName" /><![CDATA[
import org.apache.tools.ant.ComponentHelper;
import org.apache.tools.ant.AntTypeDefinition;
String existing = attributes.get("existingname");
String newName = attributes.get("newname");
ComponentHelper helper =
ComponentHelper.getComponentHelper(project);
AntTypeDefinition m = null;
m = helper.getDefinition(existing);
if ( m == null ) {
log("Cannot get definition of ${existing}");
}
else {
m.setName(newName);
helper.addDataTypeDefinition(m);
}
]]>
</scriptdef>
<macrodef name="local_routine">
<attribute name="arg" default="" />
<sequential>
<echo>Run local logic first, maybe change param and call common
routine...</echo>
<common_routine arg="OVERRIDE" />
</sequential>
</macrodef>
<target name="setup">
<!-- make second name of common routine to avoid infinite loop -->
<duplicateMacroDefinition existingName="routine"
newName="common_routine" />
<!-- permits "override" of library routine so we can add logic -->
<presetdef name="routine">
<local_routine />
</presetdef>
</target>
<target name="testcase" depends="setup">
<!-- all existing calls are "fixed", make sample call -->
<routine arg="old" />
<!-- If we need original one... -->
<common_routine arg="use this"/>
</target>
</project>
--Cyril