blob: ea2eb13d7348ba529d920f30afa0370149753c22 [file] [log] [blame]
// -------------------------------------------------------------------------------
// Copyright (c)2000 Apache Software Foundation
// -------------------------------------------------------------------------------
package org.apache.ant;
import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
/**
* Helper class to build Project object trees.
*
* XXX right now this class only deals with the primary levels (project/target/task)
* and nothing else. Also, it only supports attributes....
*
* @author James Duncan Davidson (duncan@apache.org)
*/
public class ProjectBuilder {
// -----------------------------------------------------------------
// PRIVATE MEMBERS
// -----------------------------------------------------------------
/**
*
*/
private AntFrontEnd frontEnd;
/**
*
*/
private SAXParserFactory parserFactory;
/**
*
*/
private TaskManager taskManager;
// -----------------------------------------------------------------
// CONSTRUCTORS
// -----------------------------------------------------------------
/**
* Creates a new project builder that will build projects for the given
* Ant.
*/
public ProjectBuilder(AntFrontEnd frontEnd) {
this.frontEnd = frontEnd;
taskManager = new TaskManager(frontEnd);
parserFactory = SAXParserFactory.newInstance();
parserFactory.setValidating(false);
}
// -----------------------------------------------------------------
// PUBLIC METHODS
// -----------------------------------------------------------------
/**
* Builds a project from the given file.
*/
public Project buildFromFile(File file) throws AntException {
try {
SAXParser parser = parserFactory.newSAXParser();
BuilderHandlerBase bhb = new BuilderHandlerBase();
bhb.setProjectFileLocation(file);
parser.parse(file, bhb);
Project project = bhb.getProject();
project.setFrontEnd(frontEnd);
return project;
} catch (ParserConfigurationException pce) {
throw new AntException(pce);
} catch (SAXException se) {
Exception e = se.getException();
if (e != null && e instanceof AntException) {
// it's one of our own thrown from inside the parser to stop it
throw (AntException)e;
}
throw new AntException(se);
} catch (IOException ioe) {
throw new AntException(ioe);
}
}
/**
* Returns the TaskManager associated with this ProjectBuilder and
* the projects that it builds
*/
public TaskManager getTaskManager() {
return taskManager;
}
// -----------------------------------------------------------------
// INNER CLASSES
// -----------------------------------------------------------------
/**
* Inner class that implements the needed SAX methods to get all the
* data needed out of a build file.
*/
class BuilderHandlerBase extends HandlerBase {
private static final int STATE_START = 0;
private static final int STATE_PROJECT = 1;
private static final int STATE_TARGET = 2;
private static final int STATE_TASK = 3;
private static final int STATE_DESCRIPTION = 4;
private static final int STATE_PROPERTY = 5;
private static final int STATE_FINISHED = 99;
private int state = STATE_START;
private Vector tagCharDataStack = new Vector();
private Target currentTarget;
private Task currentTask;
Project project = new Project(frontEnd, taskManager);
Project getProject() {
return project;
}
void setProjectFileLocation(File file) {
project.setBaseDir(file.getParentFile());
}
public void startElement(String name, AttributeList atts) throws SAXException {
StringBuffer tagCharData = new StringBuffer();
tagCharDataStack.insertElementAt(tagCharData, 0);
switch (state) {
case STATE_START:
if (name.equals("project")) {
state = STATE_PROJECT;
String projectName = atts.getValue("name");
if (projectName != null) {
project.setName(projectName);
} else {
String msg = "Project element doesn't contain a name attribute";
AntException ae = new AntException(msg);
throw new SAXException(ae);
}
String defaultTarget = atts.getValue("default");
if (defaultTarget != null) {
project.setDefaultTargetName(defaultTarget);
}
String baseDirName = atts.getValue("basedir");
if (baseDirName != null) {
// XXX need to check to see if base dir exists
project.setBaseDir(new File(baseDirName));
}
} else {
String msg = "Project file doesn't contain a project element as " +
"its root node";
AntException ae = new AntException(msg);
throw new SAXException(ae);
}
break;
case STATE_PROJECT:
// valid tags in a project object are: description, property, and target
if (name.equals("description")) {
state = STATE_DESCRIPTION;
} else if (name.equals("property")) {
state = STATE_PROPERTY;
String propertyName = atts.getValue("name");
String propertyValue = atts.getValue("value");
if (propertyName == null) {
String msg = "Name attribute must be present on property";
AntException ae = new AntException(msg);
throw new SAXException(ae);
} else if (propertyValue == null) {
String msg = "Value attribute must be present on property";
AntException ae = new AntException(msg);
throw new SAXException(ae);
} else {
project.setProperty(propertyName, propertyValue);
}
} else if (name.equals("target")) {
state = STATE_TARGET;
String targetName = atts.getValue("name");
if (targetName != null) {
currentTarget = new Target(targetName);
project.addTarget(currentTarget);
} else {
// XXX figure out which target we're talking about!
// Like a location
String msg = "Target element doesn't contain a name attribute";
AntException ae = new AntException(msg);
throw new SAXException(ae);
}
String depends = atts.getValue("depends");
if (depends != null) {
StringTokenizer tok = new StringTokenizer(depends, ",", false);
while(tok.hasMoreTokens()) {
currentTarget.addDependancy(tok.nextToken().trim());
}
}
// XXX add dependency checks
} else {
System.out.println("Expecting target, got: " + name);
// XXX exception out
}
break;
case STATE_TARGET:
// Valid tags inside target: task
state = STATE_TASK;
//System.out.println("Getting task: " + name + " for target " +
// currentTarget);
// XXX need to validate that task type (name) exists in system
// else exception out.
currentTask = new Task(name);
currentTarget.addTask(currentTask);
for (int i = 0; i < atts.getLength(); i++) {
String atName = atts.getName(i);
String atValue = atts.getValue(i);
currentTask.addAttribute(atName, atValue);
}
break;
case STATE_TASK:
// data in here needs to be reflected into tasks
System.out.println("Not yet supporting tags inside of tasks!");
System.out.println("The project build will probably bust right here");
break;
default:
System.out.println("I'm not sure, but we're off base here: " + name);
// XXX exception out
}
}
public void characters(char ch[], int start, int length) throws SAXException {
StringBuffer buf = (StringBuffer)tagCharDataStack.elementAt(0);
buf.append(ch, start, length);
}
public void endElement(String name) throws SAXException {
StringBuffer elementData = (StringBuffer)tagCharDataStack.elementAt(0);
tagCharDataStack.removeElementAt(0);
switch (state) {
case STATE_TASK:
state = STATE_TARGET;
break;
case STATE_TARGET:
if (name.equals("target")) {
state = STATE_PROJECT;
} else {
System.out.println("Expecting to get an end of target, got: " + name);
// XXX exception out.
}
break;
case STATE_DESCRIPTION:
if (name.equals("description")) {
state = STATE_PROJECT;
project.setDescription(elementData.toString().trim());
} else {
System.out.println("Expecting to get an end of description, got: " +
name);
// XXX exception out.
}
break;
case STATE_PROPERTY:
if (name.equals("property")) {
state = STATE_PROJECT;
} else {
System.out.println("Expecting to get end of property, got: " + name);
// XXX exception out
}
break;
case STATE_PROJECT:
if (name.equals("project")) {
state = STATE_FINISHED;
} else {
System.out.println("Expecting to get end of project, got: " + name);
// XXX exception out;
}
break;
default:
System.out.println("I'm not sure what we are ending here: " + name);
// XXX exception out;
}
}
}
}