that its becoming a bit more clear how FrontEnds should interace with the core. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268338 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -1,201 +0,0 @@ | |||||
| // ------------------------------------------------------------------------------- | |||||
| // Copyright (c)2000 Apache Software Foundation | |||||
| // ------------------------------------------------------------------------------- | |||||
| package org.apache.ant; | |||||
| import java.io.*; | |||||
| import java.util.*; | |||||
| import java.util.zip.*; | |||||
| /** | |||||
| * Central class of Ant. This is the core 'kernel' of ant. Interfaces into | |||||
| * ant talk to Ant through this class. | |||||
| * | |||||
| * @author James Duncan Davidson (duncan@apache.org) | |||||
| */ | |||||
| public class Ant { | |||||
| // ----------------------------------------------------------------- | |||||
| // PRIVATE DATA MEMBERS | |||||
| // ----------------------------------------------------------------- | |||||
| /** | |||||
| * | |||||
| */ | |||||
| private File buildfile; | |||||
| /** | |||||
| * The front end running this. | |||||
| */ | |||||
| private AntFrontEnd frontEnd; | |||||
| /** | |||||
| * Manager of tasks. | |||||
| */ | |||||
| private TaskManager taskManager = new TaskManager(); | |||||
| /** | |||||
| * | |||||
| */ | |||||
| private Project project; | |||||
| // ----------------------------------------------------------------- | |||||
| // CONSTRUCTORS | |||||
| // ----------------------------------------------------------------- | |||||
| /** | |||||
| * Constructs a new Ant instance. | |||||
| */ | |||||
| public Ant(AntFrontEnd frontEnd) { | |||||
| this.frontEnd = frontEnd; | |||||
| setUpTaskPath(); | |||||
| } | |||||
| // ----------------------------------------------------------------- | |||||
| // PUBLIC METHODS | |||||
| // ----------------------------------------------------------------- | |||||
| /** | |||||
| * Sets additional path nodes onto the task lookup path. | |||||
| */ | |||||
| public void addTaskPathNode(File node) { | |||||
| taskManager.addTaskPathNode(node); | |||||
| } | |||||
| /** | |||||
| * Builds a target. | |||||
| */ | |||||
| public void buildTarget(String targetName) throws AntException { | |||||
| // notify FrontEnd that we are starting a build on a project | |||||
| frontEnd.notifyProjectStart(project); | |||||
| Target target = project.getTarget(targetName); | |||||
| frontEnd.notifyTargetStart(target); | |||||
| // XXX don't forget to execute dependancies first! | |||||
| Enumeration enum = target.getTasks().elements(); | |||||
| while (enum.hasMoreElements()) { | |||||
| Task task = (Task)enum.nextElement(); | |||||
| frontEnd.notifyTaskStart(task); | |||||
| AbstractTask aTask = taskManager.getTaskInstance(task.getType()); | |||||
| try { | |||||
| aTask.setProject(project); | |||||
| aTask.setAttributes(task.getAttributes()); | |||||
| boolean b = aTask.execute(); | |||||
| if (!b) { | |||||
| throw new AntException("STOP: Task " + task + | |||||
| " did not succeed"); | |||||
| } | |||||
| } catch (Exception e) { | |||||
| // XXX yes yes yes, this shouldn't be a catch all... | |||||
| throw new AntException("ERR: " + e); | |||||
| } | |||||
| frontEnd.notifyTaskEnd(task); | |||||
| } | |||||
| // notify frontEnd that we are done | |||||
| frontEnd.notifyTargetEnd(target); | |||||
| frontEnd.notifyProjectEnd(project); | |||||
| } | |||||
| /** | |||||
| * | |||||
| */ | |||||
| public Project getProject() { | |||||
| return project; | |||||
| } | |||||
| /** | |||||
| * Sets the buildfile to be used. This action triggers a parse of | |||||
| * the build file and assembles a Project object from it. | |||||
| */ | |||||
| public void setBuildfile(File file) throws AntException { | |||||
| buildfile = file; | |||||
| ProjectBuilder builder = new ProjectBuilder(); | |||||
| project = builder.buildFromFile(file); | |||||
| project.setAnt(this); | |||||
| System.out.println("Loaded Project: " + project.getName()); | |||||
| // XXX remove the dump after comfort level is reached | |||||
| System.out.println("Dump of Project:"); | |||||
| Enumeration enum = project.getTargets(); | |||||
| while (enum.hasMoreElements()) { | |||||
| Target target = (Target)enum.nextElement(); | |||||
| System.out.println(" Target: " + target.getName()); | |||||
| Enumeration enum2 = target.getTasks().elements(); | |||||
| while (enum2.hasMoreElements()) { | |||||
| Task task = (Task)enum2.nextElement(); | |||||
| System.out.println(" Task: " + task.getType()); | |||||
| Enumeration enum3 = task.getAttributeNames(); | |||||
| while (enum3.hasMoreElements()) { | |||||
| String atName = (String)enum3.nextElement(); | |||||
| String atValue = task.getAttribute(atName); | |||||
| System.out.println(" Att: " + atName + " = " + | |||||
| atValue); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| // ----------------------------------------------------------------- | |||||
| // PRIVATE METHODS | |||||
| // ----------------------------------------------------------------- | |||||
| /** | |||||
| * Sets up the taskpath based on the currently running operating | |||||
| * system. In general, the ordering of the taskpath is: user directory, | |||||
| * system directory, and then installation. This allows users or | |||||
| * system admins to override or add tasks. | |||||
| */ | |||||
| private void setUpTaskPath() { | |||||
| // 1st, add user's home dir. | |||||
| File f; | |||||
| String userHome = System.getProperty("user.home"); | |||||
| // generic unix | |||||
| f = new File(userHome + ".ant", "tasks"); | |||||
| if (f.exists() && f.isDirectory()) { | |||||
| taskManager.addTaskPathNode(f); | |||||
| } | |||||
| // macos x | |||||
| f = new File(userHome + "/Library/Ant", "Tasks"); | |||||
| if (f.exists() && f.isDirectory()) { | |||||
| taskManager.addTaskPathNode(f); | |||||
| } | |||||
| // windows -- todo | |||||
| // 2nd, add system local dir. | |||||
| // generic unix | |||||
| f = new File("/usr/local/ant/tasks"); | |||||
| if (f.exists() && f.isDirectory()) { | |||||
| taskManager.addTaskPathNode(f); | |||||
| } | |||||
| // macos x | |||||
| f = new File("/Library/Ant/Tasks"); | |||||
| if (f.exists() && f.isDirectory()) { | |||||
| taskManager.addTaskPathNode(f); | |||||
| } | |||||
| // windows -- todo | |||||
| // 3rd, add installation local dir. | |||||
| //System.out.println("BASE: " + this.getClass().getResource("/")); | |||||
| // XXX ---- not really sure how the best way of getting this info is... | |||||
| // hafta think about it. | |||||
| } | |||||
| } | |||||
| @@ -22,12 +22,33 @@ public class Project { | |||||
| /** | /** | ||||
| * | * | ||||
| */ | */ | ||||
| private Ant ant; | |||||
| //private Ant ant; | |||||
| /** | |||||
| * Base directory of this project. Usually this value is the directory | |||||
| * where the project file was found, but can be different. | |||||
| */ | |||||
| private File baseDir; | |||||
| /** | /** | ||||
| * | * | ||||
| */ | */ | ||||
| private PrintStream out; | |||||
| private String defaultTargetName; | |||||
| /** | |||||
| * Short description of the project. | |||||
| */ | |||||
| private String description; | |||||
| /** | |||||
| * Front end that this project communicates to. | |||||
| */ | |||||
| private FrontEnd frontEnd; | |||||
| /** | |||||
| * Properties of this project. | |||||
| */ | |||||
| private Properties properties = new Properties(); | |||||
| /** | /** | ||||
| * Parent project to this project, if one exists. | * Parent project to this project, if one exists. | ||||
| @@ -46,13 +67,18 @@ public class Project { | |||||
| * as the value. | * as the value. | ||||
| */ | */ | ||||
| private Hashtable targets = new Hashtable(); | private Hashtable targets = new Hashtable(); | ||||
| /** | |||||
| * TaskManager for this project. | |||||
| */ | |||||
| private TaskManager taskManager = new TaskManager(this); | |||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| // PUBLIC ACCESSOR METHODS | |||||
| // PUBLIC METHODS | |||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| /** | /** | ||||
| * | |||||
| * Adds a target to this project. | |||||
| */ | */ | ||||
| public void addTarget(Target target) { | public void addTarget(Target target) { | ||||
| // XXX check out for name, if null, reject! | // XXX check out for name, if null, reject! | ||||
| @@ -60,11 +86,33 @@ public class Project { | |||||
| } | } | ||||
| /** | /** | ||||
| * | |||||
| * Returns the base directory of this project. | |||||
| */ | |||||
| public File getBaseDir() { | |||||
| return baseDir; | |||||
| } | |||||
| /** | |||||
| * Returns the default target for this project, if there is one. Otherwise | |||||
| * it returns null. | |||||
| */ | */ | ||||
| public PrintStream getOutput() { | |||||
| // XXX check if null!!!!???? | |||||
| return out; | |||||
| public String getDefaultTargetName() { | |||||
| return defaultTargetName; | |||||
| } | |||||
| /** | |||||
| * Returns a short description of this project, if any. If not, returns | |||||
| * null. | |||||
| */ | |||||
| public String getDescription() { | |||||
| return description; | |||||
| } | |||||
| /** | |||||
| * Gets the front end that is running this project. | |||||
| */ | |||||
| public FrontEnd getFrontEnd() { | |||||
| return frontEnd; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -85,42 +133,140 @@ public class Project { | |||||
| } | } | ||||
| /** | /** | ||||
| * | |||||
| * Gets an exumeration of all the targets that are part of this project. | |||||
| */ | */ | ||||
| public Enumeration getTargets() { | public Enumeration getTargets() { | ||||
| return targets.elements(); | return targets.elements(); | ||||
| } | } | ||||
| /** | /** | ||||
| * | |||||
| * Gets the name of this project. | |||||
| */ | */ | ||||
| public String getName() { | public String getName() { | ||||
| return name; | return name; | ||||
| } | } | ||||
| /** | /** | ||||
| * | |||||
| * Returns the value of a property. Returns null if the property does | |||||
| * not exist. | |||||
| */ | */ | ||||
| public void setAnt(Ant ant) { | |||||
| this.ant = ant; | |||||
| public String getProperty(String propertyName) { | |||||
| return properties.getProperty(propertyName); | |||||
| } | } | ||||
| /** | /** | ||||
| * | * | ||||
| */ | */ | ||||
| public void setOutput(PrintStream out) { | |||||
| this.out = out; | |||||
| //public void setAnt(Ant ant) { | |||||
| // this.ant = ant; | |||||
| //} | |||||
| /** | |||||
| * Sets the base dir for this project. | |||||
| */ | |||||
| public void setBaseDir(File dir) { | |||||
| // XXX should check this to make sure it's a dir! | |||||
| baseDir = dir; | |||||
| } | } | ||||
| /** | /** | ||||
| * | |||||
| * Sets the default target for this project. | |||||
| */ | |||||
| public void setDefaultTargetName(String targetName) { | |||||
| defaultTargetName = targetName; | |||||
| } | |||||
| /** | |||||
| * Sets the description for this project. | |||||
| */ | |||||
| public void setDescription(String description) { | |||||
| this.description = description; | |||||
| } | |||||
| /** | |||||
| * Sets the front end for this project. | |||||
| */ | |||||
| public void setFrontEnd(FrontEnd frontEnd) { | |||||
| this.frontEnd = frontEnd; | |||||
| } | |||||
| /** | |||||
| * Sets the name of this project. | |||||
| */ | */ | ||||
| public void setName(String name) { | public void setName(String name) { | ||||
| this.name = name; | this.name = name; | ||||
| } | } | ||||
| /** | |||||
| * Sets a property on this project. If the property is already | |||||
| * set, this method will override it. | |||||
| */ | |||||
| public void setProperty(String propertyName, String propertyValue) { | |||||
| properties.put(propertyName, propertyValue); | |||||
| } | |||||
| /** | /** | ||||
| * | |||||
| * Starts a build of this project using the default target if one | |||||
| * is set. | |||||
| */ | |||||
| public void startBuild() throws AntException { | |||||
| // XXX need to do something if the default target isn't set.. | |||||
| // maybe look for target name 'default', then bail? | |||||
| startBuild(defaultTargetName); | |||||
| } | |||||
| /** | |||||
| * Starts a build of this project with the entry point at the given | |||||
| * target. | |||||
| */ | |||||
| public void startBuild(String targetName) throws AntException { | |||||
| // notify FrontEnd that we are starting a build on a project | |||||
| frontEnd.notifyProjectStart(this); | |||||
| Target target = getTarget(targetName); | |||||
| //TaskManager taskManager = ant.getTaskManager(); | |||||
| frontEnd.notifyTargetStart(target); | |||||
| // XXX don't forget to execute dependancies first! | |||||
| Enumeration enum = target.getTasks().elements(); | |||||
| while (enum.hasMoreElements()) { | |||||
| Task task = (Task)enum.nextElement(); | |||||
| frontEnd.notifyTaskStart(task); | |||||
| try { | |||||
| AbstractTask aTask = taskManager.getTaskInstance(task.getType()); | |||||
| aTask.setProject(this); | |||||
| aTask.setAttributes(task.getAttributes()); | |||||
| boolean b = aTask.execute(); | |||||
| if (!b) { | |||||
| String msg = "Task " + task.getType() + " failed"; | |||||
| AntException ae = new AntException(msg); | |||||
| throw ae; | |||||
| } | |||||
| } catch (Exception e) { | |||||
| AntException ae; | |||||
| if (!(e instanceof AntException)) { | |||||
| ae = new AntException(e); | |||||
| } else { | |||||
| ae = (AntException)e; | |||||
| } | |||||
| ae.setProject(this); | |||||
| ae.setTarget(target); | |||||
| ae.setTask(task); | |||||
| throw ae; | |||||
| } | |||||
| frontEnd.notifyTaskEnd(task); | |||||
| } | |||||
| // notify frontEnd that we are done | |||||
| frontEnd.notifyTargetEnd(target); | |||||
| frontEnd.notifyProjectEnd(this); | |||||
| } | |||||
| /** | |||||
| * Givens a string representation of this object. Useful for debugging. | |||||
| */ | */ | ||||
| public String toString() { | public String toString() { | ||||
| return "Project name=" + name; | return "Project name=" + name; | ||||
| @@ -5,6 +5,7 @@ | |||||
| package org.apache.ant; | package org.apache.ant; | ||||
| import java.io.*; | import java.io.*; | ||||
| import java.util.*; | |||||
| import javax.xml.parsers.*; | import javax.xml.parsers.*; | ||||
| import org.xml.sax.*; | import org.xml.sax.*; | ||||
| @@ -16,46 +17,86 @@ import org.xml.sax.*; | |||||
| * | * | ||||
| * @author James Duncan Davidson (duncan@apache.org) | * @author James Duncan Davidson (duncan@apache.org) | ||||
| */ | */ | ||||
| class ProjectBuilder { | |||||
| public class ProjectBuilder { | |||||
| // ----------------------------------------------------------------- | |||||
| // PRIVATE MEMBERS | |||||
| // ----------------------------------------------------------------- | |||||
| /** | |||||
| * | |||||
| */ | |||||
| //private Ant ant; | |||||
| /** | |||||
| * | |||||
| */ | |||||
| private FrontEnd frontEnd; | |||||
| /** | |||||
| * | |||||
| */ | |||||
| private SAXParserFactory parserFactory; | private SAXParserFactory parserFactory; | ||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| // CONSTRUCTORS | // CONSTRUCTORS | ||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| ProjectBuilder() { | |||||
| /** | |||||
| * Creates a new project builder that will build projects for the given | |||||
| * Ant. | |||||
| */ | |||||
| public ProjectBuilder(FrontEnd frontEnd) { | |||||
| this.frontEnd = frontEnd; | |||||
| parserFactory = SAXParserFactory.newInstance(); | parserFactory = SAXParserFactory.newInstance(); | ||||
| parserFactory.setValidating(false); | parserFactory.setValidating(false); | ||||
| } | } | ||||
| Project buildFromFile(File file) throws AntException { | |||||
| /** | |||||
| * Builds a project from the given file. | |||||
| */ | |||||
| public Project buildFromFile(File file) throws AntException { | |||||
| try { | try { | ||||
| SAXParser parser = parserFactory.newSAXParser(); | SAXParser parser = parserFactory.newSAXParser(); | ||||
| BuilderHandlerBase bhb = new BuilderHandlerBase(); | BuilderHandlerBase bhb = new BuilderHandlerBase(); | ||||
| bhb.setProjectFileLocation(file); | |||||
| parser.parse(file, bhb); | parser.parse(file, bhb); | ||||
| return bhb.getProject(); | |||||
| Project project = bhb.getProject(); | |||||
| project.setFrontEnd(frontEnd); | |||||
| return project; | |||||
| } catch (ParserConfigurationException pce) { | } catch (ParserConfigurationException pce) { | ||||
| throw new AntException(pce.getMessage()); | |||||
| throw new AntException(pce); | |||||
| } catch (SAXException se) { | } catch (SAXException se) { | ||||
| System.out.println(se); | |||||
| System.out.println(se.getMessage()); | |||||
| throw new AntException(se.getMessage()); | |||||
| 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) { | } catch (IOException ioe) { | ||||
| throw new AntException(ioe.getMessage()); | |||||
| throw new AntException(ioe); | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Inner class that implements the needed SAX methods to get all the | |||||
| * data needed out of a build file. | |||||
| */ | |||||
| class BuilderHandlerBase extends HandlerBase { | class BuilderHandlerBase extends HandlerBase { | ||||
| private static final int STATE_START = 0; | private static final int STATE_START = 0; | ||||
| private static final int STATE_PROJECT = 1; | private static final int STATE_PROJECT = 1; | ||||
| private static final int STATE_TARGET = 2; | private static final int STATE_TARGET = 2; | ||||
| private static final int STATE_TASK = 3; | 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 static final int STATE_FINISHED = 99; | ||||
| private int state = STATE_START; | private int state = STATE_START; | ||||
| private Vector tagCharDataStack = new Vector(); | |||||
| private Target currentTarget; | private Target currentTarget; | ||||
| private Task currentTask; | private Task currentTask; | ||||
| @@ -65,42 +106,98 @@ class ProjectBuilder { | |||||
| return project; | return project; | ||||
| } | } | ||||
| void setProjectFileLocation(File file) { | |||||
| project.setBaseDir(file.getParentFile()); | |||||
| } | |||||
| public void startElement(String name, AttributeList atts) throws SAXException { | public void startElement(String name, AttributeList atts) throws SAXException { | ||||
| //System.out.println("element: " + name); | |||||
| StringBuffer tagCharData = new StringBuffer(); | |||||
| tagCharDataStack.insertElementAt(tagCharData, 0); | |||||
| switch (state) { | switch (state) { | ||||
| case STATE_START: | case STATE_START: | ||||
| if (name.equals("project")) { | if (name.equals("project")) { | ||||
| state = STATE_PROJECT; | state = STATE_PROJECT; | ||||
| String projectName = atts.getValue("name"); | String projectName = atts.getValue("name"); | ||||
| if (projectName == null) { | |||||
| System.out.println("Projects *must* have names"); | |||||
| // XXX exception out | |||||
| 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)); | |||||
| } | } | ||||
| project.setName(projectName); | |||||
| } else { | } else { | ||||
| System.out.println("Expecting project, got: " + name); | |||||
| // XXX exception out | |||||
| String msg = "Project file doesn't contain a project element as " + | |||||
| "its root node"; | |||||
| AntException ae = new AntException(msg); | |||||
| throw new SAXException(ae); | |||||
| } | } | ||||
| break; | break; | ||||
| case STATE_PROJECT: | case STATE_PROJECT: | ||||
| if (name.equals("target")) { | |||||
| // 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; | state = STATE_TARGET; | ||||
| String targetName = atts.getValue("name"); | String targetName = atts.getValue("name"); | ||||
| if (targetName == null) { | |||||
| System.out.println("Targets *must* have names"); | |||||
| // XXX exception out | |||||
| 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()); | |||||
| } | |||||
| } | } | ||||
| currentTarget = new Target(targetName); | |||||
| project.addTarget(currentTarget); | |||||
| // XXX add dependency checks | // XXX add dependency checks | ||||
| } else { | } else { | ||||
| System.out.println("Expecting target, got: " + name); | System.out.println("Expecting target, got: " + name); | ||||
| // XXX exception out | // XXX exception out | ||||
| } | } | ||||
| break; | break; | ||||
| case STATE_TARGET: | case STATE_TARGET: | ||||
| // Valid tags inside target: task | |||||
| state = STATE_TASK; | state = STATE_TASK; | ||||
| //System.out.println("Getting task: " + name + " for target " + | //System.out.println("Getting task: " + name + " for target " + | ||||
| // currentTarget); | // currentTarget); | ||||
| @@ -114,6 +211,16 @@ class ProjectBuilder { | |||||
| currentTask.addAttribute(atName, atValue); | currentTask.addAttribute(atName, atValue); | ||||
| } | } | ||||
| break; | 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: | default: | ||||
| System.out.println("I'm not sure, but we're off base here: " + name); | System.out.println("I'm not sure, but we're off base here: " + name); | ||||
| // XXX exception out | // XXX exception out | ||||
| @@ -121,14 +228,21 @@ class ProjectBuilder { | |||||
| } | } | ||||
| public void characters(char ch[], int start, int length) throws SAXException { | 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 { | public void endElement(String name) throws SAXException { | ||||
| // System.out.println("end: " + name); | |||||
| StringBuffer elementData = (StringBuffer)tagCharDataStack.elementAt(0); | |||||
| tagCharDataStack.removeElementAt(0); | |||||
| switch (state) { | switch (state) { | ||||
| case STATE_TASK: | case STATE_TASK: | ||||
| state = STATE_TARGET; | state = STATE_TARGET; | ||||
| break; | break; | ||||
| case STATE_TARGET: | case STATE_TARGET: | ||||
| if (name.equals("target")) { | if (name.equals("target")) { | ||||
| state = STATE_PROJECT; | state = STATE_PROJECT; | ||||
| @@ -137,6 +251,27 @@ class ProjectBuilder { | |||||
| // XXX exception out. | // XXX exception out. | ||||
| } | } | ||||
| break; | 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: | case STATE_PROJECT: | ||||
| if (name.equals("project")) { | if (name.equals("project")) { | ||||
| state = STATE_FINISHED; | state = STATE_FINISHED; | ||||
| @@ -145,6 +280,7 @@ class ProjectBuilder { | |||||
| // XXX exception out; | // XXX exception out; | ||||
| } | } | ||||
| break; | break; | ||||
| default: | default: | ||||
| System.out.println("I'm not sure what we are ending here: " + name); | System.out.println("I'm not sure what we are ending here: " + name); | ||||
| // XXX exception out; | // XXX exception out; | ||||
| @@ -22,6 +22,12 @@ public class Target { | |||||
| */ | */ | ||||
| private String name; | private String name; | ||||
| /** | |||||
| * Vector containing the names of the targets that this target | |||||
| * depends on. | |||||
| */ | |||||
| private Vector dependsList = new Vector(); | |||||
| /** | /** | ||||
| * Vector containing the tasks that are part of this target. | * Vector containing the tasks that are part of this target. | ||||
| */ | */ | ||||
| @@ -42,6 +48,13 @@ public class Target { | |||||
| // PUBLIC ACCESSOR METHODS | // PUBLIC ACCESSOR METHODS | ||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| /** | |||||
| * Adds a dependancy to this task. | |||||
| */ | |||||
| public void addDependancy(String targetName) { | |||||
| dependsList.addElement(targetName); | |||||
| } | |||||
| /** | /** | ||||
| * | * | ||||
| */ | */ | ||||
| @@ -23,6 +23,16 @@ class TaskManager { | |||||
| // PRIVATE DATA MEMBERS | // PRIVATE DATA MEMBERS | ||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| /** | |||||
| * Reference to Ant that holds this TaskManager | |||||
| */ | |||||
| //private Ant ant; | |||||
| /** | |||||
| * Project to which this task manger belongs. | |||||
| */ | |||||
| private Project project; | |||||
| /** | /** | ||||
| * Data structure where all the Class definition for all known tasks are | * Data structure where all the Class definition for all known tasks are | ||||
| * held. | * held. | ||||
| @@ -41,7 +51,8 @@ class TaskManager { | |||||
| /** | /** | ||||
| * Creates a new TaskManager. | * Creates a new TaskManager. | ||||
| */ | */ | ||||
| TaskManager() { | |||||
| TaskManager(Project project) { | |||||
| this.project = project; | |||||
| } | } | ||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| @@ -59,16 +70,15 @@ class TaskManager { | |||||
| /** | /** | ||||
| * | * | ||||
| */ | */ | ||||
| AbstractTask getTaskInstance(String taskName) { | |||||
| AbstractTask getTaskInstance(String taskName) throws AntException { | |||||
| Class clazz = (Class)taskClasses.get(taskName); | Class clazz = (Class)taskClasses.get(taskName); | ||||
| try { | try { | ||||
| return (AbstractTask)clazz.newInstance(); | return (AbstractTask)clazz.newInstance(); | ||||
| } catch (Exception e) { | |||||
| System.out.println("Can't instantiate task: " + taskName); | |||||
| System.out.println(e); | |||||
| // XXX error out and stop | |||||
| } catch (Exception e) { | |||||
| String msg = "Can't instantiate task: " + taskName; | |||||
| AntException ae = new AntException(msg, e); | |||||
| throw ae; | |||||
| } | } | ||||
| return null; | |||||
| } | } | ||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| @@ -94,7 +104,8 @@ class TaskManager { | |||||
| * Processes a directory to get class defintions from it | * Processes a directory to get class defintions from it | ||||
| */ | */ | ||||
| private void processDir(File dir) { | private void processDir(File dir) { | ||||
| System.out.println("Scanning " + dir + " for tasks"); | |||||
| project.getFrontEnd().writeMessage("Scanning " + dir + " for tasks", | |||||
| FrontEnd.MSG_LEVEL_LOW); | |||||
| File file = new File(dir, "taskdef.properties"); | File file = new File(dir, "taskdef.properties"); | ||||
| if (file.exists()) { | if (file.exists()) { | ||||
| try { | try { | ||||
| @@ -110,7 +121,8 @@ class TaskManager { | |||||
| URLClassLoader loader = new URLClassLoader(new URL[] {dir.toURL()}); | URLClassLoader loader = new URLClassLoader(new URL[] {dir.toURL()}); | ||||
| try { | try { | ||||
| Class clazz = loader.loadClass(taskClass); | Class clazz = loader.loadClass(taskClass); | ||||
| System.out.println("Got task: " + taskName + " " + clazz); | |||||
| project.getFrontEnd().writeMessage("Got Task: " + taskName + | |||||
| clazz, FrontEnd.MSG_LEVEL_LOW); | |||||
| taskClasses.put(taskName, clazz); | taskClasses.put(taskName, clazz); | ||||
| } catch (ClassNotFoundException cnfe) { | } catch (ClassNotFoundException cnfe) { | ||||
| System.out.println("Couldn't load task: " + taskName); | System.out.println("Couldn't load task: " + taskName); | ||||
| @@ -130,7 +142,8 @@ class TaskManager { | |||||
| * Processes a jar file to get class definitions from it | * Processes a jar file to get class definitions from it | ||||
| */ | */ | ||||
| private void processJar(File file) { | private void processJar(File file) { | ||||
| System.out.println("Scanning " + file + " for tasks"); | |||||
| project.getFrontEnd().writeMessage("Scanning " + file + " for tasks", | |||||
| FrontEnd.MSG_LEVEL_LOW); | |||||
| try { | try { | ||||
| ZipFile zipFile = new ZipFile(file); | ZipFile zipFile = new ZipFile(file); | ||||
| ZipEntry zipEntry = zipFile.getEntry("taskdef.properties"); | ZipEntry zipEntry = zipFile.getEntry("taskdef.properties"); | ||||
| @@ -147,7 +160,8 @@ class TaskManager { | |||||
| URLClassLoader loader = new URLClassLoader(new URL[] {file.toURL()}); | URLClassLoader loader = new URLClassLoader(new URL[] {file.toURL()}); | ||||
| try { | try { | ||||
| Class clazz = loader.loadClass(taskClass); | Class clazz = loader.loadClass(taskClass); | ||||
| System.out.println("Got Task: " + taskName + " " + clazz); | |||||
| project.getFrontEnd().writeMessage("Got Task: " + taskName + | |||||
| clazz, FrontEnd.MSG_LEVEL_LOW); | |||||
| taskClasses.put(taskName, clazz); | taskClasses.put(taskName, clazz); | ||||
| } catch (ClassNotFoundException cnfe) { | } catch (ClassNotFoundException cnfe) { | ||||
| System.out.println("Couldn't load task: " + taskName); | System.out.println("Couldn't load task: " + taskName); | ||||
| @@ -14,7 +14,7 @@ import org.apache.ant.*; | |||||
| * | * | ||||
| * @author James Duncan Davidson (duncan@apache.org) | * @author James Duncan Davidson (duncan@apache.org) | ||||
| */ | */ | ||||
| public class CLIFrontEnd extends AntFrontEnd { | |||||
| public class CLIFrontEnd extends FrontEnd { | |||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| // PRIVATE MEMBERS | // PRIVATE MEMBERS | ||||
| @@ -23,22 +23,28 @@ public class CLIFrontEnd extends AntFrontEnd { | |||||
| /** | /** | ||||
| * | * | ||||
| */ | */ | ||||
| private Ant ant; | |||||
| //private Ant ant; | |||||
| /** | /** | ||||
| * | * | ||||
| */ | */ | ||||
| private int msgLevel = MSG_LEVEL_MED; | |||||
| private String[] args; | |||||
| /** | |||||
| * | |||||
| */ | |||||
| private int msgLevelFilter = MSG_LEVEL_MED; | |||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| // CONSTRUCTORS | // CONSTRUCTORS | ||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| /** | /** | ||||
| * | |||||
| * Creates a new CLIFrontEnd that can drive an Ant build from the Command | |||||
| * Line. | |||||
| */ | */ | ||||
| public CLIFrontEnd() { | public CLIFrontEnd() { | ||||
| ant = new Ant(this); | |||||
| //ant = new Ant(this); | |||||
| } | } | ||||
| // ----------------------------------------------------------------- | // ----------------------------------------------------------------- | ||||
| @@ -98,74 +104,84 @@ public class CLIFrontEnd extends AntFrontEnd { | |||||
| writeMessage("Task End: " + task.getType(), MSG_LEVEL_LOW); | writeMessage("Task End: " + task.getType(), MSG_LEVEL_LOW); | ||||
| } | } | ||||
| /** | |||||
| * Prints help to System.out | |||||
| */ | |||||
| private void printHelp() { | |||||
| String ls = System.getProperty("line.separator"); | |||||
| String msg = "Usage: ant [args] [target]" + ls + | |||||
| " Arguments can be any of the following:" + ls + | |||||
| " -help" + ls + | |||||
| " -taskpath [path]" + ls + | |||||
| " -buildfile [file]" +ls + | |||||
| " -verbose" + ls + | |||||
| " -quiet" + ls + ls + | |||||
| " Note that if no buildfile argument is given, Ant will"+ls+ | |||||
| " try to find one in the current directory. If there are"+ls+ | |||||
| " two or more buildfiles in the current directory, it" +ls+ | |||||
| " will bail."; | |||||
| writeMessage(msg); | |||||
| } | |||||
| /** | /** | ||||
| * | * | ||||
| */ | */ | ||||
| public void run(String[] args) { | public void run(String[] args) { | ||||
| this.args = args; | |||||
| String target = ""; | String target = ""; | ||||
| File buildFile = null; | |||||
| writeMessage("Ant(Eater) -- Proposed Ant 2.0"); | writeMessage("Ant(Eater) -- Proposed Ant 2.0"); | ||||
| // flip through args and set things accordingly | |||||
| for (int i = 0; i < args.length; i++) { | |||||
| String arg = args[i]; | |||||
| // scan through -- all -aaa args come first. | |||||
| if (arg.startsWith("-")) { | |||||
| if (arg.equals("-help")) { | |||||
| printHelp(); | |||||
| return; | |||||
| } else if (arg.equals("-taskpath")) { | |||||
| // XXX | |||||
| // need to seperate on pathsep, but not today | |||||
| ant.addTaskPathNode(new File(args[++i])); | |||||
| } else if (arg.equals("-buildfile")) { | |||||
| // XXX | |||||
| // need to check file to make sure it exists! | |||||
| try { | |||||
| ant.setBuildfile(new File(args[++i])); | |||||
| } catch (AntException ae) { | |||||
| writeMessage("ICK: " + ae); | |||||
| writeMessage(ae.getMessage()); | |||||
| return; | |||||
| } | |||||
| } | |||||
| // process through the args set | |||||
| if (isArg("help")) { | |||||
| printHelp(); | |||||
| return; | |||||
| } | |||||
| if (isArg("quiet")) { | |||||
| msgLevelFilter = MSG_LEVEL_HIGH; | |||||
| } | |||||
| if (isArg("verbose")) { | |||||
| msgLevelFilter = MSG_LEVEL_LOW; | |||||
| } | |||||
| String argTaskpath = getArgValue("taskpath"); | |||||
| if (argTaskpath != null) { | |||||
| if (argTaskpath.equals("")) { | |||||
| writeMessage("Must give a value for -taskpath"); | |||||
| return; | |||||
| } else { | } else { | ||||
| target = arg; | |||||
| // XXX need to separate on path seps so that real paths can be taken | |||||
| // ant.addTaskPathNode(new File(argTaskpath)); | |||||
| } | } | ||||
| } | } | ||||
| String argBuildfile = getArgValue("buildfile"); | |||||
| if (argBuildfile != null) { | |||||
| if (argBuildfile.equals("")) { | |||||
| writeMessage("Must give a value for -buildfile"); | |||||
| return; | |||||
| } else { | |||||
| //try { | |||||
| buildFile = new File(argBuildfile); | |||||
| //ant.setBuildfile(new File(argBuildfile)); | |||||
| //} catch (AntException ae) { | |||||
| // writeMessage("Can't set buildfile"); | |||||
| // writeMessage(ae.toString()); | |||||
| // return; | |||||
| //} | |||||
| } | |||||
| } | |||||
| target = getTargetArg(); | |||||
| // XXX do something if we dont' have a buildfile set! | // XXX do something if we dont' have a buildfile set! | ||||
| // XXX really should check to make sure that the target is set to something | // XXX really should check to make sure that the target is set to something | ||||
| // set our listeners on the project | |||||
| Project project = ant.getProject(); | |||||
| project.setOutput(System.out); | |||||
| // like get the default... | |||||
| try { | try { | ||||
| ant.buildTarget(target); | |||||
| } catch (AntException ae) { | |||||
| writeMessage("Problem while building: " + ae); | |||||
| ProjectBuilder projectBuilder = new ProjectBuilder(this); | |||||
| Project project = projectBuilder.buildFromFile(buildFile); | |||||
| //Project project = ant.getProject(); | |||||
| // XXX | |||||
| // get taskmanager from project and set taskpath nodes on it! | |||||
| project.setFrontEnd(this); | |||||
| project.startBuild(target); | |||||
| } catch (AntException ae) { | |||||
| writeMessage("Build Stopped"); | |||||
| writeMessage(" Project: " + ae.getProject().getName()); | |||||
| writeMessage(" Target: " + ae.getTarget().getName()); | |||||
| writeMessage(" Task Type: " + ae.getTask().getType()); | |||||
| writeMessage("Details Follow"); | |||||
| writeMessage(""); | |||||
| writeMessage(ae.getMessage()); | writeMessage(ae.getMessage()); | ||||
| ae.printStackTrace(System.out); | |||||
| } | } | ||||
| } | } | ||||
| @@ -173,10 +189,100 @@ public class CLIFrontEnd extends AntFrontEnd { | |||||
| * Writes a message to the front end. | * Writes a message to the front end. | ||||
| */ | */ | ||||
| public void writeMessage(String message, int level) { | public void writeMessage(String message, int level) { | ||||
| if (level >= msgLevel) { | |||||
| if (level >= msgLevelFilter) { | |||||
| System.out.println(message); | System.out.println(message); | ||||
| } | } | ||||
| } | } | ||||
| // ----------------------------------------------------------------- | |||||
| // PRIVATE METHODS | |||||
| // ----------------------------------------------------------------- | |||||
| /** | |||||
| * Returns the value for a given argument name, null if the argument | |||||
| * name isn't in the argument set, or "" if the argument doesn't have | |||||
| * a value. | |||||
| */ | |||||
| private String getArgValue(String argName) { | |||||
| for (int i = 0; i < args.length; i++) { | |||||
| if (args[i].equals("-" + argName)) { | |||||
| if (i != args.length - 1) { | |||||
| return args[i + 1]; | |||||
| } else { | |||||
| return ""; | |||||
| } | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| /** | |||||
| * Returns the target that was requested to be built, if any. If no | |||||
| * target is determined, returns null. | |||||
| */ | |||||
| public String getTargetArg() { | |||||
| String possibleTarget = getArgValue("target"); | |||||
| if (possibleTarget != null) { | |||||
| if (possibleTarget.equals("")) { | |||||
| writeMessage("Must give a value for -target"); | |||||
| } else { | |||||
| return possibleTarget; | |||||
| } | |||||
| } | |||||
| possibleTarget = args[args.length - 1]; | |||||
| if (possibleTarget.startsWith("-")) { | |||||
| return null; | |||||
| } | |||||
| if (args[args.length - 2].startsWith("-")) { | |||||
| // our possible target might be an arg value instead of a target | |||||
| // XXX ugh -- there has to be a better way here. We need to hold | |||||
| // a list of all args that don't have values somewhere. | |||||
| if (args[args.length - 2].equals("-help") || | |||||
| args[args.length - 2].equals("-verbose") || | |||||
| args[args.length - 2].equals("-quiet")) { | |||||
| // we're ok, the arg before the possible target doesn't have a value | |||||
| return possibleTarget; | |||||
| } else { | |||||
| return null; | |||||
| } | |||||
| } else { | |||||
| return possibleTarget; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Indicates whether or not a given argument name exists in the argument | |||||
| * set. | |||||
| */ | |||||
| private boolean isArg(String argName) { | |||||
| for (int i = 0; i < args.length; i++) { | |||||
| if (args[i].equals("-" + argName)) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| /** | |||||
| * Prints help to System.out | |||||
| */ | |||||
| private void printHelp() { | |||||
| // XXX resource bundle this. | |||||
| String ls = System.getProperty("line.separator"); | |||||
| String msg = "Usage: ant [args] [target]" + ls + | |||||
| " Arguments can be any of the following:" + ls + | |||||
| " -help" + ls + | |||||
| " -taskpath [path]" + ls + | |||||
| " -buildfile [file]" +ls + | |||||
| " -verbose" + ls + | |||||
| " -quiet" + ls + ls + | |||||
| " Note that if no buildfile argument is given, Ant will"+ls+ | |||||
| " try to find one in the current directory. If there are"+ls+ | |||||
| " two or more buildfiles in the current directory, it" +ls+ | |||||
| " will bail."; | |||||
| writeMessage(msg); | |||||
| } | |||||
| } | } | ||||