| /* |
| * The Apache Software License, Version 1.1 |
| * |
| * Copyright (c) 2001 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", "Ant", 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 apache@apache.org. |
| * |
| * 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.ant.core.xml; |
| |
| import java.io.*; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.*; |
| import javax.xml.parsers.*; |
| import org.apache.ant.core.model.*; |
| import org.apache.ant.core.support.*; |
| import org.xml.sax.*; |
| import org.xml.sax.helpers.DefaultHandler; |
| |
| /** |
| * Parses a project from an XML source using a SAX Parser. |
| * |
| * @author <a href="mailto:conor@apache.org">Conor MacNeill</a> |
| */ |
| public class XMLProjectParser { |
| private Stack recursionCheck = new Stack(); |
| |
| /** |
| * The factory used to create SAX parsers. |
| */ |
| private SAXParserFactory parserFactory; |
| |
| static private Location getLocation(Locator locator) { |
| return new Location(locator.getSystemId(), locator.getLineNumber(), |
| locator.getColumnNumber()); |
| } |
| |
| /** |
| * Parse a build file form the given URL. |
| * |
| * @param buildSource the URL from where the build source may be read. |
| * |
| * @throws SAXParseException if there is a problem parsing the build file. |
| */ |
| public Project parseBuildFile(URL buildSource) |
| throws ConfigException { |
| try { |
| parserFactory = SAXParserFactory.newInstance(); |
| SAXParser saxParser = parserFactory.newSAXParser(); |
| XMLReader xmlReader = saxParser.getXMLReader(); |
| |
| recursionCheck.push(buildSource); |
| ProjectRootHandler projectRootHandler |
| = new ProjectRootHandler(buildSource, xmlReader); |
| saxParser.parse(buildSource.toString(), projectRootHandler); |
| return projectRootHandler.getProject(); |
| } |
| catch (SAXParseException e) { |
| throw new ConfigException(e.getMessage(), e, |
| new Location(buildSource.toString(), |
| e.getLineNumber(), e.getColumnNumber())); |
| } |
| catch (NoProjectReadException e) { |
| throw new ConfigException("No project defined in build source", e, |
| new Location(buildSource.toString())); |
| } |
| catch (ParserConfigurationException e) { |
| throw new ConfigException("Unable to parse project: " + e.getMessage(), e, |
| new Location(buildSource.toString())); |
| } |
| catch (SAXException e) { |
| throw new ConfigException("Unable to parse project: " + e.getMessage(), e, |
| new Location(buildSource.toString())); |
| } |
| catch (IOException e) { |
| throw new ConfigException("Unable to parse project: " + e.getMessage(), e, |
| new Location(buildSource.toString())); |
| } |
| } |
| |
| /** |
| * The root handler handles the start of parsing. This element looks for the |
| * root element which must be a project element. It then delegates handling of the |
| * project element to a project handler from which it extracts the parsed project. |
| */ |
| private class ProjectRootHandler extends RootHandler { |
| /** |
| * The project handler created to parse the project element. |
| */ |
| ProjectHandler projectHandler; |
| |
| /** |
| * Create a Root Handler. |
| * |
| * @param buildSource the URL containing the build definition |
| * @param reader the XML parser. |
| */ |
| public ProjectRootHandler(URL buildSource, XMLReader reader) { |
| super(buildSource, reader); |
| } |
| |
| /** |
| * Start a new element in the root. This must be a project element |
| * All other elements are invalid. |
| * |
| * @param uri The Namespace URI. |
| * @param localName The local name (without prefix). |
| * @param qualifiedName The qualified name (with prefix) |
| * @param attributes The attributes attached to the element. |
| * |
| * @throws SAXParseException if there is a parsing problem. |
| */ |
| public void startElement(String uri, String localName, String qualifiedName, |
| Attributes attributes) throws SAXParseException { |
| if (qualifiedName.equals("project")) { |
| projectHandler = new ProjectHandler(getXMLReader(), this, |
| getLocator(), attributes, getSourceURL()); |
| } else { |
| throw new SAXParseException("Build file should start with a <project> element not <" + |
| qualifiedName + ">", getLocator()); |
| } |
| } |
| |
| /** |
| * Get the project that has been parsed from the element |
| * |
| * @return the project that has been parsed from the build osurce |
| * |
| * @throws NoProjectReadException thrown if no project was read in. |
| */ |
| public Project getProject() throws NoProjectReadException { |
| if (projectHandler == null) { |
| throw new NoProjectReadException(); |
| } |
| return projectHandler.getProject(); |
| } |
| } |
| |
| /** |
| * Root Handler for include elements. |
| * |
| * Includes must contain either a project (which is being extended) or |
| * a fragment element which contains the fragment to be included. |
| */ |
| private class IncludeRootHandler extends RootHandler { |
| /** |
| * The project into which the fragment is to be included. |
| */ |
| private Project project; |
| |
| /** |
| * Create an Include Root Handler. |
| * |
| * @param buildSource the URL containing the fragment definition |
| * @param reader the XML parser. |
| * @param project the project into which the fragment's elements will be included. |
| */ |
| public IncludeRootHandler(URL buildSource, XMLReader reader, Project project) { |
| super(buildSource, reader); |
| this.project = project; |
| } |
| |
| /** |
| * Start a new element in the include root. This must be a project element |
| * or a fragment element. All other elements are invalid. |
| * |
| * @param uri The Namespace URI. |
| * @param localName The local name (without prefix). |
| * @param qualifiedName The qualified name (with prefix) |
| * @param attributes The attributes attached to the element. |
| * |
| * @throws SAXParseException if there is a parsing problem. |
| */ |
| public void startElement(String uri, String localName, String qualifiedName, |
| Attributes attributes) throws SAXParseException { |
| if (qualifiedName.equals("project") || |
| qualifiedName.equals("fragment")) { |
| // if it is a fragment, it must have no attributes |
| // any project attributes are ignored |
| if (qualifiedName.equals("fragment") && attributes.getLength() != 0) { |
| throw new SAXParseException("<fragment> element may not have any attributes", |
| getLocator()); |
| } |
| new ProjectHandler(getXMLReader(), this, getLocator(), |
| getSourceURL(), project); |
| } else { |
| throw new SAXParseException("An included file should contain either a " + |
| "<project> or <fragment> element and not a <" + |
| qualifiedName + "> element", getLocator()); |
| } |
| } |
| } |
| |
| /** |
| * Element to parse the project element. |
| * |
| * The project handler creates a number of different handlers to which it |
| * delegates processing of child elements. |
| */ |
| private class ProjectHandler extends ElementHandler { |
| /** |
| * The project being parsed. |
| */ |
| private Project project; |
| |
| /** |
| * The sourceURL for the current content being added to the project. |
| */ |
| private URL sourceURL; |
| |
| /** |
| * Create a ProjectHandler to read in a complete project. |
| * |
| * @param xmlReader the XML parser being used to parse the project element. |
| * @param parent the parent element handler. |
| * @param locator the SAX locator object used to associate elements with source |
| * locations. |
| * @param attributes the project element's attributes. |
| * @param projectSource the URL from which the XML source is being parsed. |
| */ |
| public ProjectHandler(XMLReader xmlReader, ContentHandler parent, |
| Locator locator, Attributes attributes, URL projectSource) |
| throws SAXParseException { |
| |
| super(xmlReader, parent, locator); |
| this.sourceURL = projectSource; |
| project = new Project(projectSource, getLocation(locator)); |
| |
| String base = null; |
| String defaultTarget = null; |
| String projectName = null; |
| |
| Map aspects = new HashMap(); |
| for (int i = 0; i < attributes.getLength(); ++i) { |
| String attributeName = attributes.getQName(i); |
| String attributeValue = attributes.getValue(i); |
| if (attributeName.equals("base")) { |
| base = attributeValue; |
| } |
| else if (attributeName.equals("default")) { |
| defaultTarget = attributeValue; |
| } |
| else if (attributeName.equals("name")) { |
| projectName = attributeValue; |
| } |
| else if (attributeName.indexOf(":") != -1) { |
| // potential aspect attribute |
| aspects.put(attributeName, attributeValue); |
| } |
| else { |
| throw new SAXParseException("The attribute '" + attributeName + "' is not " + |
| "supported by the <project> element", getLocator()); |
| } |
| } |
| |
| project.setDefaultTarget(defaultTarget); |
| project.setBase(base); |
| project.setName(projectName); |
| project.setAspects(aspects); |
| } |
| |
| /** |
| * Create a Project handler for an included fragment. The elements |
| * from the fragment are added to the given project. |
| * |
| * @param xmlReader the XML parser being used to parse the project element. |
| * @param parent the parent element handler. |
| * @param locator the SAX locator object used to associate elements with source |
| * locations. |
| * @param includeSource the URL from which the XML source is being included. |
| * @param project the project to which the included fragments elements are added. |
| */ |
| public ProjectHandler(XMLReader xmlReader, ContentHandler parent, |
| Locator locator, URL includeSource, Project project) { |
| super(xmlReader, parent, locator); |
| this.sourceURL = includeSource; |
| this.project = project; |
| } |
| |
| /** |
| * Start a new element in the project. Project currently handle the |
| * following elements |
| * <ul> |
| * <li>import</li> |
| * <li>include</li> |
| * <li>target</li> |
| * </ul> |
| * |
| * Everything else is treated as a task. |
| * |
| * @param uri The Namespace URI. |
| * @param localName The local name (without prefix). |
| * @param qualifiedName The qualified name (with prefix) |
| * @param attributes The attributes attached to the element. |
| * |
| * @throws SAXParseException if there is a parsing problem. |
| */ |
| public void startElement(String uri, String localName, String qualifiedName, |
| Attributes attributes) throws SAXParseException { |
| if (qualifiedName.equals("import")) { |
| ImportHandler importHandler |
| = new ImportHandler(getXMLReader(), this, getLocator(), |
| attributes, sourceURL); |
| try { |
| project.importProject(importHandler.getImportName(), |
| importHandler.getImportedProject()); |
| } |
| catch (ProjectModelException e) { |
| throw new SAXParseException(e.getMessage(), getLocator(), e); |
| } |
| } |
| else if (qualifiedName.equals("include")) { |
| IncludeHandler includeHandler |
| = new IncludeHandler(getXMLReader(), this, getLocator(), |
| attributes, sourceURL, project); |
| } |
| else if (qualifiedName.equals("target")) { |
| TargetHandler targetHandler |
| = new TargetHandler(getXMLReader(), this, getLocator(), attributes); |
| try { |
| project.addTarget(targetHandler.getTarget()); |
| } |
| catch (ProjectModelException e) { |
| throw new SAXParseException(e.getMessage(), getLocator(), e); |
| } |
| } |
| else { |
| // everything else is a task |
| TaskElementHandler taskElementHandler |
| = new TaskElementHandler(getXMLReader(), this, getLocator(), |
| attributes, qualifiedName); |
| project.addTask(taskElementHandler.getTaskElement()); |
| } |
| } |
| |
| /** |
| * Get the project that has been parsed from the XML source |
| * |
| * @return the project model of the parsed project. |
| */ |
| public Project getProject() { |
| return project; |
| } |
| } |
| |
| /** |
| * The import handler handles the importing of one project into another. |
| * |
| * The project to be imported is parsed with a new parser and then added to the |
| * current project under the given import name |
| */ |
| private class ImportHandler extends ElementHandler { |
| /** |
| * The attribute used to name the import. |
| */ |
| static public final String IMPORT_NAME_ATTR = "name"; |
| |
| /** |
| * The attribute name used to locate the project to be imported. |
| */ |
| static public final String IMPORT_SYSTEMID_ATTR = "project"; |
| |
| /** |
| * The project that has been imported. |
| */ |
| private Project importedProject; |
| |
| /** |
| * The name under which the project is being imported. |
| */ |
| private String importName; |
| |
| /** |
| * The systemId (URL) where the project is to be imported from. |
| */ |
| private String projectSystemId; |
| |
| /** |
| * Create an import handler to import a project. |
| * |
| * @param xmlReader the XML parser being used to parse the import element. |
| * @param parent the parent element handler. |
| * @param locator the SAX locator object used to associate elements with source |
| * locations. |
| * @param attributes attributes of the import statement. |
| * @param importingSource the URL of the importing source. |
| */ |
| public ImportHandler(XMLReader xmlReader, ContentHandler parent, |
| Locator locator, Attributes attributes, URL importingSource) |
| throws SAXParseException { |
| super(xmlReader, parent, locator); |
| for (int i = 0; i < attributes.getLength(); ++i) { |
| String attributeName = attributes.getQName(i); |
| String attributeValue = attributes.getValue(i); |
| if (attributeName.equals(IMPORT_NAME_ATTR)) { |
| importName = attributeValue; |
| } |
| else if (attributeName.equals(IMPORT_SYSTEMID_ATTR)) { |
| projectSystemId = attributeValue; |
| } |
| else { |
| throw new SAXParseException("Attribute " + attributeName + |
| " is not allowed in an <import> element", getLocator()); |
| } |
| } |
| |
| if (importName == null) { |
| throw new SAXParseException("Attribute " + IMPORT_NAME_ATTR + |
| " is required in an <import> element", getLocator()); |
| } |
| |
| if (projectSystemId == null) { |
| throw new SAXParseException("Attribute " + IMPORT_SYSTEMID_ATTR + |
| " is required in an <import> element", getLocator()); |
| } |
| |
| // create a new parser to read this project relative to the |
| // project's URI |
| try { |
| URL importURL = new URL(importingSource, projectSystemId); |
| SAXParser importSAXParser = parserFactory.newSAXParser(); |
| XMLReader importXMLReader = importSAXParser.getXMLReader(); |
| |
| |
| if (recursionCheck.contains(importURL)) { |
| throw new SAXParseException("Circular import detected when importing '" + |
| importURL + "'", getLocator()); |
| } |
| recursionCheck.push(importURL); |
| ProjectRootHandler importRootHandler = new ProjectRootHandler(importURL, importXMLReader); |
| importSAXParser.parse(importURL.toString(), importRootHandler); |
| if (recursionCheck.pop() != importURL) { |
| throw new RuntimeException("Failure to pop expected element off recursion stack"); |
| } |
| importedProject = importRootHandler.getProject(); |
| } |
| catch (SAXParseException e) { |
| throw e; |
| } |
| catch (NoProjectReadException e) { |
| throw new SAXParseException("No project was imported from " + projectSystemId, |
| getLocator()); |
| } |
| catch (MalformedURLException e) { |
| throw new SAXParseException("Unable to import project from " + projectSystemId + |
| ": " + e.getMessage(), |
| getLocator()); |
| } |
| catch (ParserConfigurationException e) { |
| throw new SAXParseException("Unable to parse project imported from " + projectSystemId + |
| ": " + e.getMessage(), |
| getLocator()); |
| } |
| catch (SAXException e) { |
| throw new SAXParseException("Unable to parse project imported from " + projectSystemId + |
| ": " + e.getMessage(), |
| getLocator()); |
| } |
| catch (IOException e) { |
| throw new SAXParseException("Error reading project imported from " + projectSystemId + |
| ": " + e.getMessage(), |
| getLocator()); |
| } |
| } |
| |
| /** |
| * Import does not support nested elements. This method will always throw an |
| * exception |
| * @param uri The Namespace URI. |
| * @param localName The local name (without prefix). |
| * @param qualifiedName The qualified name (with prefix) |
| * @param attributes The attributes attached to the element. |
| * |
| * @throws SAXParseException always. |
| */ |
| public void startElement(String uri, String localName, String qualifiedName, |
| Attributes attributes) throws SAXParseException { |
| // everything is a task |
| throw new SAXParseException("<import> does not support nested elements", getLocator()); |
| } |
| |
| /** |
| * Get the project imported. |
| * |
| * @return an imported Project. |
| */ |
| public Project getImportedProject() { |
| return importedProject; |
| } |
| |
| /** |
| * Get the name under which the project is imported. |
| * |
| * @return the import name of the project |
| */ |
| public String getImportName() { |
| return importName; |
| } |
| } |
| |
| /** |
| * The include handler is used to read in included projects or |
| * fragments into a project. |
| */ |
| private class IncludeHandler extends ElementHandler { |
| /** |
| * The attribute name which identifies the fragment to be included |
| */ |
| static public final String INCLUDE_SYSTEMID_ATTR = "fragment"; |
| |
| /** |
| * The system id of the fragment to be included. |
| */ |
| private String includeSystemId; |
| |
| /** |
| * Create an IncludeHandler to include an element into the |
| * current project |
| * |
| * @param xmlReader the XML parser being used to parse the include element. |
| * @param parent the parent element handler. |
| * @param locator the SAX locator object used to associate elements with source |
| * locations. |
| * @param attributes attributes of the include statement. |
| * @param includingSource the URL of the including source. |
| * @param project the project into which the included elements are added. |
| */ |
| public IncludeHandler(XMLReader xmlReader, ContentHandler parent, |
| Locator locator, Attributes attributes, URL includingSource, |
| Project project) |
| throws SAXParseException { |
| super(xmlReader, parent, locator); |
| for (int i = 0; i < attributes.getLength(); ++i) { |
| String attributeName = attributes.getQName(i); |
| String attributeValue = attributes.getValue(i); |
| if (attributeName.equals(INCLUDE_SYSTEMID_ATTR)) { |
| includeSystemId = attributeValue; |
| } |
| else { |
| throw new SAXParseException("Attribute " + attributeName + |
| " is not allowed in an <include> element", getLocator()); |
| } |
| } |
| |
| if (includeSystemId == null) { |
| throw new SAXParseException("Attribute " + INCLUDE_SYSTEMID_ATTR + |
| " is required in an <include> element", getLocator()); |
| } |
| |
| // create a new parser to read this project relative to the |
| // project's URI |
| try { |
| URL includeURL = new URL(includingSource, includeSystemId); |
| SAXParser includeSAXParser = parserFactory.newSAXParser(); |
| XMLReader includeXMLReader = includeSAXParser.getXMLReader(); |
| |
| if (recursionCheck.contains(includeURL)) { |
| throw new SAXParseException("Circular include detected when including '" + |
| includeURL + "'", getLocator()); |
| } |
| recursionCheck.push(includeURL); |
| IncludeRootHandler includeRootHandler |
| = new IncludeRootHandler(includeURL, includeXMLReader, project); |
| includeSAXParser.parse(includeURL.toString(), includeRootHandler); |
| if (recursionCheck.pop() != includeURL) { |
| throw new RuntimeException("Failure to pop expected element off recursion stack"); |
| } |
| } |
| catch (SAXParseException e) { |
| throw e; |
| } |
| catch (MalformedURLException e) { |
| throw new SAXParseException("Unable to include " + includeSystemId + |
| ": " + e.getMessage(), |
| getLocator()); |
| } |
| catch (ParserConfigurationException e) { |
| throw new SAXParseException("Unable to parse include " + includeSystemId + |
| ": " + e.getMessage(), |
| getLocator()); |
| } |
| catch (SAXException e) { |
| throw new SAXParseException("Unable to parse include " + includeSystemId + |
| ": " + e.getMessage(), |
| getLocator()); |
| } |
| catch (IOException e) { |
| throw new SAXParseException("Error reading include " + includeSystemId + |
| ": " + e.getMessage(), |
| getLocator()); |
| } |
| } |
| |
| /** |
| * Include does not support nested elements. This method will always throw an |
| * exception |
| * |
| * @param uri The Namespace URI. |
| * @param localName The local name (without prefix). |
| * @param qualifiedName The qualified name (with prefix) |
| * @param attributes The attributes attached to the element. |
| * |
| * @throws SAXParseException always. |
| */ |
| public void startElement(String uri, String localName, String qualifiedName, |
| Attributes attributes) throws SAXParseException { |
| // everything is a task |
| throw new SAXParseException("<include> does not support nested elements", getLocator()); |
| } |
| |
| } |
| |
| /** |
| * A TargetHandler process the Target element. |
| */ |
| private class TargetHandler extends ElementHandler { |
| /** |
| * The target being configured. |
| */ |
| private Target target; |
| |
| /** |
| * Create a Target handler. Event element in a target is |
| * considered to be a task |
| * |
| * @param xmlReader the XML parser being used to parse the target element. |
| * @param parent the parent element handler. |
| * @param locator the SAX locator object used to associate elements with source |
| * locations. |
| * @param attributes attributes of the target |
| */ |
| public TargetHandler(XMLReader xmlReader, ContentHandler parent, |
| Locator locator, Attributes attributes) |
| throws SAXParseException { |
| super(xmlReader, parent, locator); |
| String targetName = null; |
| String depends = null; |
| Map aspects = new HashMap(); |
| for (int i = 0; i < attributes.getLength(); ++i) { |
| String attributeName = attributes.getQName(i); |
| String attributeValue = attributes.getValue(i); |
| if (attributeName.equals("name")) { |
| targetName = attributeValue; |
| } |
| else if (attributeName.equals("depends")) { |
| depends = attributeValue; |
| } |
| else if (attributeName.indexOf(":") != -1) { |
| // potential aspect attribute |
| aspects.put(attributeName, attributeValue); |
| } |
| else { |
| throw new SAXParseException("The attribute '" + attributeName + "' is not " + |
| "supported by the <target> element", getLocator()); |
| } |
| } |
| if (targetName == null) { |
| throw new SAXParseException("Targets must have a name attribute", locator); |
| } |
| target = new Target(getLocation(locator), targetName); |
| target.setAspects(aspects); |
| |
| if (depends != null) { |
| StringTokenizer tokenizer = new StringTokenizer(depends, ","); |
| while (tokenizer.hasMoreTokens()) { |
| String dependency = tokenizer.nextToken(); |
| target.addDependency(dependency); |
| } |
| } |
| } |
| |
| /* |
| * Process an element within this target. All elements within the target are |
| * treated as tasks. |
| * |
| * @param uri The Namespace URI. |
| * @param localName The local name (without prefix). |
| * @param qualifiedName The qualified name (with prefix) |
| * @param attributes The attributes attached to the element. |
| * |
| * @throws SAXParseException if there is a parsing problem. |
| */ |
| public void startElement(String uri, String localName, String qualifiedName, |
| Attributes attributes) throws SAXParseException { |
| // everything is a task |
| TaskElementHandler taskHandler |
| = new TaskElementHandler(getXMLReader(), this, getLocator(), |
| attributes, qualifiedName); |
| target.addTask(taskHandler.getTaskElement()); |
| } |
| |
| /** |
| * Get the target parsed by this handler. |
| * |
| * @return the Target model object parsed by this handler. |
| */ |
| public Target getTarget() { |
| return target; |
| } |
| } |
| |
| /** |
| * A TaskElementHandler parses the task elements of a build |
| */ |
| private class TaskElementHandler extends ElementHandler { |
| /** |
| * The task element being parsed by this handler. |
| */ |
| private TaskElement taskElement; |
| |
| /** |
| * Create a task element handler to parse a task element |
| * |
| * @param xmlReader the XML parser being used to parse the task element. |
| * @param parent the parent element handler. |
| * @param locator the SAX locator object used to associate elements with source |
| * locations. |
| * @param attributes attributes of the task element |
| * @param elementTagName the name of the task element. |
| */ |
| public TaskElementHandler(XMLReader xmlReader, ContentHandler parent, Locator locator, |
| Attributes attributes, String elementTagName) { |
| super(xmlReader, parent, locator); |
| taskElement |
| = new TaskElement(getLocation(locator), elementTagName); |
| |
| Map aspects = new HashMap(); |
| for (int i = 0; i < attributes.getLength(); ++i) { |
| String attributeName = attributes.getQName(i); |
| String attributeValue = attributes.getValue(i); |
| if (attributeName.indexOf(":") != -1) { |
| // potential aspect attribute |
| aspects.put(attributeName, attributeValue); |
| } |
| else { |
| taskElement.addAttribute(attributeName, attributeValue); |
| } |
| } |
| taskElement.setAspects(aspects); |
| } |
| |
| /** |
| * Process a nested element of this task element. All nested elements |
| * of a taskElement are themselves taskElements. |
| * |
| * @param uri The Namespace URI. |
| * @param localName The local name (without prefix). |
| * @param qualifiedName The qualified name (with prefix) |
| * @param attributes The attributes attached to the element. |
| * |
| * @throws SAXParseException if there is a parsing problem. |
| */ |
| public void startElement(String uri, String localName, String qualifiedName, |
| Attributes attributes) throws SAXParseException { |
| // everything within a task element is also a task element |
| TaskElementHandler nestedHandler |
| = new TaskElementHandler(getXMLReader(), this, getLocator(), |
| attributes, qualifiedName); |
| taskElement.addTaskElement(nestedHandler.getTaskElement()); |
| } |
| |
| public void characters(char[] buf, int start, int end) throws SAXParseException { |
| taskElement.addText(new String(buf, start, end)); |
| } |
| |
| /** |
| * Get the task element being parsed by this handler. |
| * |
| * @return the TaskElement being parsed. |
| */ |
| public TaskElement getTaskElement() { |
| return taskElement; |
| } |
| } |
| |
| /** |
| * A NoProjectReadException is used to indicate that a project |
| * was not read from the particular source. This will happen |
| * if the source is empty. |
| */ |
| private class NoProjectReadException extends Exception { |
| } |
| } |
| |