| “Strategies in (*)ability” | [iDareMedia] [JWare] [PET] [CI-Dashboard] |
[guide] <artifactdef> |
If a SAM artifact retrieval mechanism (ARM) functions as a simplifying facade to your system’s processing, then SAM artifact definition elements (<artifactdef>s) supply the client script’s delegates or proxies to that facade. Like their counterparts in other application domains, the SAM artifactdef acts as a client-side abstraction that shields your driver scripts from the public but still volatile interaction details of each ARM. More importantly, artifactdefs reflect your workflow and nomenclature; they reduce the dependency of your scripts and your client’s scripts on any particular ARM.
In spite of its name, artifactdefs are not like other Ant “def” elements— you can only define them as part of a group called an artifact definition catalog (see <add-artifactdefs>). A catalog lets you configure how the enclosed artifact definitions and their ARMs are located, loaded, executed, and listened-to. A catalog also ensures its definitions are properly installed into the current SAM build-iteration so they are available to your driver project as well as any child or sub projects.
An artifact definition consists of a named set of conceptually related ARM configurations called versions (<version>). We say versions must be “conceptually related” because how each version generates the final artifact can differ substantially. The important thing to remember is that from a driver or client script’s perspective, each version represents a slight variation of a common artifact generating procedure; the “devil hidden in the details” is your problem. Once loaded, an artifact definition is available to your Ant script as a set of presetdef elements named like artifactname-versionname; see the “Naming Versions” section for more information. The snippet below shows how an artifactdef’s name and a version’s name combine to create a presetdef’s name.
[ Definition ] [ Presetdefs ]
<artifactdef name="varconfs"> -----+
<version name="java">… +--> <varconfs-java/>
<version name="webapp">… +--> <varconfs-webapp/>
</artifactdef> -----+
A <version> definition will include everything your script needs for a particular use of an ARM including setup, custom call parameters, and finally result announcement. A version is also where you define whether the client script can override your parameter values and where you define whether the artifact is generate-once or (re)generate-per-use. You should design each version to stand on its own within the context of the called ARM’s known constraints. An artifact definition can have as many versions as you decide. The general form of an <artifactdef> is shown below.
<artifactdef name="artifactname">
<defaults>
<method use="arm's uri"/>
[shared options for all]
<version name="variation-a">
[custom options for (a)]
<version name="variation-b">
[custom options for (b)]
…
<version name="variation-N">
[custom options for (N)]
</artifactdef>
In its simplest form, an artifact definition is a direct, single, parameterless call to a retrieval method (<method>) like the timestamps definition below is to the mktimestamps ARM. At first, you might think that creating such a limited artifact definition is not useful; but you would be wrong. It is actually very useful to create these definitions when you consider all of the hidden benefits SAM provides with artifactdefs like dynamic ARM loading, immutable presetdefs, and observable artifact announcements. And, of course, you can change from this one-to-one mapping to something more complex without changing any dependent Ant scripts.
<artifactdef name="timestamps">
<version name="common"/>
<method use="mktimestamps"/>
</version>
</artifactdef>
A more typical artifact definition will include two or three versions that each call the same ARM but with different parameters (<parameter> and <refparameter>) and optionally different setup instructions (<setup>). Below is the outline of a definition javasources that works with a mkmergedsources ARM. This definition uses many of the options available to you when creating a new artifactdef including the special <defaults> element that lets you define configuration that is common to all versions. Note that the order in which you declare versions is not important.
<artifactdef name="javasources">
<defaults>
<method use="mkmergedsources"/>
<version use="latest"/>
<parameter name="type" value="java"/>
<parameter name="modulelist" value="ui,uimobile,web,mbeans,db"/>
<parameter name="todir" value="@{src}"/>
</defaults>
<version name="latest">
<setup>
<varconfs-java/>
</setup>
<parameter name="varconfs" value="@{varconfs-java.loc}"/>
</version>
<version name="stable">
<setup>
<varconfs-java-stable/>
</setup>
<parameter name="varconfs" value="@{varconfs-java-stable.loc}"/>
<parameter name="tag" value="r1-1build16"/>
</version>
<version name="adhoc" inherit="latest" allowoverrides="yes">
<announcement>
<include parameter="tag"/>
<include parameter="modulelist"/>
<include parameter="varconfs"/>
</announcement>
</version>
</artifactdef>
Occasionally, you will need to make a version’s definition completely different from all others including its retrieval method. In the definition below, the xmlprototype version uses a different method from all other versions; in fact, it uses a local macrodef mkreadmes-xml. Artifact definitions can use four kinds of retrieval methods: antlib-based ARMs, local targets, local macrodefs, and a small set of Ant tasks like <get> and <cvs>. You indicate the method’s type in its name (a URI format). Coincidentally, in this example, the parameters inherited as defaults to the ARM are also recognized by the local macrodef. However, you can also remove inherited parameter values as part of each version’s definition. Most packaged ARMs can start life as local macrodefs and migrate into standalone independent entities after they’ve been thoroughly tested.
<artifactdef name="readmes">
<defaults>
<method use="mkreadmes"/>
<version use="latest">
<parameter name="for" value="@{package}-readmes-pkg"/>
<parameter name="uploads" value="@{docs.dir}/readmes"/>
<parameter name="license" value="MIT"/>
<announcement>
<include parameter="for"/>
</announcement>
</defaults>
<version name="latest">
<parameter name="downloads" value="${cvs.modules}"/>
</version>
<version name="stable">
<parameter name="tag" value="r1-1build123"/>
<parameter name="downloads" value="${cvs.modules}/r1-1build123"/>
</version>
<version name="xmlprototype" announce="no">
<method use="macro:mkreadmes-xml"/>
<setup>
<directory-stylesheets/>
</setup>
<parameter name="downloads" value="${cvs.modules}/branch-xml"/>
<parameter name="xsl" value="@{stylesheets-readmes.loc}"/>
</version>
</artifactdef>
From a driver or client script’s perspective, each artifactdef version represents a slight variation of a common artifact generating procedure. You should remember this simple principle when you name your versions. Because your version’s name combines with the enclosing artifactdef’s name to form the client-facing hook into your build or test system, your name should reflect what makes this version different from the others.
<artifactdef name="materials"> -------+
... |
<version name="baselines"> +--> <materials-baselines/>
... |
<version name="ebfs"> +--> <materials-ebfs/>
... |
<version name="smoketest-uat"> +--> <materials-smoketest-uat/>
... |
</artifactdef> -------+
Some developers prefer to include a verb prefix in their artifactdefs’ names to better reflect the versions’s role as a specific function call. Either convention is perfectly acceptable; the more important idea is to be consistent and clear. (Note that if you plan to allow clients to decorate artifact generation, the noun-only naming convention is usually a more human-readable fit in that particular scenario.)
<artifactdef name="get-materials"> ------+
... |
<version name="baselines"> +--> <get-materials-baselines/>
... |
<version name="ebfs"> +--> <get-materials-ebfs/>
... |
<version name="smoketest-uat"> +--> <get-materials-smoketest-uat/>
... |
</artifactdef> -------+
The <artifactdef> task alleviates your need to write redundant definition XML through two reuse mechanisms: its <defaults> element and each <version> element’s inherit parameter. You can think of the <defaults> item as a special version definition that is always inherited by all other versions but cannot be called directly from a client script. The inherit parameter lets you explicitly base a new version definition on an existing one. With both options, your final version’s settings take precedence over any values predefined in the defaults or inherited from the parent.
Occasionally you will create a version definition that uses a custom retrieval method that is “mostly” compatible with a set of inherited parameters. To remove an inherited <parameter>, <refparameter>, or <announcement> value, redeclare the element in the version definition omitting its value attribute and setting its drop attribute to “yes”. Call and announcement parameters are the only inherited setup that you can remove from a new version’s definition; for instance, you cannot remove inherited setup steps.
It is often the case that a set of artifacts serve only as prerequisites for other, more complex, artifact definitions. Sometimes these prerequisite artifacts are as simple as a new empty directory or the expanded output of a previously downloaded archive file; basically, something can is easily produced by one of a small set of standard Ant tasks. To facilitate this common type of artifact definition, the artifactdef’s <method> directive supports a special kind of retrieval method called task methods. You use a task method by setting the artifactdef’s method to the task method’s name, prefixed with the task: string like: <method use="task:unjar">. The parameters of the artifactdef are those permitted by the named task; for example, to use the unjar method you must supply the archive’s name (src) and the output directory (dest) just as you would if you used the task standalone.
<artifactdef name="directory" description="Project directory structure">
<defaults announce="no">
<method use="task:chkdir"/>
<parameter name="locformat" value="ospath"/>
</defaults>
<version name="documents">
<parameter name="path" value="@{outputs.dir}/documents"/>
</version>
<version name="deployables" allowoverrides="yes">
<parameter name="clean" value="yes"/>
<parameter name="path" value="@{outputs.dir}/deploy"/>
</version>
<version name="stylesheets">
<parameter name="path" value="@{helpers.dir}/stylesheets"/>
<parameter name="mustexist" value="yes"/>
</version>
…
</artifactdef>
...
<artifactdef name="apidocs" description="Standard javadoc artifacts">
<defaults>
<method use="mkapidocs"/>
<setup>
<directory-documents/>
<directory-stylesheets/>
</setup>
<parameter name="css" value="@{directory-stylesheets.loc}/css"/>
<parameter name="html" value="@{directory-documents.loc}/apis"/>
</defaults>
…
</artifactdef>
SAM does not permit all Ant tasks as task methods; only a select few are acceptable. Currently the set is limited to Ant tasks: mkdir, get, cvs, unjar, unzip, gunzip, bunzip2, xslt, and sync, and AntX tasks: chkdir, mkdirs and newtempdir. The chkdir is a custom SAM task method that works better that the standard mkdir task in many cases of directory preparation; for instance, chkdir lets you scrub a directory’s contents and check to make sure the directory is read/writable to the Ant process. Refer to the SAM task methods guide for a complete description of all task methods and their options.
If successful, all task methods produce a physical artifact that can be located with a URL (as is required for all retrieval methods types). For the supported set of task methods, the artifact is usually obvious and its location is almost always the value of a dest or out type parameter.
The ultimate reason we create and use artifact definitions is to generate some artifact. Part of the contract an ARM has with SAM is to return an artifact location value on a successful completion. When you call an artifactdef from your scripts, that location value is automatically stored in a project property named, by default, after the version presetdef you used to call the ARM. Specifically, the default property’s name is formed like: presetdefname.loc; for example, if we called the <readmes-latest> presetdef from this preceding example, we would read the “readmes-latest.loc” property to get the path of the directory containing the final readmes files.
If you would like to use a different naming scheme for your location properties, you have two options. You can force SAM to update a different property per-use of a version presetdef by setting the presetdef’s special artifactlocation parameter to the name of your update property. Alternatively, you can define a custom locationproperty parameter for each artifactdef version. Below is an example Ant test script testLocs that changes the location property at the call-level to verify the feature works as described.
<add-artifactdefs>
<artifactdef name="directory" allowoverrides="no">
<defaults>
<method use="task:chkdir"/>
<parameter name="clean" value="no"/>
</defaults>
<version name="results">
<parameter name="path" value="${env.TMPDIR}/results"/>
</version>
…
</artifactdef>
...
<target name="testLocs">
<assert noneset="directory-results.loc,results.dir"/>
<directory-results artifactlocation="results.dir"/>
<assert isdirectory="${results.dir}" msg="'results.dir' found"/>
<assert isnotset="directory-results.loc"/>
<directory-results/>
<assert isdirectory="${directory-results.loc}" msg="'directory-results.loc' found"/>
<assert equals="${results.dir}" value="${directory-results.loc}"/>
</target>
By default, retrieval methods (all types, not just ARMs) are encouraged to return their artifact locations as URLs; this guideline emphasizes that SAM puts remote artifacts on the same footing as local ones. However, URLs can be inconvenient for certain kinds of artifact locations like local file system paths because few standard Ant tasks handle file paths described as file:// URLs. To alleviate this problem, retrieval methods that manipulate local artifacts could either return their locations as paths (and document that fact) or they could support some form of “transform” parameter that lets the caller decide whether or not URLs are OK. The builtin SAM task retrieval methods like cvs and get combine both approaches: they return file paths by default, but also support a “locformat” transform parameter that lets you get the location as a file:// URL.
To support the delayed evaluation of artifact definition parameter values, SAM lets you define your artifact definitions using the attribute reference syntax of Ant macrodefs, @{…}. Everytime the <artifactdef> is used, all such references are converted to their equivalent property values (as if the ${…} syntax has been used). Actually, you do not need to use the macro syntax because SAM will try to re-resolve unresolved property references whenever an <artifactdef> is used. However, using the alternative syntax makes your intention clear and safe from accidental premature assignment (which is particularly important if you use AntX value uris in your parameter values). The SAM “How-To” section includes an extended example using delayed property evaluation.
It is often the case that an artifact serves only as an aggregator for a small set of other artifacts; for example, an artifact “documents” that just creates, in order, a set of specific document types like licenses, javadocs, readmes, userguides, changelogs, etc., all defined by their own independent artifact definitions. To facilitate this common type of artifact definition, we have included a special no-op task method nothing to be used like: <method use="task:nothing">. This task method takes no parameters (all inherited parameters are ignored and do not have to be dropped). The following example is how you might declare the definition for an aggregate documents artifact documents.
<artifactdef name="documents">
<setup>
<directory-documents/>
<parallel>
<readmes/>
<apidocs/>
<changelogs/>
</parallel>
<examples/>
<userguides/>
</setup>
<method use="task:nothing"/>
</artifactdef>
In addition to changing parameters and setup instructions, you can affect the artifact generating process of an ARM in two ways: you can do some kind of special processing when an ARM is triggered (either before or after the ARM is actually called but before the artifact’s location is announced), or you can do some special processing in response to the artifact’s creation announcement (and recreation if the artifact is not cached for reuse). Both cases are handled by the SAMS component known as a reaction definition or <reactiondef>. Like an artifact definition, a reaction definition’s implementation can be one of the four standard method types SAMS understands: a dynamically loaded (regular) antlib, a local target, a local macrodef, or a task method. The SAMS overview includes a sample reaction definition that is triggered whenever javadocs are generated. Read the <add-reactiondefs> documentation for more information about installing your own reaction scriptlets.
Once we started using SAMS to organize our Ant scripts, we quickly realized that being able to generically specify how to undo or cleanup the output of an ARM would be a very useful ability particularly if it could be packaged with the ARM’s antlib and easily linked to the artifactdef. So SAMS lets you declare an undo macrodef within your ARM script that you can later link to a cleanup definition or <cleanupdef>.
| Attribute | Description | Required |
| name | The main script-facing name of all artifacts generated by this definition. Version names are appended to this name (separated by a dash “-”). If a default version is declared, its standalone element name will be this value. You are responsible for ensuring this value is a valid XML element name. | Yes unless being loaded from a file. |
| standalone | Tells this definition whether it should produce standalone <prefsetdef>s of its various versions. You should set this option to “no” if this definition will accessed through artifactdef value URIs only. | No; defaults “yes”. |
| file, resource, url |
Location of a standalone <artifactdef> file. The file must contain a single declaration element to be considered valid. If defined, no other parameter or nested element is permitted. | No; one when specified. |
The <assert> element lets you link an AntX assertion to this definition. Note that all artifactdef assertions are run once as a batch before the first artifactdef version is used not as the definition is loaded. The format of this <assert> element is exactly the same as the standalone AntX <assert>; if the assertion fails, SAMS will signal a build error at the point in the script that used the artifactdef. Unlike the <fixturecheck> element (see next), assertions can be disabled by turning the disable AntX assertions option on.
The <fixturecheck> element lets you insert a fixture verification assertion into this definition so you can verify that all required environment settings have been defined. Unlike an assertion, a fixture check is evaluated as the artifactdef is being parsed and loaded so it should be used to verify properties that the definition expects to exist when the definition is loaded. The format of this element is exactly the same as the standalone AntX <fixturecheck> element; if the check fails <artifactdef> will signal a build error.
The <defaults> element lets you define the default settings for all other versions within the definition. You can think of the <defaults> as a special version declaration that is always inherited by all other versions but cannot be called directly from a script. Although none of a <defaults>’s attributes or nested elements are required, you would not create a defaults element unless there was some default value to be defined.
| Attribute | Description | Required |
| announce | Sets whether artifact locations will be inserted into the SAM iteration’s locations catalog for all SAM components (including this one) to see and (re)use. | No; defaults “yes”. |
| usecache | Sets whether each definition will reuse previously determined artifact locations to avoid re-running definition methods unnecessarily. | No; defaults “yes”. |
| allowoverrides | Sets whether each standalone presetdef will permit parameter overrides from the client Ant script. This option does not pertain to the artifact location property (which you can always override per use). | No; defaults “no”. |
The <setup> taskset lets you define a set of other artifacts that must exist before this definition executes. You can only nest other artifact definition’s presetdefs, the <parallel>, and the <sequential> element inside a setup taskset. You are responsible for ensuring a preparation artifact does not indirectly depend on the artifactdef being generated (thereby creating a circular execution path).
The <method> element lets you define the artifact retrieval method that versions of this artifactdef will use by default. This element requires a single use parameter that represents the name of the method to call. SAM supports several kinds of retrieval mechanisms, the most common one being an antlib based ARM. However, you can also use local macrodefs, local targets, and even a small subset of standard Ant tasks as retrieval methods; see the description of a version’s <method> for full details.
| Attribute | Description | Required |
| use | The URI of the method to call. | Yes. |
The <version> element lets you define the default version for this artifactdef if one is not specified explicitly; for instance, this is the version that is triggered when the versionless standalone presetdef element is used. This element requires a single use parameter that defines the name of the version to use.
| Attribute | Description | Required |
| use | The name of the default artifactdef version. | Yes. |
The <parameter> element lets you define a default value for a particular retrieval method parameter. The named parameter must be known to the retrieval method; for instance, if using a macrodef to generate an artifact, the parameter must be declared as a valid attribute of the macrodef. You can set the parameter’s value by using either the value parameter or the text body of the element.
| Attribute | Description | Required |
| name | The name of the parameter (all lowercased). | Yes. |
| value | The value of the parameter. Delayed property references can be declared using the Ant macrodef attribute reference syntax, @{…}. You can also set the parameter’s value as the text body of the element. | Yes if body text is empty. |
| trim | Set to “yes” to have the parameter’s value trimmed of surrounding whitespace before being used. This option is useful when using the body of the element to set its value. | No. |
| if | A property name. The parameter is included if and only if this property exists in the target project. | No. |
| unless | A property name. The parameter is included if and only if this property does not exist in the target project. | No. |
The <refparameter> element lets you define a default value for a retrieval method parameter that expects a reference to a project data object like a fileset or a classpath. You would use a <refparameter> to declare, embedded in the artifactdef itself, the data object that SAM should automatically install (under an dynamically generated reference id) and uninstall whenever the ARM is called. The actual data object is defined as a single nested element of the <refparameter>. The named reference parameter must be known to the retrieval method; for instance, if using a macrodef to generate an artifact, the parameter must be declared as a valid attribute of the macrodef.
Reference parameters are almost always used to declare an Ant dataset of some sort like a <fileset>, <patternset>, or a <path>. By declaring the value of complex parameters directly inside the artifactdef, you keep data necessary for the correct functioning of your artifactdef with the definiton itself. When combined with proper <assert>s, reference parameters let you can define very stable and maintainable artifact definitions.
| Attribute | Description | Required |
| name | The name of the parameter (all lowercased). | Yes. |
| if | A property name. The parameter is included if and only if this property exists in the target project. | No. |
| unless | A property name. The parameter is included if and only if this property does not exist in the target project. | No. |
Nested Elements[1]
You can nest at most one data object declaration inside a single <refparameter>. Although you can use any legitimate Ant, AntX, or SAMS data type, executable tasks are usually not embedded as reference parameters.
The <announcement> element lets you define a set of context properties that should be included, by default, as part of the artifact’s announced context. Whenever SAM tries to determine if an artifact has already been generated, it will include the current request’s values for these properties in its search operation. You would add parameter-based context to an artifact if you planned to use different parameter values to differentiate variations of a single artifactdef version.
Nested Element: <include>
The include element lets you define a single parameter or property to include in announcement context.
| Attribute | Description | Required |
| parameter | The name of the parameter or property to include. Parameters take precedence over project properties of the same name. | Yes. |
| value | The explicit announcement context value for the item. | No. |
| if | A property name. The parameter is included if and only if this property exists in the target project. | No. |
| unless | A property name. The parameter is included if and only if this property does not exist in the target project. | No. |
The <version> element lets you define all the parameters for a particular artifact generating call to an ARM. For each unspecified version parameter, the default setting is determined by the version’s inherited or defaults configuration.
| Attribute | Description | Required |
| name | The version’s symbolic application name. This name will be used in artifact URIs (as part of fragment) to indicate this particular variant of the enclosing artifact definition. If this version is part of a standalone artifact definition, its name should also be a valid as part of an XML element's tag. | Yes. |
| locationproperty | Name of the location property the standalone presetdef of this version will update. If not specified, the location property is defined as a combination of the artifactdef’s name and this version’s name. | No; calculated. |
| inherit | Name of another version from which this version will get its configuration. Inherited configuration is combined with both the artifactdef’s defaults and the version’s own settings. | No. |
| announce | Sets whether the artifact’s location will be inserted into the SAM iteration’s locations catalog for all SAM components (including this one) to see and (re)use. This options does not control whether the version’s location property is updated. | No. |
| usecache | Sets whether each invocation of this version will reuse previously determined artifact locations to avoid re-running definition methods unnecessarily. | No. |
| allowoverrides | Sets whether each use of this version’s standalone presetdef will permit parameter overrides from the client Ant script. This option does not pertain to the version’s location property (which you can always override per use). | No. |
| standalone | Tells this version whether it should produce a standalone <prefsetdef>. You should set this option to “no” if this version only defines a set of common parameters for other versions. | No; defaults “yes”. |
The <setup> taskset lets you define a set of other artifacts that must exist before this version executes. You can only nest other artifact definition’s presetdefs, the <parallel>, or the <sequential> element inside a setup taskset. A version’s setup is run after an inherited setup which is run after any default setup. You are responsible for ensuring a preparation artifact does not indirectly depend on the artifactdef being generated (thereby creating a circular execution path).
The <method> element lets you define the artifact retrieval method that this version uses to generate the artifact. This element requires a single use parameter that represents the name of the method to call. The format of the URI you must use to declare the method’s name is: [protocol:]methodname where protocol is one of the known SAMS method types and methodname is the requested method of that type. The default method type, antlib-based ARMs, does not require a protocol prefix; all other method types do. Use macro: to name a local macrodef as your method. Use target: to name a local target as your method. Use task: to name one of the builtin SAM task methods (like get or cvs). If you use a target: method, the named target must exist in the artifactdef’s triggering project. In other words, if the artifact definition is used from a child project (say from a call to <subant>), the target must exist in the child project; targets defined in the parent (or artifactdef parent project) are not visible to the child project.
| Attribute | Description | Required |
| use | The URI of the method to call. | Yes. |
The <parameter> element lets you define or undefine a value for a particular retrieval method parameter. The named parameter must be known to the retrieval method; for instance, if using a task method to generate an artifact, the parameter must be declared as a valid parameter of the called task. You can set the parameter’s value by using either the value parameter or the text body of the element.
| Attribute | Description | Required |
| name | The name of the parameter (all lowercased). | Yes. |
| value | The value of the parameter. Delayed property references can be declared using the Ant macrodef attribute reference syntax, @{…}. You can also set the parameter’s value as the text body of the element. | Yes unless dropping or no body text. |
| drop | Set to “yes” if this parameter should be dropped from all inherited parameters. You might need to drop inherited parameters if you want to use a default parameter value (for example in a macrodef) or if this version uses a method different from the inherited one and needs a different set of parameters. This parameter’s name can refer to both simple and reference parameters for dropping. | No. |
| trim | Set to “yes” to have the parameter’s value trimmed of surrounding whitespace before being used. This option is useful when using the body of the element to set its value. | No. |
| if | A property name. The parameter is included if and only if this property exists in the target project. | No. |
| unless | A property name. The parameter is included if and only if this property does not exist in the target project. | No. |
The <refparameter> element used by the <version> element is the same as the <refparameter> used by the <defaults> element.
The <announcement> element used by the <version> element is the same as the <announcement> used by the <defaults> element.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam fermentum vestibulum est. Cras rhoncus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed quis tortor. Donec non ipsum.
<?xml version="1.0"?>
<run-configuration name="root" description="Bootstrap build configuration.">
<-- [required] -->
<assert isset="productid" msg="property 'productid' defined"/>
<-- [defaults] -->
<tstamp/>
<property name="audience" value="dev"/>
<-- [required] -->
<assert filenotempty="conf-${audience}.xml" msg="conf-${audience}.xml valid"/>
<xmlproperty file="conf-${audience}.xml"/>
<-- [features] -->
<managebundles action="install-root" file="default.msgs"/>
<manageuris action="enable" file="valueuris.xml"/>
...
</run-configuration>