/*
* Copyright (C) Chaperon. All rights reserved.
* -------------------------------------------------------------------------
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package net.sourceforge.chaperon.ant;
import java.io.*;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.util.Vector;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.taskdefs.MatchingTask;
//import org.apache.xerces.parsers.SAXParser;
import org.apache.xml.serialize.Method;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import net.sourceforge.chaperon.grammar.Grammar;
import net.sourceforge.chaperon.grammar.SyntaxErrorException;
import net.sourceforge.chaperon.grammar.generator.SAXGrammarGenerator;
import net.sourceforge.chaperon.parser.generator.ParserTableGenerator;
import net.sourceforge.chaperon.parser.ParserTable;
/**
* The ant task builds a parser table from a grammar
*
* @author Stephan Michels
* @version %version%
*/
public class ChaperonBuild extends MatchingTask
{
private File destDir = null;
private File baseDir = null;
private String parsertableFilename = null;
private String targetExtension = ".html";
private Vector params = new Vector();
private File inFile = null;
private File outFile = null;
private FileUtils fileUtils;
private int msgLevel = Project.MSG_ERR;
private AntLogger logger;
/**
* Constructs the ant task
*/
public ChaperonBuild()
{
fileUtils = FileUtils.newFileUtils();
}
/**
* Executes the ant task
*
* @throws BuildException
*/
public void execute() throws BuildException
{
logger = new AntLogger(this, msgLevel);
DirectoryScanner scanner;
String[] list;
String[] dirs;
if (baseDir == null)
baseDir = project.resolveFile(".");
if ((inFile != null) && (outFile != null))
{
try
{
process(inFile, outFile);
}
catch (Exception e)
{
e.printStackTrace();
}
return;
}
if (destDir == null)
{
String msg = "destdir attributes must be set!";
throw new BuildException(msg);
}
scanner = getDirectoryScanner(baseDir);
log("Transforming into " + destDir, Project.MSG_INFO);
list = scanner.getIncludedFiles();
for (int i = 0; i < list.length; ++i)
process(baseDir, list[i], destDir);
dirs = scanner.getIncludedDirectories();
for (int j = 0; j < dirs.length; ++j)
{
list = new File(baseDir, dirs[j]).list();
for (int i = 0; i < list.length; ++i)
process(baseDir, list[i], destDir);
}
}
/**
* Set the base directory.
*
* @param dir The base directory
*/
public void setBasedir(File dir)
{
baseDir = dir;
}
/**
* Set the destination directory into which the parser table
* files should be copied to
*
* @param dir The destination directory
*/
public void setDestdir(File dir)
{
destDir = dir;
}
/**
* Set the desired file extension to be used for the targe
*
* @param name The extension to use
*/
public void setExtension(String name)
{
targetExtension = name;
}
/**
* Sets an output file
*
* @param outFile The output file
*/
public void setOut(File outFile)
{
this.outFile = outFile;
}
/**
* Sets the grammar file
*
* @param inFile The grammar file
*/
public void setIn(File inFile)
{
this.inFile = inFile;
}
/**
* Sets the message level
*
* @param inFile The grammar file
*/
public void setMsglevel(String msgLevel)
{
if (msgLevel.equalsIgnoreCase("debug"))
this.msgLevel = Project.MSG_DEBUG;
else if (msgLevel.equalsIgnoreCase("verbose"))
this.msgLevel = Project.MSG_VERBOSE;
else if (msgLevel.equalsIgnoreCase("info"))
this.msgLevel = Project.MSG_INFO;
else if (msgLevel.equalsIgnoreCase("warn"))
this.msgLevel = Project.MSG_WARN;
else if (msgLevel.equalsIgnoreCase("error"))
this.msgLevel = Project.MSG_ERR;
}
/**
* Processes the given input XML file and stores the result
* in the given resultFile.
*
* @param baseDir Base directory
* @param xmlFile Grammar file
* @param destDir Destination directory for the parser table files
* @param outputFile File for the build information
*
* @throws BuildException
*/
private void process(File baseDir, String xmlFile, File destDir) throws BuildException
{
String fileExt = targetExtension;
File outFile = null;
File inFile = null;
try
{
inFile = new File(baseDir, xmlFile);
int dotPos = xmlFile.lastIndexOf('.');
if (dotPos > 0)
outFile = new File(destDir,
xmlFile.substring(0, xmlFile.lastIndexOf('.'))
+ fileExt);
else
outFile = new File(destDir, xmlFile + fileExt);
if (!inFile.exists())
{
log("File " + inFile + " doesn't exists");
return;
}
if (inFile.lastModified() > outFile.lastModified())
{
ensureDirectoryFor(outFile);
log("Building a parsertable from " + inFile);
//SAXParser parser = new SAXParser();
XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
SAXGrammarGenerator grammargenerator = new SAXGrammarGenerator();
parser.setContentHandler(grammargenerator);
try
{
parser.parse(inFile.toString());
}
catch (SAXParseException se)
{
log("The grammar file is not valid: " + se.getMessage());
return;
}
Grammar grammar = grammargenerator.getGrammar();
ParserTableGenerator generator = new ParserTableGenerator(grammar);
generator.enableLogging(logger);
ParserTable parsertable = generator.getParserTable();
if (parsertable != null)
{
//System.out.println(grammar.getTokens());
//System.out.println(grammar.getProductions());
//parsertable.save(outFile.toString());
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(outFile));
out.writeObject(parsertable);
out.flush();
out.close();
//System.out.println(parsertable);
}
}
}
catch (Exception ex)
{
log("Failed to process " + inFile, Project.MSG_INFO);
if (outFile != null)
outFile.delete();
if (ex instanceof SyntaxErrorException)
{
log(ex.toString());
throw new BuildException("Build faild");
}
else
{
ex.printStackTrace();
throw new BuildException(ex);
}
}
}
/**
* Processes the given input XML file and stores the result
* in the given resultFile.
*
* @param inFile Grammar file
* @param outFile Parser table file
* @param outputFile File for the build information
*
* @throws BuildException
*/
private void process(File inFile, File outFile) throws BuildException
{
try
{
log("In file " + inFile + " time: " + inFile.lastModified(),
Project.MSG_DEBUG);
log("Out file " + outFile + " time: " + outFile.lastModified(),
Project.MSG_DEBUG);
if (!inFile.exists())
{
log("File " + inFile + " doesn't exists");
return;
}
if (inFile.lastModified() > outFile.lastModified())
{
ensureDirectoryFor(outFile);
log("Building a parsertable from " + inFile);
//SAXParser parser = new SAXParser();
XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
SAXGrammarGenerator grammargenerator = new SAXGrammarGenerator();
parser.setContentHandler(grammargenerator);
try
{
parser.parse(inFile.toString());
}
catch (SAXParseException se)
{
log("The grammar file is not valid: " + se.getMessage());
return;
}
Grammar grammar = grammargenerator.getGrammar();
ParserTableGenerator generator = new ParserTableGenerator(grammar);
generator.enableLogging(logger);
ParserTable parsertable = generator.getParserTable();
if (parsertable != null)
{
//System.out.println(grammar.getTokens());
//System.out.println(grammar.getProductions());
//parsertable.save(outFile.toString());
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(outFile));
out.writeObject(parsertable);
out.flush();
out.close();
//System.out.println(parsertable);
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
log("Failed to process " + inFile, Project.MSG_INFO);
if (outFile != null)
outFile.delete();
if (ex instanceof SyntaxErrorException)
{
log(ex.toString());
throw new BuildException("Build faild");
}
else
{
ex.printStackTrace();
throw new BuildException(ex);
}
}
}
/**
* Ensures the directories for biuld the parser tables
*
* @param targetFile
*
* @throws BuildException
*/
private void ensureDirectoryFor(File targetFile) throws BuildException
{
File directory = new File(targetFile.getParent());
if ((!directory.exists()) && (!directory.mkdirs()))
throw new BuildException("Unable to create directory: "
+ directory.getAbsolutePath());
}
}