Folks,

Attached is an XMLC Task for Ant.  XMLC is the XML compiler from
Enhydra.org that converts XML(and HTML) documents to Java classes
implementing the W3C Java DOM.  
I had to slightly tweak XMLC to get it to play nice with Ant.  I'm
hoping the XMLC folks will add the change to the main tree.

Attached is:
xmlctask.jar 
- contains task source, api docs, README, xmlc.jar, xmlctask.jar

XMLC.java 
- the source

We have found the xmlc task useful, I hope you do as well.
Cheers,
Bill

Attachment: xmlctask.jar
Description: application/java-archive

/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact [EMAIL PROTECTED]
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 */

package org.apache.tools.ant.taskdefs.optional;

import org.apache.tools.ant.*;
import org.apache.tools.ant.taskdefs.*;

import java.lang.reflect.Method;
import java.io.*;
import java.util.*;

/**
 * Task to compile XML source files to Java DOMs using XMLC from Enhydra.org.
 * This task can take the following arguments:
 * <ul>
 * <li>classpath - classpath used by xmlc
 * <li>destdir - destination directory for generated class files
 * <li>ext - extension of files to compile, defaults to html
 * <li>info - xmlc option to print info about the page object
 * <li>methods - xmlc options to print signatures of access methods.
 * <li>options - options to pass through to xmlc
 * <li>package - package for compiled xml files
 * <li>parser - the parser xmlc should use to parse xml
 * <li>srcdir - source directory of xml files to compile
 * </ul>
 * Of these arguments, the <b>srcdir</b> and <b>destdir</b> are required.
 * <p>
 * When this task executes, it will recursively scan the sourcedir and
 * destdir looking for XML source files to compile.  By default, files
 * ending with '.html' will be compiled.  This can be changed by setting the 
 * <b>ext</b> attribute.  This task makes its compile decision based on 
timestamp.
 * <p>
 * This class is based on org.apache.tools.ant.taskdefs.Javac.
 *
 * @author James Davidson <a href="mailto:[EMAIL PROTECTED]">[EMAIL 
PROTECTED]</a>
 * @author Robin Green <a href="mailto:[EMAIL PROTECTED]">[EMAIL PROTECTED]</a>
 * @author Bill Thompson <a href="mailto:[EMAIL PROTECTED]">[EMAIL 
PROTECTED]</a> 
 */

public class XMLC extends MatchingTask {

    private Path src;
    private File destDir;
    private Path classpath;
    private String parser;
    private boolean methods = false;
    private boolean info = false;
    private String options;
    private String ext = "html";
    private String destPackage;

    protected Vector compileList = new Vector();

    /**
     * Create a nested <src ...> element for multiple source path
     * support.
     *
     * @return a nexted src element.
     */
    public Path createSrc() {
        if (src != null) {
            src = new Path();
        }
        return src;
    }

    /**
     * Set the package that files will be compiled to
     */
    public void setPackage(String destPackage) {
        this.destPackage = destPackage;
    }

    /**
     * Set extension of the files that will be compiled
     */
    public void setExt(String ext) {
        this.ext = ext;
    }

    /**
     * Set xmlc options.
     */
    public void setOptions(String options) {
        this.options = options;
    }

    /**
     * Set the parser used to parse xml template files.
     */
    public void setParser(String parser) {
        this.parser = parser;
    }

    /**
     * Set the methods flag.
     */
    public void setMethods(boolean methods) {
        this.methods = methods;
    }
    
    /**
     * Set the info flag.
     */
    public void setInfo(boolean info) {
        this.info = info;
    }
    
    /**
     * Set the source dirs to find the source Java files.
     */
    public void setSrcdir(Path srcDir) {
        if (src == null) {
            src = srcDir;
        } else {
            src.append(srcDir);
        }
    }

    /**
     * Set the destination directory into which the Java source
     * files should be compiled.
     */
    public void setDestdir(File destDir) {
        this.destDir = destDir;
    }

    /**
     * Set the classpath to be used for this compilation.
     */
    public void setClasspath(Path classpath) {
        if (classpath == null) {
            classpath = classpath;
        } else {
            classpath.append(classpath);
        }
    }

    /**
     * Maybe creates a nested classpath element.
     */
    public Path createClasspath() {
        if (classpath == null) {
            classpath = new Path();
        }
        return classpath;
    }


    /**
     * Executes the task.
     */
    public void execute() throws BuildException {
        // first off, make sure that we've got a srcdir and destdir

        if (src == null) {
            throw new BuildException("srcdir attribute must be set!");
        }
        
        String [] list = src.list();
        if (list.length == 0) {
            throw new BuildException("srcdir attribute must be set!");
        }
        
        if (destDir == null) {
            throw new BuildException("destdir attribute must be set!");
        }

        // scan source directories and dest directory to build up both copy 
lists and
        // compile lists
        resetFileLists();
        for (int i=0; i<list.length; i++) {
            File srcDir = (File)project.resolveFile(list[i]);
            if (!srcDir.exists()) {
                throw new BuildException("srcdir " + srcDir.getPath() + " does 
not exist!");
            }

            DirectoryScanner ds = this.getDirectoryScanner(srcDir);

            String[] files = ds.getIncludedFiles();

            scanDir(srcDir, destDir, files);
        }
        
        // compile the source files
        if (compileList.size() > 0) {
            log("Compiling " + compileList.size() + 
                " source files to " + destDir);

            for (int i = 0; i < compileList.size(); i++) {
                String strFile = (String)compileList.elementAt(i);
                int extIndex = strFile.lastIndexOf('.');
                String strExt = strFile.substring(extIndex + 1);
                int fileIndex = strFile.lastIndexOf(File.separator);
                String strFilename = strFile.substring(fileIndex + 1, extIndex);

                // build xmlc args
                Vector argList = new Vector();

                if (parser != null) {
                        argList.addElement("-parser");
                        argList.addElement(parser);
                }

                if (methods) argList.addElement("-methods");
                if (info) argList.addElement("-info");

                if (options != null) {
                        StringTokenizer st = new StringTokenizer(options);
                        while (st.hasMoreTokens()) {
                                argList.addElement(st.nextToken());
                        }
                }

                if (classpath != null) {
                        argList.addElement("-classpath");
                        argList.addElement(classpath.toString());
                }

                argList.addElement("-d");
                argList.addElement(destDir.getAbsolutePath());

                if (destPackage != null) {
                        argList.addElement("-class");
                        argList.addElement(destPackage + "." + strFilename + 
strExt.toUpperCase());
                } else {
                        argList.addElement("-class");
                        argList.addElement(strFilename + strExt.toUpperCase());
                }

                argList.addElement(strFile);

                log("Compilation args: " + argList.toString(), 
Project.MSG_VERBOSE);

                String[] args = new String[argList.size()];
                for(int j = 0; j < argList.size(); j++) {
                        args[j] = (String)argList.elementAt(j);
                }
                
                log("Compiling: " + strFile);

                // wgthom add a static method for this?
                org.enhydra.xml.xmlc.commands.xmlc.XMLC xmlc = new 
org.enhydra.xml.xmlc.commands.xmlc.XMLC();
                xmlc.compileHandleErrors(args);
            }
        }
    }

    /**
     * Clear the list of files to be compiled and copied.. 
     */
    protected void resetFileLists() {
        compileList.removeAllElements();
    }

    /**
     * Scans the directory looking for source files to be compiled.
     * The results are returned in the class variable compileList.
     */
    protected void scanDir(File srcDir, File destDir, String files[]) {

        long now = (new Date()).getTime();

        for (int i = 0; i < files.length; i++) {
            File srcFile = new File(srcDir, files[i]);
            if ( files[i].endsWith("." + ext) ) {
                int extIndex = files[i].lastIndexOf('.');
                String strExt = (files[i].substring(extIndex + 
1)).toUpperCase();
                String strFilename = files[i].substring(0, extIndex);

                String destPackageDir = "";     
                if ( destPackage != null ) {
                        destPackageDir = destPackage.replace('.', 
File.separatorChar) + File.separator;
                }
                
                File classFile = new File(destDir, destPackageDir + strFilename 
+ strExt + ".class"); 

                if (srcFile.lastModified() > now) {
                    log("Warning: file modified in the future: " +
                        files[i], Project.MSG_WARN);
                }

                if (srcFile.lastModified() > classFile.lastModified()) {
                    compileList.addElement(srcFile.getAbsolutePath());
                }
            }
        }
    }

}

Reply via email to