| // ------------------------------------------------------------------------------- |
| // 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; |
| } |
| } |
| } |
| } |