Package org.backsource.utils.ant.edit

A virtual ant task to edit files in zip-files and directories while copying.

See:
          Description

Class Summary
Doc Bogus class to make package.html visable to javadoc.
 

Package org.backsource.utils.ant.edit Description

A virtual ant task to edit files in zip-files and directories while copying.

The edit package/ant task is mean to be used to do customized builds/and installs of packages that contains propertyfiles, deploymentdesriptors or other XML-files that need to be edited to fit into a certain environment. Typcial tasks is to install a customzied version of JBoss where all system params needed to be able to start more than one instance on the same machin are edited, or deployment/installation of ejb/war/ear files wich need to be custimized to the runtime envrionment.

The edit task is currently not done to an own ant task, but intead uses the building blocks of ant. At its core is a edit defintion file. You start by specifying all the edits that should be done to a directory/zip-file. By setting up some small stuff in your build.xml/project.xml the definitions in the file will be executed. This is done by first invoking the herin distributed edit.xml file. This file contains an ant task that will set up things correct, translate you definition file into an ant build file and finally invoke that file.

We will go through the steps here to use the edit task.

First grab the edit.jar and timutils.jar from timutils. See to it that timutils.jar is in your classpath and create a directory where you unpack the edit.jar.

Next you need to set four properties in your buildfile: edit.xsl, edit.prepocess.xsl, edit.run.dir and (if its not already set, tmp.dir).Say that you unpacked them i the resource dir, it might look like this:

    
    <property name="edit.xsl" value="resources/edit.xsl"/>
    <property name="edit.prepocess.xsl" value="resources/preedit.xsl"/>
    <property name="edit.run.dir" value="${basedir}/run"/>

The target need a place to put its generated build-files in. As you see above we use run. Remember to create it!

To invoke the virtual edit task you define an ant task to be run. It could look like this:

   <ant inheritRefs="true" antfile="${res.dir}/edit.xml" target="edit">
     <property name="edit.file" value="${jboss.edit}"/>
     <property name="edit.name" value="jbossinstall"/>
     <property name="edit.fromJar" value="${jboss.jar}"/>
     <property name="edit.toDir" value="${jboss.install.dir}"/>
   </ant>

Lets see what we have to fill in. When invoking the edit target in the edit.xml build-file we have to specify some properties. First we give it the edit.file. This should point to a edit definitions file (explained later). To be able to run the scripts we also have to give the stuff a name (edit.name) so edit can name files after something. The two last properties say what we want to edit, and where we want to place it. The folowing properties are possible to define: fromDir,fromJar,toDir,toJar. There are however currently obly three possible combinations: fromDir - toDir, fromJar - toDir, fromJar - toJar.

The central thing in this is the edit definition file. The file starts with a root element <edit>. It then caintains one or more elements of <xmleditor>, <propertyeditor> or nested <edit> elements. Each such element defines an type of edit filter to use, the files to use it on and the actions to take on those files. The nested edit element is for editing embedded zip/jar/war/ear/sar/aar files. Lets start by taking a quick look at a possible (made up file) for JBoss:

  <edit>
  <!-- edit the files in conf -->
  <xmleditor include="**/conf/jboss-service.xml">
        <replace xpath="//mbean/attribute[@name='Port'][text()='1099']" value="${jboss.jndi.jnp.port}"/>
       <replace xpath="//mbean/attribute[@name='Port'][text()='8083']" value="${jboss.webservice.port}"/>
       <replace xpath="//mbean/attribute[@name='RMIObjectPort']" value="${jboss.rmi.object.port}"/>
  </xmleditor>

  <propertyeditor include="**/server/all/conf/jacorb.properties">
      <replace key="OAPort" value="${jboss.orb.OAPort}"/>
  </propertyeditor>

  <edit fromJar="subjar.sar" toJar="subjar.sar">
    <xmleditor file="META-INF/testconf.xml">
       <replace xpath="//mbean/attribute[@name='Port'][text()='8083']" value="${jboss.codebase.port}"/>
    </xmleditor>
</edit>

xmleditor is an inline XML editor. With it one can insert/replace and remove content and elements in an XML file. It is possible both to replace attribute values, element content and XML fragments. We also se a propertyeditor. With this you can edit java style property file and replace the value for certain keys or remove keys altogether. Both elements takes either the attribute include - which works much the same way as ant includes does - or file which points out a file to work on. Both elements then take one or more actions, specifyed as replace, insert or remove. However, the attributes for the actions differ. An xmleditor takes the attribute xpath, which is an XPath expression pointing to the node one want to do an action on. For more information on how this works see XmlFilter. The instead takes a key attribute, which points to a key in a property file. For more information on how it works see PropertyFilter.

The xmleditor element takes another type of elements to: <param>. With it you may specify if the outputed XML should be indented or not:

<param name="indent" value="false"/>

And you may also give a reference to a globaly defines XMLCatalog:

<param name="xmlcatalogref" value="jbosscatalog"/>

edit also takes nested edit elements. You may therefor do inline editing of compressed files. The nested edit element takes the fromJar and toJar attributes. The fromJar attribute must fully specify the path to the jarfile inside the thing you are editing.

If we look closer to the definition we see that the values are defines as ant property references, eg: ${jboss.jndi.jnp.port}. This is part of a pattern to use when using edit. If we hardcoded the values here, we end up defining a new edit file for each type of install. Instead we prefere to define them in an external property file. We might even use an XML based propertyfile to easilly define XML fragments we wants to insert. Here is a couple of examples of how to do this.

Have a property file, which may be redefined on the commandline when invokning ant.

jboss.jndi.jnp.port=1099
jboss.webservice.port=8083
jboss.rmi.object.port=4444
jboss.log4j.file.pattern=%d %-5r %-5p [%c] (%t:%x) %m%n
jboss.orb.OAPort=8683
jboss.hypersonic.port=1476
jboss.mq.oil.port=8090
jboss.mq.uil.port=8091
jboss.web.port=8080

Load it in ant.

   <!-- Load properties -->
   <loadproperties srcFile="${jboss.properties}"/>
   <filter filtersfile="${jboss.properties}"/>

If you need to insert XML define an XML propery file.

<jboss>
  <jndi><port>1299</port></jndi>
   <codebase><port>8383</port></codebase>
  <a><![CDATA[ hej ]]></a>
  <login-config>
   <newdomains><![CDATA[<application-policy name = "my">
       <authentication>
          <login-module code = "org.jboss.security.auth.spi.UsersRolesLoginModule"
             flag = "required" />
       </authentication>
    </application-policy>
     ]]>
    </newdomains>
   </login-config>
   <replace><myelement/></replace>
   <ats name="Replace">My Data</ats>
</jboss>

Load that to into ant. Observe that the XMLProperty class that comes with ant 1.5 still does not handle CDATA. Use ant from timutils, or check CVS if out patch has been applied.

   <!-- An xml templates file may contain tokens to filter, therfore we
        copy it first -->
   <copy file="${jboss.template}" tofile="${tmp.dir}/jboss-template.xml" filtering="yes" overwrite="yes"/>
   <xmlproperty file="${tmp.dir}/jboss-template.xml" collapseAttributes="true" />

Now you may use the ant propertys in your edit definition file.

Extending edit

If you want to extend an edit file you get somewhere from it is possible by using the edit.merge.dir property and the mergepoint element. The edit.merge.dir properties point to a directory containing files with the naming convetion edit-*.xml, where * is any name. These file may contain xmleditor,propertyeditor or sub edit tasks (no root element). When run whith the edit.merge.dir property set all files in the directory will be merged into the point where the <mergepoint> is in the edit file. If (and only if) the original edit definition file contains that element, ie. <mergepoint>, will the content of the property be inserted. This means that you may build installers - for example a JBoss installer - which may be incorporated into other projects, where you add more filtering targets to the dit task.

For a live example of how this is used, see the project jboss-installer



Copyright © 2000-2004 Backsource. All Rights Reserved.