diff --git a/proposal/sandbox/embed/ProjectHelper.java b/proposal/sandbox/embed/ProjectHelper.java
index 66243c20e..92eec91c9 100644
--- a/proposal/sandbox/embed/ProjectHelper.java
+++ b/proposal/sandbox/embed/ProjectHelper.java
@@ -69,7 +69,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.xml.sax.AttributeList;
-
+import org.apache.tools.ant.helper.ProjectHelperImpl;
/**
* Configures a Project (complete with Targets and Tasks) based on
@@ -90,48 +90,42 @@ import org.xml.sax.AttributeList;
*
* @author duncan@x180.com
*/
-public /*abstract*/ class ProjectHelper {
+public class ProjectHelper {
/**
- * Configures the Project with the contents of the specified XML file.
- * ( should it be deprecated ? Using getProjectHelper(), parse()
- * is cleaner )
+ * Configures the project with the contents of the specified XML file.
+ *
+ * @param project The project to configure. Must not be null
.
+ * @param buildFile An XML file giving the project's configuration.
+ * Must not be null
.
+ *
+ * @exception BuildException if the configuration is invalid or cannot
+ * be read
*/
- public static void configureProject(Project project, File buildFile)
- throws BuildException
- {
+ public static void configureProject(Project project, File buildFile) throws BuildException {
ProjectHelper helper=ProjectHelper.getProjectHelper();
helper.parse(project, buildFile);
}
public ProjectHelper() {
}
-
- /**
- * Constructs a new Ant parser for the specified XML file.
- * @deprecated Use the plugin mechanism instead.
- */
- private ProjectHelper(Project project, File buildFile) {
- // this.project = project;
- // this.buildFile = new File(buildFile.getAbsolutePath());
- // buildFileParent = new File(this.buildFile.getParent());
- }
- public Project createProject(ClassLoader coreLoader) {
- return new Project();
- }
-
/**
- * Process an input source for the project.
+ * Parses the project file, configuring the project as it goes.
+ *
+ * @param project The project for the resulting ProjectHelper to configure.
+ * Must not be null
.
+ * @param source The source for XML configuration. A helper must support
+ * at least File, for backward compatibility. Helpers may
+ * support URL, InputStream, etc or specialized types.
*
- * All processors must support at least File sources. It is usefull to also support
- * InputSource - this allows the input to come from a non-filesystem source
- * (like input stream of a POST, or a soap body ).
+ * @since Ant1.5
+ * @exception BuildException if the configuration is invalid or cannot
+ * be read
*/
- public /*abstract*/ void parse(Project project, Object source)
- throws BuildException
- {
- throw new BuildException("You must use a real ProjectHelper implementation");
+ public void parse(Project project, Object source) throws BuildException {
+ throw new BuildException("ProjectHelper.parse() must be implemented in a helper plugin "
+ + this.getClass().getName());
}
/* -------------------- Helper discovery -------------------- */
@@ -142,21 +136,22 @@ public /*abstract*/ class ProjectHelper {
"/META-INF/services/org.apache.tools.ant.ProjectHelper";
- /** Discover a project helper instance.
+ /** Discover a project helper instance. Uses the same patterns
+ * as JAXP, commons-logging, etc: a system property, a JDK1.3
+ * service discovery, default.
*/
public static ProjectHelper getProjectHelper()
throws BuildException
{
// Identify the class loader we will be using. Ant may be
// in a webapp or embeded in a different app
- ClassLoader classLoader = getContextClassLoader();
ProjectHelper helper=null;
// First, try the system property
try {
String helperClass = System.getProperty(HELPER_PROPERTY);
if (helperClass != null) {
- helper = newHelper(helperClass, classLoader);
+ helper = newHelper(helperClass);
}
} catch (SecurityException e) {
// It's ok, we'll try next option
@@ -167,13 +162,15 @@ public /*abstract*/ class ProjectHelper {
// automatically if in CLASSPATH, with the right META-INF/services.
if( helper==null ) {
try {
+ ClassLoader classLoader=getContextClassLoader();
InputStream is=null;
- if (classLoader == null) {
- is=ClassLoader.getSystemResourceAsStream( SERVICE_ID );
- } else {
+ if (classLoader != null) {
is=classLoader.getResourceAsStream( SERVICE_ID );
}
-
+ if( is==null ) {
+ is=ClassLoader.getSystemResourceAsStream( SERVICE_ID );
+ }
+
if( is != null ) {
// This code is needed by EBCDIC and other strange systems.
// It's a fix for bugs reported in xerces
@@ -190,7 +187,7 @@ public /*abstract*/ class ProjectHelper {
if (helperClassName != null &&
! "".equals(helperClassName)) {
- helper= newHelper( helperClassName, classLoader );
+ helper= newHelper( helperClassName );
}
}
} catch( Exception ex ) {
@@ -202,17 +199,25 @@ public /*abstract*/ class ProjectHelper {
return new ProjectHelperImpl();
}
- private static ProjectHelper newHelper(String helperClass,
- ClassLoader classLoader)
+ /** Create a new helper. It'll first try the thread class loader,
+ * then Class.forName() will load from the same loader that
+ * loaded this class.
+ */
+ private static ProjectHelper newHelper(String helperClass)
throws BuildException
{
-
+ ClassLoader classLoader = getContextClassLoader();
try {
Class clazz = null;
- if (classLoader == null) {
+ if (classLoader != null) {
+ try {
+ clazz = classLoader.loadClass(helperClass);
+ } catch( ClassNotFoundException ex ) {
+ // try next method
+ }
+ }
+ if( clazz==null ) {
clazz = Class.forName(helperClass);
- } else {
- clazz = classLoader.loadClass(helperClass);
}
return ((ProjectHelper) clazz.newInstance());
} catch (Exception e) {
@@ -220,7 +225,9 @@ public /*abstract*/ class ProjectHelper {
}
}
- /**
+ /**
+ * JDK1.1 compatible access to the context class loader.
+ * Cut&paste from Jaxp.
*/
public static ClassLoader getContextClassLoader()
throws BuildException
@@ -251,42 +258,42 @@ public /*abstract*/ class ProjectHelper {
return (classLoader);
}
-
- /* -------------------- Common utilities and wrappers -------------------- */
+ // -------------------- Static utils, used by most helpers --------------------
- /** Configure a java object using ant's rules.
+ /**
+ * Configures an object using an introspection handler.
+ *
+ * @param target The target object to be configured.
+ * Must not be null
.
+ * @param attrs A list of attributes to configure within the target.
+ * Must not be null
.
+ * @param project The project containing the target.
+ * Must not be null
.
+ *
+ * @exception BuildException if any of the attributes can't be handled by
+ * the target
*/
public static void configure(Object target, AttributeList attrs,
Project project) throws BuildException {
- TaskAdapter adapter=null;
if( target instanceof TaskAdapter ) {
- adapter=(TaskAdapter)target;
- target=adapter.getProxy();
+ target=((TaskAdapter)target).getProxy();
}
IntrospectionHelper ih =
IntrospectionHelper.getHelper(target.getClass());
- if( adapter != null )
- adapter.setIntrospectionHelper( ih );
- // XXX What's that ?
project.addBuildListener(ih);
for (int i = 0; i < attrs.getLength(); i++) {
// reflect these into the target
String value=replaceProperties(project, attrs.getValue(i),
project.getProperties() );
- String name=attrs.getName(i).toLowerCase(Locale.US);
try {
- if (adapter!=null ) {
- adapter.setAttribute( name, value );
- } else {
- ih.setAttribute(project, target,
- name, value);
- }
+ ih.setAttribute(project, target,
+ attrs.getName(i).toLowerCase(Locale.US), value);
+
} catch (BuildException be) {
// id attribute must be set externally
- // XXX Shuldn't it be 'name' ( i.e. lower-cased ) ?
if (!attrs.getName(i).equals("id")) {
throw be;
}
@@ -296,14 +303,35 @@ public /*abstract*/ class ProjectHelper {
/**
* Adds the content of #PCDATA sections to an element.
+ *
+ * @param project The project containing the target.
+ * Must not be null
.
+ * @param target The target object to be configured.
+ * Must not be null
.
+ * @param buf A character array of the text within the element.
+ * Will not be null
.
+ * @param start The start element in the array.
+ * @param count The number of characters to read from the array.
+ *
+ * @exception BuildException if the target object doesn't accept text
*/
- public static void addText(Project project, Object target, char[] buf, int start, int end)
+ public static void addText(Project project, Object target, char[] buf, int start, int count)
throws BuildException {
- addText(project, target, new String(buf, start, end));
+ addText(project, target, new String(buf, start, count));
}
/**
* Adds the content of #PCDATA sections to an element.
+ *
+ * @param project The project containing the target.
+ * Must not be null
.
+ * @param target The target object to be configured.
+ * Must not be null
.
+ * @param text Text to add to the target.
+ * May be null
, in which case this
+ * method call is a no-op.
+ *
+ * @exception BuildException if the target object doesn't accept text
*/
public static void addText(Project project, Object target, String text)
throws BuildException {
@@ -320,7 +348,17 @@ public /*abstract*/ class ProjectHelper {
}
/**
- * Stores a configured child element into its parent object
+ * Stores a configured child element within its parent object.
+ *
+ * @param project Project containing the objects.
+ * May be null
.
+ * @param parent Parent object to add child to.
+ * Must not be null
.
+ * @param child Child object to store in parent.
+ * Should not be null
.
+ * @param tag Name of element which generated the child.
+ * May be null
, in which case
+ * the child is not stored.
*/
public static void storeChild(Project project, Object parent, Object child, String tag) {
IntrospectionHelper ih = IntrospectionHelper.getHelper(parent.getClass());
@@ -328,10 +366,18 @@ public /*abstract*/ class ProjectHelper {
}
/**
- * Replace ${} style constructions in the given value with the string value of
- * the corresponding data types.
+ * Replaces ${xxx}
style constructions in the given value with
+ * the string value of the corresponding properties.
+ *
+ * @param value The string to be scanned for property references.
+ * May be null
.
*
- * @param value the string to be scanned for property references.
+ * @exception BuildException if the string contains an opening
+ * ${
without a closing
+ * }
+ * @return the original string with the properties replaced, or
+ * null
if the original string is null
.
+ *
* @since 1.5
*/
public static String replaceProperties(Project project, String value)
@@ -340,10 +386,22 @@ public /*abstract*/ class ProjectHelper {
}
/**
- * Replace ${} style constructions in the given value with the string value of
- * the corresponding data types.
+ * Replaces ${xxx}
style constructions in the given value
+ * with the string value of the corresponding data types.
*
- * @param value the string to be scanned for property references.
+ * @param project The container project. This is used solely for
+ * logging purposes. Must not be null
.
+ * @param value The string to be scanned for property references.
+ * May be null
, in which case this
+ * method returns immediately with no effect.
+ * @param keys Mapping (String to String) of property names to their
+ * values. Must not be null
.
+ *
+ * @exception BuildException if the string contains an opening
+ * ${
without a closing
+ * }
+ * @return the original string with the properties replaced, or
+ * null
if the original string is null
.
*/
public static String replaceProperties(Project project, String value, Hashtable keys)
throws BuildException {
@@ -375,11 +433,21 @@ public /*abstract*/ class ProjectHelper {
}
/**
- * This method will parse a string containing ${value} style
- * property values into two lists. The first list is a collection
- * of text fragments, while the other is a set of string property names
- * null entries in the first list indicate a property reference from the
- * second list.
+ * Parses a string containing ${xxx}
style property
+ * references into two lists. The first list is a collection
+ * of text fragments, while the other is a set of string property names.
+ * null
entries in the first list indicate a property
+ * reference from the second list.
+ *
+ * @param value Text to parse. Must not be null
.
+ * @param fragments List to add text fragments to.
+ * Must not be null
.
+ * @param propertyRefs List to add property names to.
+ * Must not be null
.
+ *
+ * @exception BuildException if the string contains an opening
+ * ${
without a closing
+ * }
*/
public static void parsePropertyString(String value, Vector fragments, Vector propertyRefs)
throws BuildException {
@@ -414,5 +482,4 @@ public /*abstract*/ class ProjectHelper {
fragments.addElement(value.substring(prev));
}
}
-
}
diff --git a/proposal/sandbox/embed/ProjectHelperImpl.java b/proposal/sandbox/embed/ProjectHelperImpl.java
index a825a687a..221a5a3df 100644
--- a/proposal/sandbox/embed/ProjectHelperImpl.java
+++ b/proposal/sandbox/embed/ProjectHelperImpl.java
@@ -52,7 +52,9 @@
* null
.
+ */
+ public AbstractHandler(DocumentHandler parentHandler) {
this.parentHandler = parentHandler;
- this.helper=helper;
// Start handling SAX events
- helper.parser.setDocumentHandler(this);
+ parser.setDocumentHandler(this);
}
-
+
+ /**
+ * Handles the start of an element. This base implementation just
+ * throws an exception.
+ *
+ * @param tag The name of the element being started.
+ * Will not be null
.
+ * @param attrs Attributes of the element being started.
+ * Will not be null
.
+ *
+ * @exception SAXParseException if this method is not overridden, or in
+ * case of error in an overridden version
+ */
public void startElement(String tag, AttributeList attrs) throws SAXParseException {
- throw new SAXParseException("Unexpected element \"" + tag + "\"", helper.locator);
+ throw new SAXParseException("Unexpected element \"" + tag + "\"", locator);
}
- public void characters(char[] buf, int start, int end) throws SAXParseException {
- String s = new String(buf, start, end).trim();
+ /**
+ * Handles text within an element. This base implementation just
+ * throws an exception.
+ *
+ * @param buf A character array of the text within the element.
+ * Will not be null
.
+ * @param start The start element in the array.
+ * @param count The number of characters to read from the array.
+ *
+ * @exception SAXParseException if this method is not overridden, or in
+ * case of error in an overridden version
+ */
+ public void characters(char[] buf, int start, int count) throws SAXParseException {
+ String s = new String(buf, start, count).trim();
if (s.length() > 0) {
- throw new SAXParseException("Unexpected text \"" + s + "\"", helper.locator);
+ throw new SAXParseException("Unexpected text \"" + s + "\"", locator);
}
}
@@ -247,31 +273,45 @@ public class ProjectHelperImpl extends ProjectHelper {
*/
protected void finished() {}
+ /**
+ * Handles the end of an element. Any required clean-up is performed
+ * by the finished() method and then the original handler is restored to
+ * the parser.
+ *
+ * @param name The name of the element which is ending.
+ * Will not be null
.
+ *
+ * @exception SAXException in case of error (not thrown in
+ * this implementation)
+ *
+ * @see #finished()
+ */
public void endElement(String name) throws SAXException {
finished();
// Let parent resume handling SAX events
- helper.parser.setDocumentHandler(parentHandler);
+ parser.setDocumentHandler(parentHandler);
}
}
/**
- * Handler for the root element. It's only child must be the "project" element.
+ * Handler for the root element. Its only child must be the "project" element.
*/
- private static class RootHandler extends HandlerBase {
- private ProjectHelperImpl helper;
+ private class RootHandler extends HandlerBase {
- public RootHandler( ProjectHelperImpl helper ) {
- this.helper=helper;
- }
-
/**
- * resolve file: URIs as relative to the build file.
+ * Resolves file: URIs relative to the build file.
+ *
+ * @param publicId The public identifer, or null
+ * if none is available. Ignored in this
+ * implementation.
+ * @param systemId The system identifier provided in the XML
+ * document. Will not be null
.
*/
public InputSource resolveEntity(String publicId,
String systemId) {
- helper.project.log("resolving systemId: " + systemId, Project.MSG_VERBOSE);
+ project.log("resolving systemId: " + systemId, Project.MSG_VERBOSE);
if (systemId.startsWith("file:")) {
String path = systemId.substring(5);
@@ -294,7 +334,7 @@ public class ProjectHelperImpl extends ProjectHelper {
File file = new File(path);
if (!file.isAbsolute()) {
- file = new File(helper.buildFileParent, path);
+ file = new File(buildFileParent, path);
}
try {
@@ -302,7 +342,7 @@ public class ProjectHelperImpl extends ProjectHelper {
inputSource.setSystemId("file:" + entitySystemId);
return inputSource;
} catch (FileNotFoundException fne) {
- helper.project.log(file.getAbsolutePath()+" could not be found",
+ project.log(file.getAbsolutePath()+" could not be found",
Project.MSG_WARN);
}
}
@@ -310,27 +350,69 @@ public class ProjectHelperImpl extends ProjectHelper {
return null;
}
+ /**
+ * Handles the start of a project element. A project handler is created
+ * and initialised with the element name and attributes.
+ *
+ * @param tag The name of the element being started.
+ * Will not be null
.
+ * @param attrs Attributes of the element being started.
+ * Will not be null
.
+ *
+ * @exception SAXParseException if the tag given is not
+ * "project"
+ */
public void startElement(String tag, AttributeList attrs) throws SAXParseException {
if (tag.equals("project")) {
- new ProjectHandler(helper, this).init(tag, attrs);
+ new ProjectHandler(this).init(tag, attrs);
} else {
- throw new SAXParseException("Config file is not of expected XML type", helper.locator);
+ throw new SAXParseException("Config file is not of expected XML type", locator);
}
}
+ /**
+ * Sets the locator in the project helper for future reference.
+ *
+ * @param locator The locator used by the parser.
+ * Will not be null
.
+ */
public void setDocumentLocator(Locator locator) {
- helper.locator = locator;
+ ProjectHelperImpl.this.locator = locator;
}
}
/**
* Handler for the top level "project" element.
*/
- private static class ProjectHandler extends AbstractHandler {
- public ProjectHandler(ProjectHelperImpl helper, DocumentHandler parentHandler) {
- super(helper, parentHandler);
+ private class ProjectHandler extends AbstractHandler {
+
+ /**
+ * Constructor which just delegates to the superconstructor.
+ *
+ * @param parentHandler The handler which should be restored to the
+ * parser at the end of the element.
+ * Must not be null
.
+ */
+ public ProjectHandler(DocumentHandler parentHandler) {
+ super(parentHandler);
}
-
+
+ /**
+ * Initialisation routine called after handler creation
+ * with the element name and attributes. The attributes which
+ * this handler can deal with are: "default"
,
+ * "name"
, "id"
and "basedir"
.
+ *
+ * @param tag Name of the element which caused this handler
+ * to be created. Should not be null
.
+ * Ignored in this implementation.
+ * @param attrs Attributes of the element which caused this
+ * handler to be created. Must not be null
.
+ *
+ * @exception SAXParseException if an unexpected attribute is
+ * encountered or if the "default"
attribute
+ * is missing.
+ */
public void init(String tag, AttributeList attrs) throws SAXParseException {
String def = null;
String name = null;
@@ -350,44 +432,59 @@ public class ProjectHelperImpl extends ProjectHelper {
} else if (key.equals("basedir")) {
baseDir = value;
} else {
- throw new SAXParseException("Unexpected attribute \"" + attrs.getName(i) + "\"", helper.locator);
+ throw new SAXParseException("Unexpected attribute \"" + attrs.getName(i) + "\"", locator);
}
}
if (def == null) {
throw new SAXParseException("The default attribute of project is required",
- helper.locator);
+ locator);
}
- helper.project.setDefaultTarget(def);
+ project.setDefaultTarget(def);
if (name != null) {
- helper.project.setName(name);
- helper.project.addReference(name, helper.project);
+ project.setName(name);
+ project.addReference(name, project);
}
if (id != null) {
- helper.project.addReference(id, helper.project);
+ project.addReference(id, project);
}
- if (helper.project.getProperty("basedir") != null) {
- helper.project.setBasedir(helper.project.getProperty("basedir"));
+ if (project.getProperty("basedir") != null) {
+ project.setBasedir(project.getProperty("basedir"));
} else {
if (baseDir == null) {
- helper.project.setBasedir(helper.buildFileParent.getAbsolutePath());
+ project.setBasedir(buildFileParent.getAbsolutePath());
} else {
// check whether the user has specified an absolute path
if ((new File(baseDir)).isAbsolute()) {
- helper.project.setBasedir(baseDir);
+ project.setBasedir(baseDir);
} else {
- helper.project.setBaseDir(helper.project.resolveFile(baseDir, helper.buildFileParent));
+ project.setBaseDir(project.resolveFile(baseDir, buildFileParent));
}
}
}
}
+ /**
+ * Handles the start of a top-level element within the project. An
+ * appropriate handler is created and initialised with the details
+ * of the element.
+ *
+ * @param tag The name of the element being started.
+ * Will not be null
.
+ * @param attrs Attributes of the element being started.
+ * Will not be null
.
+ *
+ * @exception SAXParseException if the tag given is not
+ * "taskdef"
, "typedef"
,
+ * "property"
, "target"
+ * or a data type definition
+ */
public void startElement(String name, AttributeList attrs) throws SAXParseException {
if (name.equals("taskdef")) {
handleTaskdef(name, attrs);
@@ -397,31 +494,91 @@ public class ProjectHelperImpl extends ProjectHelper {
handleProperty(name, attrs);
} else if (name.equals("target")) {
handleTarget(name, attrs);
- } else if (helper.project.getDataTypeDefinitions().get(name) != null) {
+ } else if (project.getDataTypeDefinitions().get(name) != null) {
handleDataType(name, attrs);
} else {
- throw new SAXParseException("Unexpected element \"" + name + "\"", helper.locator);
+ throw new SAXParseException("Unexpected element \"" + name + "\"", locator);
}
}
-
+
+ /**
+ * Handles a task defintion element by creating a task handler
+ * and initialising is with the details of the element.
+ *
+ * @param tag The name of the element to be handled.
+ * Will not be null
.
+ * @param attrs Attributes of the element to be handled.
+ * Will not be null
.
+ *
+ * @exception SAXParseException if an error occurs when initialising
+ * the task handler
+ *
+ */
private void handleTaskdef(String name, AttributeList attrs) throws SAXParseException {
- (new TaskHandler(helper, this, null, null, null)).init(name, attrs);
+ (new TaskHandler(this, null, null, null)).init(name, attrs);
}
+ /**
+ * Handles a type defintion element by creating a task handler
+ * and initialising is with the details of the element.
+ *
+ * @param tag The name of the element to be handled.
+ * Will not be null
.
+ * @param attrs Attributes of the element to be handled.
+ * Will not be null
.
+ *
+ * @exception SAXParseException if an error occurs initialising the
+ * handler
+ */
private void handleTypedef(String name, AttributeList attrs) throws SAXParseException {
- (new TaskHandler(helper, this, null, null, null)).init(name, attrs);
+ (new TaskHandler(this, null, null, null)).init(name, attrs);
}
+ /**
+ * Handles a property defintion element by creating a task handler
+ * and initialising is with the details of the element.
+ *
+ * @param tag The name of the element to be handled.
+ * Will not be null
.
+ * @param attrs Attributes of the element to be handled.
+ * Will not be null
.
+ *
+ * @exception SAXParseException if an error occurs initialising
+ * the handler
+ */
private void handleProperty(String name, AttributeList attrs) throws SAXParseException {
- (new TaskHandler(helper, this, null, null, null)).init(name, attrs);
+ (new TaskHandler(this, null, null, null)).init(name, attrs);
}
+ /**
+ * Handles a target defintion element by creating a target handler
+ * and initialising is with the details of the element.
+ *
+ * @param tag The name of the element to be handled.
+ * Will not be null
.
+ * @param attrs Attributes of the element to be handled.
+ * Will not be null
.
+ *
+ * @exception SAXParseException if an error occurs initialising
+ * the handler
+ */
private void handleTarget(String tag, AttributeList attrs) throws SAXParseException {
- new TargetHandler(helper, this).init(tag, attrs);
+ new TargetHandler(this).init(tag, attrs);
}
-
+ /**
+ * Handles a data type defintion element by creating a data type
+ * handler and initialising is with the details of the element.
+ *
+ * @param tag The name of the element to be handled.
+ * Will not be null
.
+ * @param attrs Attributes of the element to be handled.
+ * Will not be null
.
+ *
+ * @exception SAXParseException if an error occurs initialising
+ * the handler
+ */
private void handleDataType(String name, AttributeList attrs) throws SAXParseException {
- new DataTypeHandler(helper, this).init(name, attrs);
+ new DataTypeHandler(this).init(name, attrs);
}
}
@@ -429,13 +586,37 @@ public class ProjectHelperImpl extends ProjectHelper {
/**
* Handler for "target" elements.
*/
- private static class TargetHandler extends AbstractHandler {
+ private class TargetHandler extends AbstractHandler {
private Target target;
- public TargetHandler(ProjectHelperImpl helper, DocumentHandler parentHandler) {
- super(helper, parentHandler);
+ /**
+ * Constructor which just delegates to the superconstructor.
+ *
+ * @param parentHandler The handler which should be restored to the
+ * parser at the end of the element.
+ * Must not be null
.
+ */
+ public TargetHandler(DocumentHandler parentHandler) {
+ super(parentHandler);
}
+ /**
+ * Initialisation routine called after handler creation
+ * with the element name and attributes. The attributes which
+ * this handler can deal with are: "name"
,
+ * "depends"
, "if"
,
+ * "unless"
, "id"
and
+ * "description"
.
+ *
+ * @param tag Name of the element which caused this handler
+ * to be created. Should not be null
.
+ * Ignored in this implementation.
+ * @param attrs Attributes of the element which caused this
+ * handler to be created. Must not be null
.
+ *
+ * @exception SAXParseException if an unexpected attribute is encountered
+ * or if the "name"
attribute is missing.
+ */
public void init(String tag, AttributeList attrs) throws SAXParseException {
String name = null;
String depends = "";
@@ -461,12 +642,12 @@ public class ProjectHelperImpl extends ProjectHelper {
} else if (key.equals("description")) {
description = value;
} else {
- throw new SAXParseException("Unexpected attribute \"" + key + "\"", helper.locator);
+ throw new SAXParseException("Unexpected attribute \"" + key + "\"", locator);
}
}
if (name == null) {
- throw new SAXParseException("target element appears without a name attribute", helper.locator);
+ throw new SAXParseException("target element appears without a name attribute", locator);
}
target = new Target();
@@ -474,10 +655,10 @@ public class ProjectHelperImpl extends ProjectHelper {
target.setIf(ifCond);
target.setUnless(unlessCond);
target.setDescription(description);
- helper.project.addTarget(name, target);
+ project.addTarget(name, target);
if (id != null && !id.equals("")) {
- helper.project.addReference(id, target);
+ project.addReference(id, target);
}
// take care of dependencies
@@ -487,11 +668,22 @@ public class ProjectHelperImpl extends ProjectHelper {
}
}
+ /**
+ * Handles the start of an element within a target.
+ *
+ * @param tag The name of the element being started.
+ * Will not be null
.
+ * @param attrs Attributes of the element being started.
+ * Will not be null
.
+ *
+ * @exception SAXParseException if an error occurs when initialising
+ * the appropriate child handler
+ */
public void startElement(String name, AttributeList attrs) throws SAXParseException {
- if (helper.project.getDataTypeDefinitions().get(name) != null) {
- new DataTypeHandler(helper, this, target).init(name, attrs);
+ if (project.getDataTypeDefinitions().get(name) != null) {
+ new DataTypeHandler(this, target).init(name, attrs);
} else {
- new TaskHandler(helper, this, target, null, target).init(name, attrs);
+ new TaskHandler(this, target, null, target).init(name, attrs);
}
}
}
@@ -499,28 +691,78 @@ public class ProjectHelperImpl extends ProjectHelper {
/**
* Handler for all task elements.
*/
- private static class TaskHandler extends AbstractHandler {
+ private class TaskHandler extends AbstractHandler {
+ /** Containing target, if any. */
private Target target;
+ /**
+ * Container for the task, if any. If target is
+ * non-null
, this must be too.
+ */
private TaskContainer container;
+ /**
+ * Task created by this handler.
+ */
private Task task;
+ /**
+ * Wrapper for the parent element, if any. The wrapper for this
+ * element will be added to this wrapper as a child.
+ */
private RuntimeConfigurable parentWrapper;
+ /**
+ * Wrapper for this element which takes care of actually configuring
+ * the element, if this element is contained within a target.
+ * Otherwise the configuration is performed with the configure method.
+ * @see ProjectHelper#configure(Object,AttributeList,Project)
+ */
private RuntimeConfigurable wrapper = null;
-
- public TaskHandler(ProjectHelperImpl helper,
- DocumentHandler parentHandler,
- TaskContainer container,
- RuntimeConfigurable parentWrapper,
- Target target)
- {
- super(helper, parentHandler);
+
+ /**
+ * Constructor.
+ *
+ * @param parentHandler The handler which should be restored to the
+ * parser at the end of the element.
+ * Must not be null
.
+ *
+ * @param container Container for the element.
+ * May be null
if the target is
+ * null
as well. If the
+ * target is null
, this parameter
+ * is effectively ignored.
+ *
+ * @param parentWrapper Wrapper for the parent element, if any.
+ * May be null
. If the
+ * target is null
, this parameter
+ * is effectively ignored.
+ *
+ * @param target Target this element is part of.
+ * May be null
.
+ */
+ public TaskHandler(DocumentHandler parentHandler, TaskContainer container, RuntimeConfigurable parentWrapper, Target target) {
+ super(parentHandler);
this.container = container;
this.parentWrapper = parentWrapper;
this.target = target;
}
+ /**
+ * Initialisation routine called after handler creation
+ * with the element name and attributes. This configures
+ * the element with its attributes and sets it up with
+ * its parent container (if any). Nested elements are then
+ * added later as the parser encounters them.
+ *
+ * @param tag Name of the element which caused this handler
+ * to be created. Must not be null
.
+ *
+ * @param attrs Attributes of the element which caused this
+ * handler to be created. Must not be null
.
+ *
+ * @exception SAXParseException in case of error (not thrown in
+ * this implementation)
+ */
public void init(String tag, AttributeList attrs) throws SAXParseException {
try {
- task = helper.project.createTask(tag);
+ task = project.createTask(tag);
} catch (BuildException e) {
// swallow here, will be thrown again in
// UnknownElement.maybeConfigure if the problem persists.
@@ -528,15 +770,13 @@ public class ProjectHelperImpl extends ProjectHelper {
if (task == null) {
task = new UnknownElement(tag);
- task.setProject(helper.project);
- task.setTaskType(tag);
+ task.setProject(project);
+ //XXX task.setTaskType(tag);
task.setTaskName(tag);
}
- task.setLocation(new Location(helper.buildFile.toString(),
- helper.locator.getLineNumber(),
- helper.locator.getColumnNumber()));
- helper.configureId(task, attrs);
+ task.setLocation(new Location(buildFile.toString(), locator.getLineNumber(), locator.getColumnNumber()));
+ configureId(task, attrs);
// Top level tasks don't have associated targets
if (target != null) {
@@ -550,35 +790,65 @@ public class ProjectHelperImpl extends ProjectHelper {
}
} else {
task.init();
- configure(task, attrs, helper.project);
+ configure(task, attrs, project);
}
}
+ /**
+ * Executes the task if it is a top-level one.
+ */
protected void finished() {
if (task != null && target == null) {
task.execute();
}
}
- public void characters(char[] buf, int start, int end) throws SAXParseException {
+ /**
+ * Adds text to the task, using the wrapper if one is
+ * available (in other words if the task is within a target)
+ * or using addText otherwise.
+ *
+ * @param buf A character array of the text within the element.
+ * Will not be null
.
+ * @param start The start element in the array.
+ * @param count The number of characters to read from the array.
+ *
+ * @exception SAXParseException if the element doesn't support text
+ *
+ * @see ProjectHelper#addText(Project,Object,char[],int,int)
+ */
+ public void characters(char[] buf, int start, int count) throws SAXParseException {
if (wrapper == null) {
try {
- addText(helper.project, task, buf, start, end);
+ addText(project, task, buf, start, count);
} catch (BuildException exc) {
- throw new SAXParseException(exc.getMessage(), helper.locator, exc);
+ throw new SAXParseException(exc.getMessage(), locator, exc);
}
} else {
- wrapper.addText(buf, start, end);
+ wrapper.addText(buf, start, count);
}
}
-
+
+ /**
+ * Handles the start of an element within a target. Task containers
+ * will always use another task handler, and all other tasks
+ * will always use a nested element handler.
+ *
+ * @param tag The name of the element being started.
+ * Will not be null
.
+ * @param attrs Attributes of the element being started.
+ * Will not be null
.
+ *
+ * @exception SAXParseException if an error occurs when initialising
+ * the appropriate child handler
+ */
public void startElement(String name, AttributeList attrs) throws SAXParseException {
if (task instanceof TaskContainer) {
// task can contain other tasks - no other nested elements possible
- new TaskHandler(helper, this, (TaskContainer)task, wrapper, target).init(name, attrs);
+ new TaskHandler(this, (TaskContainer)task, wrapper, target).init(name, attrs);
}
else {
- new NestedElementHandler(helper, this, task, wrapper, target).init(name, attrs);
+ new NestedElementHandler(this, task, wrapper, target).init(name, attrs);
}
}
}
@@ -586,24 +856,50 @@ public class ProjectHelperImpl extends ProjectHelper {
/**
* Handler for all nested properties.
*/
- private static class NestedElementHandler extends AbstractHandler {
+ private class NestedElementHandler extends AbstractHandler {
+ /** Parent object (task/data type/etc). */
private Object parent;
+ /** The nested element itself. */
private Object child;
+ /**
+ * Wrapper for the parent element, if any. The wrapper for this
+ * element will be added to this wrapper as a child.
+ */
private RuntimeConfigurable parentWrapper;
+ /**
+ * Wrapper for this element which takes care of actually configuring
+ * the element, if a parent wrapper is provided.
+ * Otherwise the configuration is performed with the configure method.
+ * @see ProjectHelper#configure(Object,AttributeList,Project)
+ */
private RuntimeConfigurable childWrapper = null;
- private TaskAdapter adapter=null;
+ /** Target this element is part of, if any. */
private Target target;
- public NestedElementHandler(ProjectHelperImpl helper,
- DocumentHandler parentHandler,
+ /**
+ * Constructor.
+ *
+ * @param parentHandler The handler which should be restored to the
+ * parser at the end of the element.
+ * Must not be null
.
+ *
+ * @param parent Parent of this element (task/data type/etc).
+ * Must not be null
.
+ *
+ * @param parentWrapper Wrapper for the parent element, if any.
+ * May be null
.
+ *
+ * @param target Target this element is part of.
+ * May be null
.
+ */
+ public NestedElementHandler(DocumentHandler parentHandler,
Object parent,
RuntimeConfigurable parentWrapper,
Target target) {
- super(helper, parentHandler);
+ super(parentHandler);
if (parent instanceof TaskAdapter) {
- this.adapter= (TaskAdapter)parent;
- this.parent = adapter.getProxy();
+ this.parent = ((TaskAdapter) parent).getProxy();
} else {
this.parent = parent;
}
@@ -611,87 +907,159 @@ public class ProjectHelperImpl extends ProjectHelper {
this.target = target;
}
+ /**
+ * Initialisation routine called after handler creation
+ * with the element name and attributes. This configures
+ * the element with its attributes and sets it up with
+ * its parent container (if any). Nested elements are then
+ * added later as the parser encounters them.
+ *
+ * @param tag Name of the element which caused this handler
+ * to be created. Must not be null
.
+ *
+ * @param attrs Attributes of the element which caused this
+ * handler to be created. Must not be null
.
+ *
+ * @exception SAXParseException in case of error, such as a
+ * BuildException being thrown during configuration.
+ */
public void init(String propType, AttributeList attrs) throws SAXParseException {
Class parentClass = parent.getClass();
IntrospectionHelper ih =
IntrospectionHelper.getHelper(parentClass);
- if( adapter!=null ) {
- adapter.setIntrospectionHelper( ih );
- }
-
+
try {
String elementName = propType.toLowerCase(Locale.US);
if (parent instanceof UnknownElement) {
UnknownElement uc = new UnknownElement(elementName);
- uc.setProject(helper.project);
+ uc.setProject(project);
((UnknownElement) parent).addChild(uc);
child = uc;
} else {
- child = ih.createElement(helper.project, parent, elementName);
+ child = ih.createElement(project, parent, elementName);
}
- helper.configureId(child, attrs);
+ configureId(child, attrs);
if (parentWrapper != null) {
childWrapper = new RuntimeConfigurable(child, propType);
childWrapper.setAttributes(attrs);
parentWrapper.addChild(childWrapper);
} else {
- configure(child, attrs, helper.project);
- ih.storeElement(helper.project, parent, child, elementName);
+ configure(child, attrs, project);
+ ih.storeElement(project, parent, child, elementName);
}
} catch (BuildException exc) {
- throw new SAXParseException(exc.getMessage(), helper.locator, exc);
+ throw new SAXParseException(exc.getMessage(), locator, exc);
}
}
- public void characters(char[] buf, int start, int end) throws SAXParseException {
+ /**
+ * Adds text to the element, using the wrapper if one is
+ * available or using addText otherwise.
+ *
+ * @param buf A character array of the text within the element.
+ * Will not be null
.
+ * @param start The start element in the array.
+ * @param count The number of characters to read from the array.
+ *
+ * @exception SAXParseException if the element doesn't support text
+ *
+ * @see ProjectHelper#addText(Project,Object,char[],int,int)
+ */
+ public void characters(char[] buf, int start, int count) throws SAXParseException {
if (parentWrapper == null) {
try {
- addText(helper.project, child, buf, start, end);
+ addText(project, child, buf, start, count);
} catch (BuildException exc) {
- throw new SAXParseException(exc.getMessage(), helper.locator, exc);
+ throw new SAXParseException(exc.getMessage(), locator, exc);
}
} else {
- childWrapper.addText(buf, start, end);
+ childWrapper.addText(buf, start, count);
}
}
+ /**
+ * Handles the start of an element within this one. Task containers
+ * will always use a task handler, and all other elements
+ * will always use another nested element handler.
+ *
+ * @param tag The name of the element being started.
+ * Will not be null
.
+ * @param attrs Attributes of the element being started.
+ * Will not be null
.
+ *
+ * @exception SAXParseException if an error occurs when initialising
+ * the appropriate child handler
+ */
public void startElement(String name, AttributeList attrs) throws SAXParseException {
if (child instanceof TaskContainer) {
// taskcontainer nested element can contain other tasks - no other
// nested elements possible
- new TaskHandler(helper, this, (TaskContainer)child, childWrapper, target).init(name, attrs);
+ new TaskHandler(this, (TaskContainer)child, childWrapper, target).init(name, attrs);
}
else {
- new NestedElementHandler(helper, this, child, childWrapper, target).init(name, attrs);
+ new NestedElementHandler(this, child, childWrapper, target).init(name, attrs);
}
}
}
/**
- * Handler for all data types at global level.
+ * Handler for all data types directly subordinate to project or target.
*/
- private static class DataTypeHandler extends AbstractHandler {
+ private class DataTypeHandler extends AbstractHandler {
+ /** Parent target, if any. */
private Target target;
+ /** The element being configured. */
private Object element;
+ /** Wrapper for this element, if it's part of a target. */
private RuntimeConfigurable wrapper = null;
-
- public DataTypeHandler(ProjectHelperImpl helper, DocumentHandler parentHandler) {
- this(helper, parentHandler, null);
+
+ /**
+ * Constructor with no target specified.
+ *
+ * @param parentHandler The handler which should be restored to the
+ * parser at the end of the element.
+ * Must not be null
.
+ */
+ public DataTypeHandler(DocumentHandler parentHandler) {
+ this(parentHandler, null);
}
- public DataTypeHandler(ProjectHelperImpl helper,
- DocumentHandler parentHandler,
- Target target)
- {
- super(helper, parentHandler);
+ /**
+ * Constructor with a target specified.
+ *
+ * @param parentHandler The handler which should be restored to the
+ * parser at the end of the element.
+ * Must not be null
.
+ *
+ * @param target The parent target of this element.
+ * May be null
.
+ */
+ public DataTypeHandler(DocumentHandler parentHandler, Target target) {
+ super(parentHandler);
this.target = target;
}
+ /**
+ * Initialisation routine called after handler creation
+ * with the element name and attributes. This configures
+ * the element with its attributes and sets it up with
+ * its parent container (if any). Nested elements are then
+ * added later as the parser encounters them.
+ *
+ * @param tag Name of the element which caused this handler
+ * to be created. Must not be null
.
+ *
+ * @param attrs Attributes of the element which caused this
+ * handler to be created. Must not be null
.
+ *
+ * @exception SAXParseException in case of error, such as a
+ * BuildException being thrown during configuration.
+ */
public void init(String propType, AttributeList attrs) throws SAXParseException {
try {
- element = helper.project.createDataType(propType);
+ element = project.createDataType(propType);
if (element == null) {
throw new BuildException("Unknown data type "+propType);
}
@@ -701,30 +1069,60 @@ public class ProjectHelperImpl extends ProjectHelper {
wrapper.setAttributes(attrs);
target.addDataType(wrapper);
} else {
- configure(element, attrs, helper.project);
- helper.configureId(element, attrs);
+ configure(element, attrs, project);
+ configureId(element, attrs);
}
} catch (BuildException exc) {
- throw new SAXParseException(exc.getMessage(), helper.locator, exc);
+ throw new SAXParseException(exc.getMessage(), locator, exc);
}
}
- public void characters(char[] buf, int start, int end) throws SAXParseException {
+ // XXX: (Jon Skeet) Any reason why this doesn't use the wrapper
+ // if one is available, whereas NestedElementHandler.characters does?
+ /**
+ * Adds text to the element.
+ *
+ * @param buf A character array of the text within the element.
+ * Will not be null
.
+ * @param start The start element in the array.
+ * @param count The number of characters to read from the array.
+ *
+ * @exception SAXParseException if the element doesn't support text
+ *
+ * @see ProjectHelper#addText(Project,Object,char[],int,int)
+ */
+ public void characters(char[] buf, int start, int count) throws SAXParseException {
try {
- addText(helper.project, element, buf, start, end);
+ addText(project, element, buf, start, count);
} catch (BuildException exc) {
- throw new SAXParseException(exc.getMessage(), helper.locator, exc);
+ throw new SAXParseException(exc.getMessage(), locator, exc);
}
}
+ /**
+ * Handles the start of an element within this one.
+ * This will always use a nested element handler.
+ *
+ * @param tag The name of the element being started.
+ * Will not be null
.
+ * @param attrs Attributes of the element being started.
+ * Will not be null
.
+ *
+ * @exception SAXParseException if an error occurs when initialising
+ * the child handler
+ */
public void startElement(String name, AttributeList attrs) throws SAXParseException {
- new NestedElementHandler(helper, this, element, wrapper, target).init(name, attrs);
+ new NestedElementHandler(this, element, wrapper, target).init(name, attrs);
}
}
- public ProjectHelperImpl() {
- }
-
+ /**
+ * Returns the parser factory to use. Only one parser
+ * factory is ever created by this method (multi-threading
+ * issues aside) and is then cached for future use.
+ *
+ * @return a SAXParserFactory to use within this class
+ */
private static SAXParserFactory getParserFactory() {
if (parserFactory == null) {
parserFactory = SAXParserFactory.newInstance();
@@ -734,11 +1132,14 @@ public class ProjectHelperImpl extends ProjectHelper {
}
/**
- * Scan AttributeList for the id attribute and maybe add a
- * reference to project.
- *
- *
Moved out of {@link #configure configure} to make it happen - * at parser time.
+ * Scans an attribute list for theid
attribute and
+ * stores a reference to the target object in the project if an
+ * id is found.
+ * + * This method was moved out of the configure method to allow + * it to be executed at parse time. + * + * @see #configure(Object,AttributeList,Project) */ private void configureId(Object target, AttributeList attr) { String id = attr.getValue("id"); @@ -746,5 +1147,4 @@ public class ProjectHelperImpl extends ProjectHelper { project.addReference(id, target); } } - }