diff --git a/proposal/mutant/docs/desc.html b/proposal/mutant/docs/desc.html index 49aba6f42..daed0c8eb 100644 --- a/proposal/mutant/docs/desc.html +++ b/proposal/mutant/docs/desc.html @@ -2,19 +2,19 @@ - + - + - - The Jakarta Site - Mutant Design Notes + + Mutant Proposal - Mutant Design Notes - - + + @@ -27,58 +27,21 @@ - + diff --git a/proposal/mutant/docs/design.html b/proposal/mutant/docs/design.html new file mode 100644 index 000000000..8a88c0ce7 --- /dev/null +++ b/proposal/mutant/docs/design.html @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + Mutant Proposal - Developers + + + +

-

Apache Ant

- -

Download

- -

Jakarta

- -

Get Involved

+

Mutant Proposal

+ + + + +
+ +
+ + + + + + + + + + + + +
+
+
+

Mutant Proposal

+ +
+ + + +
+ + Developers + +
+
+

+This page will describe the design of Mutant's core. +

+
+
+
+
+
+
+ Copyright © 2000-2002, Apache Software Foundation +
+
+ + + + + + + diff --git a/proposal/mutant/docs/developers.html b/proposal/mutant/docs/developers.html new file mode 100644 index 000000000..856ca1544 --- /dev/null +++ b/proposal/mutant/docs/developers.html @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + Mutant Proposal - Developers + + + + + + + + +
+ +
+ + + + + + + + + + + + +
+
+
+

Mutant Proposal

+ +
+ + + +
+ + Developers + +
+
+

+This page will describe the operation of Mutant from a task developers perspective. +

+
+
+
+
+
+
+ Copyright © 2000-2002, Apache Software Foundation +
+
+ + + + + + + diff --git a/proposal/mutant/docs/features.html b/proposal/mutant/docs/features.html new file mode 100644 index 000000000..6c3159fa1 --- /dev/null +++ b/proposal/mutant/docs/features.html @@ -0,0 +1,1112 @@ + + + + + + + + + + + + + + Mutant Proposal - Mutant Features + + + + + + + + +
+ +
+ + + + + + + + + + + + +
+
+
+

Mutant Proposal

+ +
+ + + +
+ + User Features + +
+
+

+This page describes the major features in Mutant which are significantly +different from those of Ant1. These are covered from a user perspective. Other +pages describe the differences from the perspectives of a task developer and an +Ant core developer. +

+
+
+ + + +
+ + Directory Layout + +
+
+

+When Mutant is installed, the most immediately obvious difference will be in the +directory layout, particularly the lib directory. Where Ant1's lib directory +contained ant.jar, optional.jar and the bundled XML jars, Mutant's lib directory +contain a number of subdirectories. +

+

+In the root directory, there are a number of jars. These jars are the startup +jars +

+ + + + + + + + + + + + + +
+ + init.jar + + + + a set of low level utility routines required at startup + +
+ + start.jar + + + + the Mutant launcher class + +
+ + ant.jar + + + + old Ant1 entry point + +
+

+The subdirectories have the following functions +

+ + + + + + + + + + + + + + + + + + + + + +
+ + parser + + + + The XML parser jars. This is not available to task libraries unless +they explicitly indicate that it is required. + +
+ + antcore + + + + Mutant's core classes. These classes are not available to +tasks. + +
+ + common + + + + classes which are available to both the core and all task +libraries. + +
+ + syslibs/antlibs + + + + Task libraries. The distinction between the two is +discussed below. + +
+ + frontend + + + + Ant Frontends. Different frontends may be plugged in by placing +jars here. + +
+

+The directory a jar is in will control the visibility of the jar's classes and +resources. This is closely related to the classloader hiearchy used by +Mutant. +

+
+
+ + + +
+ + Ant Libraries + +
+
+

+Mutant supports the concept of Ant Libraries. These are collections of +components (tasks and types) and their supporting classes packaged into a +Jar. In Mutant each library has a globally unique identifier. This identifier +uses the same conventions as Java package naming - i.e. a reverse DNS name. +

+

The jar does not need to be exclusively for Ant. For example, it may be the +jar for a tool which wishes to provide some Ant tasks for using the tool. It +could be the main jar of an appication server that bundles Ant tasks for +deployment. The jar does not even need to be installed in Mutant's antlib +directory - Mutant can be configured to look in jars in other locations for Ant +Libraries.

+ + + +
+ + Ant library descriptor + +
+
+

+Whatever the jar contains and wherever it is located, Mutant looks for an XML +based descriptor in the jar at META-INF/antlib.xml. This XML file describes the +components in the jar that will be available to Mutant. +

+

+Here is an example of the descriptor. +

+
+ + + + + + + + + + + + + + + + +
+<antlib libid="ant.system"
+        home="http://jakarta.apache.org/ant">
+
+  <taskdef name="libpath" classname="org.apache.ant.antlib.system.LibPath"/>
+  <taskdef name="loadlib" classname="org.apache.ant.antlib.system.LoadLib"/>
+  <taskdef name="import" classname="org.apache.ant.antlib.system.Import"/>
+
+  <converter classname="org.apache.ant.antlib.system.FileConverter"/>
+  <converter classname="org.apache.ant.antlib.system.URLConverter"/>
+  <converter classname="org.apache.ant.antlib.system.PrimitiveConverter"/>
+
+  <aspect classname="org.apache.ant.antlib.system.AntAspect"/>
+</antlib>
+
+
+

+As a user you generally won't need to worry about this decriptor. The library +developer will have developed it to describe their library. Mutant uses the +descriptor to understand what Ant related components the library provides. +

+
+
+ + + +
+ + Loading libraries + +
+
+

+Library management in Mutant is split into two phases - a loading phase and an +import phase. The loading phase is where Mutant loads the antlib.xml descriptor +from the library. After loading, Mutant knows where the library is located and +what components it provides. In general Mutant will not make the components +available to build scripts automatically. A build script needs to notify Mutant +what components it is using from each library. This is known as importing. +

+

Mutant loads libraries from two locations within the Mutant directory +structure when Mutant starts up - the lib/syslibs and lib/antlibs directories. +The distinction between these two locations is explained in the configuration +discussion below. All jars in these directories will be search for library +descriptors. All libraries providing descriptors will be available for importing +into builds

+

In addition to the automatically loaded libraries, it is possible to +explicitly request additional libraries to be loaded using the +<loadlib> task. Individual libraries may be loaded or a set +of libraries loaded from a directory. Libraries may also be loaded from remote +locations by specifying a URL. The loadlib task can request that all components +in the loaded library also be imported at the time of loading. Examples of the +loadlib task follow

+
+ + + + + + + + + + + + + + + + +
+  <!-- load a library from a specific file and import all components -->
+  <loadlib file="/opt/tools/toollib.jar" importall="true"/>
+
+  <!-- load all libraries from a directory -->
+  <loadlib dir="/opt/appserver/lib/"/>
+
+  <!-- load libraries from a remote server -->
+  <loadlib url="http://jakarta.apache.org/ant/testtasks.jar"/>
+
+
+

+In general the loading of libraries from absolute locations would be a +configuration task. These would be specified in the Mutant configuration file +and would not be used in a build file. The loading of project libraries from +relative locations may be something that you would see in a build file. +

+
+
+ + + +
+ + Importing components + +
+
+

+Mutant is designed to allow tasks to be defined simply by dropping a jar in a +directory or configuring Mutant to look in particular places for jars. This will +allow tasks and types developed by many different developers to be used. With +many developers developing tasks, however, inevitably some tasks will end up +with the same name. +

+

+This is very similar to the situation faced by Java with Java class names. +Many Java classes have the same name. When a Java programmer uses a class they +must import that class with an import statement. This tells the Java compiler +which particular class is being referenced by the classname. Effectively the +import statement creates a mapping from a name used in the Java source file and +a class in the global package namespace. +

+

+Mutant provides an import task to specify, in a manner similar to Java's import +statement, which components are being used. When a component is imported the +library is identified by its unique id. By default the component is imported +into the frame using the name it is known by within the library. When this would +conflict with a name that has already been imported, the import task allows the +component to be given a new name, or alias, by which it will be referenced. It +is also possible to import all the components in a library. The folowing example +shows the various methods by which the import task can be used to import +components. +

+
+ + + + + + + + + + + + + + + + +
+  <!-- import the runtool task from the com.foo.tools library -->
+  <import libraryId="com.foo.tools" name="runtool"/>
+
+  <!-- import the runtool task from the com.bar.tools library and
+       alias it since the runtool is already defined -->
+  <import libraryId="com.bar.tools" name="runtool" alias="runbartool"/>
+
+  <!-- import all of the tasks from the com.fubar.tools library -->
+  <import libraryId="com.fubar.tools"/>
+
+
+

+By using library identifiers, import operations are not tied to a particular +library location. The separation of the loading and importing into separate +phases allows environment-dependent locations to be specified as configuration +information and location independent importing to be specified in the build +file. This is similar to the case of Java imports. Java classes are imported by +their global name without needing to known where the classfile is that contains +that class. That information is provided externally in the CLASSPATH variable. +

+
+
+ + + +
+ + Library classpath management + +
+
+

+Many libraries will have dependencies on external jars. For example, a task +might make use of regular-expression libraries such as jakarta-regexp or a task +may provide a wrapper around some external tool. In these cases the task will +usually need to have the required classes available in the classloader from +which the task itself was loaded. It is possible to avoid these direct +dependencies using techniques such as reflection and explicitly loading the +required classes through additional classloaders but the code is often harder to +write and understand. +

+

It is not always possible or desirable to bundle the required classes in the +task's jar nor is it desirable that the system classpath contains the required +classes. In fact it is often preferable to run Mutant with an empty classpath. +Buildfiles which do not assume that the system classpath contains particular +classes are generally more portable. Mutant provides a task, +<libpath>, to allow additional paths to be assodicated with a +library. As with the loadlib task, the libpath task may be used to associate a +single file, all jars in a directory or remote jars with a library.

+
+ + + + + + + + + + + + + + + + +
+  <libpath libraryid="ant.ant1compat"
+           dir="/home/conor/jakarta-ant/lib/optional/"/>
+
+
+

The above example associates all the jars in +/home/conor/jakarta-ant/lib/optional/ with the library whose unique id is +ant.ant1compat. A path must be associated with a library before any components +are imported from the library. Mutant associates the paths with the library and +at the time a component is requested from the library, Mutant will form the +classloader that will be used. The additional paths are added to the definition +of the classloader. Once a component is loaded, further paths will not have any +effect. For this reason, and since the additonal paths are likely to be absolute +paths, the <libpath> task is normally used in Mutant's +configuration phase.

+
+
+ + + +
+ + Automatic Imports + +
+
+

+Mutant will automatically import all components of any library whose unique +identifier begins with "ant." when the ;library is loaded. This is +mainly a convenience to provide a minimum set of tasks with which to construct +build files. +

+
+
+
+
+ + + +
+ + Includes + +
+
+

Mutant provides a mechanism for including build file fragments into a build +file. This following example illustrates how this works

+
+ + + + + + + + + + + + + + + + +
+build.ant
+==========
+<project default="main" xmlns:ant="http://jakarta.apache.org/ant">
+  <ant:include fragment="fragment.ant"/>
+</project>
+
+fragment.ant
+============
+<fragment>
+  <target name="main">
+    <echo message="main target"/>
+  </target>
+</fragment>
+
+
+

The include mechanism can be used to include a complete project file or as +shown in the example, a fragment. When including a project, any attributes on +the included <project> element are ignored and the contents +of the project inserted into the including project. In all cases the included +files must be a well formed XML file containing a root element.

+
+ + + + + + + + + + + + + + + + +
+ + +

This area of Mutant is subject to change.

+ +

At present include elements are processed at parse-time. As such they can +only occur at the top-level of the build file. They cannot occur in a target. +The use of the namespace to qualify the include element is intended to convey +the fact that this is not part of the build structure.

+ +

An alternative approach would be to define include as a regular task. When an +include is processed, the top-level tasks of the included project would be +executed immediately and the targets added to the current project +structure.

. + + +
+
+
+
+ + + +
+ + Project References + +
+
+ + + +
+ + Creating references + +
+
+

+Mutant allows build file writers to reference properties and targets in other +projects by creating a project reference. Project references are introduced +using the ref task. +

+
+ + + + + + + + + + + + + + + + +
+  <!-- create a reference to the main build -->
+  <ref project="main.xml" name="main"/>
+
+  <ref project="test.xml" name="test">
+    <property name=build.dir" value="build/test"/>
+  </ref>
+
+
+

+The above example creates two project references - one to the build in main.xml +and one to the build in test.xml. When a reference is created, it must be given +a label. This label will be used to refer to items within the referenced +project (see below). Note that the ref task is a regular task and the reference +is only created when the ref task is executed. A ref task may be placed at the +top level of a build to effectively create static references. Alternatively a +reference may be created dynamically by putting the ref task in a target. +

+
+
+ + + +
+ + Referencing project items + +
+
+

+The label given to a project reference is used when accessing items within the +project. So, to access the build.dir property in the project referenced by the +main label, you would use main:build.dir. Similarly the compile target would be +referred to as main:compile. Since the referenced projects may also create their +own project references, labels may be concatenated to access items at arbitrary +depths. For example, if main.xml referenced another project under the label +"sub", a property debug could be referenced as main:sub:debug. The +following example shows various items in the referenced project being used. +

+
+ + + + + + + + + + + + + + + + +
+  <!-- Specify the build.dir in the main project prior to the reference
+       being created -->
+  <property name="main:build.dir" value="build/main"/>
+
+  <!-- create the reference to the main build -->
+  <ref project="main.xml" name="main"/>
+
+  <!-- create the reference to the test build -->
+  <ref project="test.xml" name="test">
+    <property name="build.dir" value="build/test"/>
+  </ref>
+
+  <!-- our main target calls the fubar target in the main build -->
+  <target name="main">
+    <antcall target="main:fubar"/>
+  </target>
+
+  <!-- Our alt target depends on the fubar target in the main build -->
+  <target name="alt" depends="main:fubar">
+    <echo message="main's debug flag is ${main:debug}"/>
+  </target>
+
+
+

+When a project is referenced, the top level tasks of the referenced project are +run to allow the project to initialize itself. Mutant allows the referring +build to set a property in a referenced project before the reference is +created. When the reference is eventually created these properties are set +before initialization occurs. In normal Ant fashion, these overriding +properties take precedence. In particular properties in the referenced projects +may be set from the command line as this example shows +

+
+ + + + + + + + + + + + + + + + +
+  mutant -Dmain:build.dir=temp
+
+
+

+The example above shows a target in the referenced project being used as a +dependency and also as a target in an antcall. Since refs are dynamic, Mutant +will only evaluate such dependencies when required. If the alt target were +never to be run, the dependency on main:fubar would never be checked. +

+

+The import task allows components defined in a referenced project to be brought +into the main build. For example, the following will bring the definition of +tool from the test project in the build. The imported component may also be +aliased to a new name. +

+
+ + + + + + + + + + + + + + + + +
+  <!-- import a task definition from another project -->
+  <import ref="test:tool"/>
+
+
+
+
+
+
+ + + +
+ + Configuration + +
+
+

+As discussed above Mutant provides a number of tasks to manage libraries and +it is appropriate to run many of these tasks as part of a user or system-wide +configuration rather than incorporating them into the build file. Mutant +provides a configuration system to support running these tasks at an appropriate +time. A Mutant configuration file looks as follows +

+
+ + + + + + + + + + + + + + + + +
+<antconfig allow-unset-properties="true">
+  <global-tasks>
+    <libpath libraryid="ant.ant1compat"
+             file="/home/conor/dev/jakarta-ant/lib/optional/"/>
+  </global-tasks>
+  <project-tasks>
+    <import libraryid="antopt.monitor"/>
+  </project-tasks>
+</antconfig>
+
+
+

+The antconfig element is the root element of the configuration file. It supports +three attributes +

+ + + + + + + + + + + + + +
+ + allow-unset-properties + + + + controls whether Mutant will fail a build which +refers to a property which has not been set. This defaults to the Ant1 behaviour +(true) + +
+ + allow-remote-library + + + + controls whether Mutant uses components defined in remote libraries + +
+ + allow-remote-project + + + + controls whether Mutant can run a project or reference a project which is +located remotely. + +
+

+The configuration provides two collections of configuration tasks, global-tasks +and project-tasks. Global-tasks are run once and are run in the context of the +main project - i.e. the build file identified on the command line (defaults to +build.xml/build.ant), whilst project-tasks are run as part of the initialization +of every project including referenced projects and antcall projects. Looking at +the above example, the global-tasks associate a path with the ant.ant1compat +library while the per-project tasks import the antopt.monitor library into every +project that Mutant processes. +

+

+The tasks that can be run in the configuration phase are regular tasks but not +all tasks are automatically available. This is the difference between the +syslibs and antlibs directories. The global tasks are run after the syslibs +libraries have been loaded but prior to the antlibs libraries being loaded. The +syslibs library tasks are therefore available in the configuration phase. This +arrangement is to allow the configuration tasks to setup library paths for the +libraries contained in the antlibs directory, especially libraries in the Ant +namespace which are automatically imported at the time they are loaded. +

+

+If it is required to use tasks from libraries installed in the antlibs +directory, the configuration tasks may explicitly load the library and import +the required tasks. The following example shows the loading and use of the echo +task in the configuration tasks. Note that the ant.home property has been set at +the time the configuration tasks are started. +

+
+ + + + + + + + + + + + + + + + +
+<antconfig allow-unset-properties="true">
+  <global-tasks>
+    <loadlib file="${ant.home}/lib/antlibs/ant1compat.jar" importall="true"/>
+    <echo message="Starting the build"/>
+  </global-tasks>
+  <project-tasks>
+    <echo message="Starting new project"/>
+  </project-tasks>
+</antconfig>
+
+
+

+When Mutant starts up it will load configurations from two locations - The file +.ant/conf/antconfig.xml in the user's home directory and the file +conf/antconfig.xml in the Mutant home directory. In addition, config files can +be specified on the command line using a -config argument. This allows project +specific configurations to be used. +

+
+
+ + + +
+ + Targetless builds + +
+
+

+Mutant allows any task or datatype to be placed outside of a target. All such +components are processed when the project is initialized and before any targets +are processed. In fact Mutant does not require that a project contain any +targets. In this case the only operations performed are the top level tasks at +project initialization. The following shows a simple example +

+
+ + + + + + + + + + + + + + + + +
+<project>
+  <echo message="Welcome to Mutant"/>
+</project>
+
+
+
+
+ + + +
+ + Extensibility + +
+
+

+Normally when a task supports a nested element, Ant automatically determines the +type of the nested element and creates an instance of this type. This instance is +then configured and passed to the task. Mutant extends this scheme by allowing +a build file writer to specify the type of nested element to use rather than +relying on the core to determine it. Mutant will process attributes and further +nested elements based on the specified type. For example: +

+
+ + + + + + + + + + + + + + + + +
+    <copy todir="dest">
+      <fileset xsi:type="classfileset" dir="../../bin/ant1compat/">
+        <root classname="org.apache.tools.ant.Project"/>
+      </fileset>
+    </copy>
+
+
+

+In this example the nested element is actually a classfileset which supports the +<root> nested element. The actual type is specified using the notation from +XML Schema. Mutant predclares the XML Schema namespace under the xsi prefix. You +may explicitly declare this in the build file's XML and use a different prefix +if you wish. For example, this is equivalent to the above +

+
+ + + + + + + + + + + + + + + + +
+<?xml version="1.0"?>
+<project xmlns:schema="http://www.w3.org/2001/XMLSchema-instance"
+         name="test" default="main">
+  <target name="main">
+    <delete dir="dest"/>
+    <mkdir dir="dest"/>
+    <copy todir="dest">
+      <fileset schema:type="classfileset" dir="../../bin/ant1compat/">
+        <root classname="org.apache.tools.ant.Project"/>
+      </fileset>
+    </copy>
+  </target>
+</project>
+
+
+
+
+ + + +
+ + Default build file + +
+
+

In Ant1, the default build file name is build.xml. In Mutant, the default +build file is build.ant. If build.xnt cannot be found, Mutant will then look for +build.xml. This allows you to support both Ant1 and Ant2 users. The build.xml +file can contain an Ant1 build file. The build.ant file can include or reference +this build and make use of Mutant's capabilities such as library management, +library path settings, etc. +

+
+
+
+
+
+
+ Copyright © 2002, Apache Software Foundation +
+
+ + + + + + + diff --git a/proposal/mutant/docs/goals.html b/proposal/mutant/docs/goals.html new file mode 100644 index 000000000..ac6c9d429 --- /dev/null +++ b/proposal/mutant/docs/goals.html @@ -0,0 +1,867 @@ + + + + + + + + + + + + + + Mutant Proposal - Mutant Goals + + + + + + + + +
+ +
+ + + + + + + + + + + + +
+
+
+

Mutant Proposal

+ +
+ + + +
+ + Goals + +
+
+

+This page describes the key goals that have shaped the development of +Mutant. +

+

+The first section identifies a set of issues with Ant1 that have cropped up as +Ant1 has evolved. The design implications of each issue are then summarized as a +Mutant requirement. I do not want to suggest that these problems are unsolvable +within the Ant1 design. Already I believe we have seen the Ant2 proposals +influencing people trying to extend Ant1. These issues may be solvable, although at +the risk of backward compatability impacts or further complication of the Ant1 +codebase. +

+

+The second section covers a set of additional requirements that have emerged as +the whole concept of Ant2 has developed. Many of these came from the discussions +on the Ant-Dev mailing list. +

+

+The realisation of these requirements as they impact a user is on the +next page. Th implications for task developers and +Ant developers are discussed in the following sections. +

+
+
+ + + +
+ + Ant1 Issues + +
+
+ + + +
+ + Unrestricted core access + +
+
+

+The interface between the Ant core and tasks is not controlled. It +allows tasks almost complete access to the internal data structures of the +core. This is poor encapsulation. Whilst most tasks do not need and do not +use this access, its existence nonetheless prevents changes being made to +the core without raising concerns about impacting backward compatability. +

+

+The uncontrolled nature of the task-core interface also makes it difficult +to reuse tasks and types in a different context without almost completely +duplicating the Ant core +

+
+ + + + + + + + + + + + + + + + +
+ +

+A tightly defined interface between the core and the components (tasks and +types) will allow the core implementation to be changed without the risk +of impacting tasks. It will also allow components to be reused in other +contexts. +

+ +
+
+
+
+ + + +
+ + Lack of embedding support + +
+
+

+Ant1 does not provide strong support for embedding Ant in other systems, +particularly a GUI or IDE. The development of Antidote highlighted this +difficultly. Antidote was forced to perform its own XML parsing so it could +build its own model of the build. There is no communication medium for a GUI to +communicate with the core. Without this capability any GUI will be limited to +simply editing the XML representation of the build. +

+
+ + + + + + + + + + + + + + + + +
+ +

+The definition of a project model, a Java-based object-model of a build +description would decouple Ant from the XML representation. This allows +other representations to be used. Such an object model also forms the basis +for communications between systems which want to embed Ant. An IDE could +manipulate this project object model directly and pass to the core for +processing without needing to convert to and from an external +representations such as XML. +

+ +
+
+
+
+ + + +
+ + Configuration done at Parse-Time + +
+
+

+The original implementation of Ant1 performed all task configuration at the +time the XML description of the build was parsed (parse-time). This approach +could not handle dynamically created tasks very well since in some +instances the type of the task to be configured was not known at parse-time. +This limitation was overcome with the introduction of the UnknownElement and +RuntimeConfigurable classes. While these work well, they are confusing and at +times surprising to most Ant developers. Also some operations still occur at +parse-time, notably creation of nested elements of known types. This could be +overcome by going to a fully dynamic model but the fear of backward +incompatability constrains this change from occuring. +

+
+ + + + + + + + + + + + + + + + +
+ +

+Execution-time configuration of tasks allows for the latest information to be +used for configuration. It is also necessary to support the concept of the +project model. The project model cannot contain execution-time information as it +does in Ant1 +

+ +

+The decoupling of the parsing and exection phases, communicating through the +medium of the project model will allow the core to be modularized. The parsing +and execution phases can be separated and one replaced without impacting the +other. +

+ +
+
+
+
+ + + +
+ + Multiple execution + +
+
+

+In Ant1, a task, once configured, may be used more than once - i.e. its +execute method may be called more than once. This occurs when the Ant +command line specifies the evaluation of two targets. If those targets have +overlapping dependencies, the tasks in those overlapping dependencies will +be executed twice. This arrangement requires task writers to preserve the +state configured by Ant during the execution of the task so that the next +execution has the correct configuration. +

+

+Many task writers are not aware of this requirement. Frequently the task's +state is changed during the execution method, which can lead to mysterious +falures during subsequent executions. This need to preserve the configuration +state makes writing tasks much harder. +

+
+ + + + + + + + + + + + + + + + +
+ +

+Once a task is configured, it should be executed once. If the execution of +multiple targets is required, a new task instance should be created and +configured from the same project model. If reuse of task instances is desired +each instance must be reinitialized and reconfigured before use. +

+ +
+
+
+
+ + + +
+ + No automatic deployment of tasks + +
+
+

+Ant1 has a set of well-known tasks (and types). A well-known task is one +for which a mapping between the taskname and its implementing class is +predefined in Ant. This mapping is provided by the two defaults.properties +files in Ant's code. These well-known tasks do not need to be taskdef'd to +make them available in a build file. Conversely tasks which are not in this +list need to be explicitly taskdef'd. +

+

+Note that this distinction is not the same as the core/optional +distinction found in Ant1. An Ant1 core task is notionally supported by Ant +without requiring any additional external libraries - it just requires the +classes available in the 1.1 JDK, in Ant and in the libraries Ant uses such +as the XML parser. An optional task is a task which requires JDK 1.2+ +features or the support of an external library, such as jakarta-regexp. +

+

+The problem with this system is that there is no namespace management. If a +new task is added to Ant, it may invalidate buildfiles which are already +using that taskname via a taskdef. Actually the taskdef may continue to work or +it may not - it will depend on the nested elements that the task definitions +support (see above discussion of regarding cofiguration at parse-time) +

+
+ + + + + + + + + + + + + + + + +
+ +

+Tasks need to be deployed in libraries by either placing them in well known +directories of an Ant install or by telling Ant where to look for them. Removing +the central management of defined task names allows tasks libraries to be +developed and maintained independently of Ant much more easily. +

+ +

+Once centralised management of the task namespace is removed, there is, +however, the possibility of name collision. A mechanism is required to allow a +build file writer to select which particular tasks are assigned to which +tasknames. +

+ +
+
+
+
+ + + +
+ + Top level tasks + +
+
+

+In Ant1 certain tasks may appear outside of any target. This is implemented as a +set of hardcoded conditions in the XML parsing phase. The execution and +configuration of these tasks does not involve the use of RuntimeConfigurable and +UnknownElement. +

+

+This hardcoding is not very inituitive. It is confusing to users who do not +know why only some tasks may be run outside of a target. Also as the list of +tasks that may be useful as a top-level task grows, further special cases must +be added to the code making the code harder to maintain. +

+
+ + + + + + + + + + + + + + + + +
+ +

+The number of special names should be kept to a minimum. Special cases should +be avoided as they are not inituitive. +

+ +
+
+
+
+ + + +
+ + Build file inclusion is cumbersome + +
+
+

+In Ant1, the inclusion of a set of build file definitions or targets is achieved +through the use of XML entities. This is just cumbersome. +

+
+ + + + + + + + + + + + + + + + +
+ +

+A simplified include mechanism is required to replace the entity based +inclusion of Ant1. +

+ +
+
+
+
+ + + +
+ + Classpath management + +
+
+

+Probably the greatest issue facing Ant1 today involves the management of the +classpath and the associated visibility of classes. Most optional tasks in Ant1 +require the supporting classes for the task to be available on the system +classpath. For example, the JUnit task is only usable if the JUnit jar is on +the classpath. If it is not, Ant will complain about being unable to create the +junit task. +

+

+The usual solution when a user runs into this problem is to put the required jar +into the ANT_HOME/lib directory. This just adds the required jar to the system +classpath prior to starting Ant albeit without requiring the user to explicitly +set the classpath. +

+

+There are a number of issues with this approach. The classes on the +classpath share the same classloader as Ant's classes and Ant's support +libraries - particularly the XML parser. If a task wishes to use a specific XML +parser, it may conflict with Ant's own parser. If two tasks require different +versions of a supporting jar, these will conflict. +

+

+Many tasks make use of factory objects (dynamic class instantiation, dynamic +resource loading, etc). When the factory is in the system classpath it will not +be able to load resources available in a taskdef'd task's custom classpath due +to the delegating nature of classloaders. Such errors can be very confusing to +users. More recent code is likely to attempt use of a context classloader but +this is not set by Ant1 currently. +

+
+ + + + + + + + + + + + + + + + +
+ +

+Do not require jars to be added to ANT_HOME/lib to enable tasks. Allow users to +specify the location of support jars on a per-library basis. +

+ +
+
+
+
+ + + +
+ + Extensibility + +
+
+

+The earliest versions Ant1 did not explicitly support any datatypes. The only +datatype, property, was actually created as a side-effect of running the +<property> task. If it were to be implemented today, property +would probably be known as a string datatype, perhaps associated with a +<load-properties> task. This is also the reason property +is one of those tasks which is allowed to exist outside of a target. +

+

As Ant1 evolved new types such as <path> and +<fileset> were added. The concept of datatypes has continued +to evolve to the point where users can now define new datatypes. It would be +expected that in addition to new types there will be many sub-types created, +such as new types of fileset. Ant1, however, does not strongly support such type +extensibility. When a subtype is created by extending an existing type, Ant1 +requires it to be either used by reference or all tasks which accept the base +type need to be modified to support the new type. Use by reference is not always +possible. It will depend on whether the base type has been coded to support +references.

+
+ + + + + + + + + + + + + + + + +
+ +

+Support polymorphic behaviour, allowing a build file to pass a subtype to a +task which is defined to accept the base type. Allow task interfaces to be +defined in terms of interfaces. +

+ +

+Move reference processing to the core to make it more regular removing the +burden of type developers to explicitly support references. +

+ +
+
+
+
+ + + +
+ + Project object does too much + +
+
+

+In Ant1 the Project object takes on too many roles including all of the +following: +

+
    +
  • Holds the project model built when parsing the build file
  • +
  • Holds the run-time state of the build through the properties and current +task definitions
  • +
  • Provides context for task execution. All tasks have a reference to their +project instance and use it to access core functions
  • +
  • Provides the implementation of common task operations
  • +
  • Build event management
  • +
  • Message logging
  • +
  • Global filter definitions
  • +
  • Java Version
  • +
  • Property replacement
  • +
  • Message Levels
  • +
  • Utility functions such as boolean conversion and path translation
  • +
  • Integration point for embedding Ant
  • +
+

As a class, Project is not cohesive. Reuse of the Ant core functionality is +difficulty as all of these concerns bring in many other support classes. +

+
+ + + + + + + + + + + + + + + + +
+ +

+Separate the various roles of Project into more cohesive classes. +

+ +
+
+
+
+
+
+ + + +
+ + Other Goals + +
+
+

+In addition to the issues which arise from Ant1 limitations, there are a number +of requirements which have emerged in the mailing list discussions about Ant2. +This isn't a complete list - just the ones I picked up for Mutant. +

+ + + +
+ + Limited project reuse + +
+
+

In Ant1 the only way to reuse build file definitions is to use the +<ant> task. While useful, it is relatively coarse-grained. It +can also be tedious if you are trying to extend an existing project definition - +that is, adding new targets while retaining a user's ability to access the +existing targets.

+

+In addition to the extension of projects, it should be possible to compose +projects creating dependencies between the targets of the different projects, +and to access the data and definitions of one project by a controlling project +

+
+ + + + + + + + + + + + + + + + +
+ +

+Allow a project to extend and control other projects +

+ +
+
+
+
+ + + +
+ + Ant1 Compatibility - Zero Friction + +
+
+

+While it has always been accepted that there will be come backward compatibility +breaks in moving from Ant1 to Ant2, these should be minimized. If the changeover +from Ant1 to Ant2 is difficult, it may never happen. On the other hand, the +openness of the Ant1 interface means that some tasks will not work as expected - +the most difficult being the <script> task. +

+
+ + + + + + + + + + + + + + + + +
+ +

+Achieve a practical level of compatability without degrading the integrity of +the core's interfaces. A practical level of compatability is intentionally a +vague measure but it would require the majority of projects in Gump to be built +without noticeable differences from Ant1 +

+ +
+
+
+
+ + + +
+ + XML Configuration + +
+
+

+In Ant1 configuration of Ant is achieved either through the execution of OS +dependent scripts by the launcher scripts or though properties files which have +the limited capability to set properties. +

+
+ + + + + + + + + + + + + + + + +
+ +

+Provide an XML based configuration system with rich capabilities to configure +the operation of Ant. +

+ +
+
+
+
+ + + +
+ + Aspects + +
+
+

+In Ant1 there are many things which are common to a group of tasks but adding +the capability to each task is repetitive and tedious. An example would be the +failonerror attribute which controls whether a task will cause the build to stop +when it fails. This started on just one task but has since been added to many +other tasks as users want more fine control over when their builds stop. Aspects +have been discussed as a mechanism for providing a single implementation of a +concept or control that can then be applied to tasks independently. +

+
+ + + + + + + + + + + + + + + + +
+ +

+Investigate the use of an Aspect approach to provide common functionality +across tasks with a single implementation +

+ +
+
+
+
+
+
+
+
+
+
+ Copyright © 2002, Apache Software Foundation +
+
+ + + + + + + diff --git a/proposal/mutant/docs/index.html b/proposal/mutant/docs/index.html new file mode 100644 index 000000000..51f1714a9 --- /dev/null +++ b/proposal/mutant/docs/index.html @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + Mutant Proposal - Mutant Introduction + + + + + + + + +
+ +
+ + + + + + + + + + + + +
+
+
+

Mutant Proposal

+ +
+ + + +
+ + Introduction + +
+
+

+These pages describe the design and implementation of Mutant. +

+

+For some time, there has been the concept of Ant 2.0. a rearchitecting of +Ant designed to address the shortcomings in the design of Ant 1.x, while +drawing the experience gained in that development. This rearchitecting +would most likely be accompanied by at least some break in backward +compatability. Over time Ant 2.0 has come to be known as Ant2 and the current +Ant codebase is generally known as Ant1. +

+

+Mutant is my proposal, a revolution, for Ant2. Actually, I consider it more +an evolution of the design and implementation used for Ant1, but in Jakarta +parlance, being a separate codebase, it is termed a revolution. +

+

+There is no special significance in the name Mutant. I chose it because, as +a word, it is an extension of the word Ant and it also signifies a change +from the previous generation +

+
+
+ + + +
+ + Other Proposals + +
+
+

+Mutant is not the only proposed revolution for Ant2. Peter Donald has +developed another known as +Myrmidon +which presents a different view of how Ant2 could be realized. Other +people hold the view that Ant1 can continue to evolve and that there +is no need for rearchitecture of its codebase. I recommend you +investigate all these points of view. +

+

+As I write this, no decision has been taken as to which codebase will be +adopted for Ant2. It may not be Mutant and it could even be some entirely +new proposal. These pages do not compare and contrast Mutant with these +other proposals or points of view, at least not explicitly. They are just +intended to describe how Mutant is designed and implemented and why it is the +way it is. +

+
+
+ + + +
+ + Getting Started + +
+
+
+ + + + + + + + + + + + + + + + +
+ +

Caution

+ +

+Mutant is not even an alpha release. While it is relatively stable, it is +subject to change. There are no backward compatability guarantees for any of +the classes, interfaces, build files, configuration, launch scripts, etc that +Mutant provides. +

+ +

In particular, some features in Mutant are experimental and may not, in the +long run, prove to be worthwhile.

+ + +
+
+

+Start now by looking at the key requirements which have +shaped the design of Mutant. +

+
+

Conor MacNeill

+
+
+
+
+
+
+
+ Copyright © 2002, Apache Software Foundation +
+
+ + + + + + + diff --git a/proposal/mutant/docs/intro.html b/proposal/mutant/docs/intro.html new file mode 100644 index 000000000..2284183e3 --- /dev/null +++ b/proposal/mutant/docs/intro.html @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + Mutant Proposal - Mutant Introduction + + + + + + + + +
+ +
+ + + + + + + + + + + + +
+
+
+

Mutant Proposal

+ +
+ + + +
+ + Introduction + +
+
+

+These pages describe the design and implementation of mutant. +

+

+For some time, there has been the concept of Ant 2.0. a rearchitecting of +Ant designed to address the shortcomings in the design of Ant 1.x while +drawing the experience gained in that development. This rearchitecting +would most likely be accompanied by at least some break in backward +compatability. Indeed this fact was recognized by Duncan, the original +author of Ant when he proposed his AntEater revolution. Over time Ant 2.0 +has come to be known as Ant2 and the current Ant codebase is generally +known as Ant1. +

+

+Mutant is my proposal, a revolution, for Ant2. Actually, I consider it more +an evolution of the design and implementation used for Ant1, but in Jakarta +parlance, being a separate codebase, it is termed a revolution. +

+

+There is no special significance in the name mutant. I chose it because, as +a word, it is an extension of the word ant and it also signifies a change +from the previos generation +

+
+
+ + + +
+ + Other Proposals + +
+
+

+Mutant is not the only proposed revolution for Ant2. Peter Donald, another +Ant committer, has developed another proposal known as Myrmidon, which you +should also investigate if you are interested in a different view of how +Ant2 should be realized. Other people hold the view that there is no need +for any rearchitecting and the Ant1 codebase can continue to evolve. +

+

+As I write this, no decision has been taken as to which codebase will be +adopted for Ant2. It may not be mutant or it could be some entirely new +proposal. This document does not compare and contrast mutant with these +other proposals or points of view, at least not explicitly. It is just +intended to describe and highlight how mutant is designed and implemented. +

+
+
+
+
+
+
+ Copyright © 2000-2002, Apache Software Foundation +
+
+ + + + + + + diff --git a/proposal/mutant/xdocs/design.xml b/proposal/mutant/xdocs/design.xml new file mode 100644 index 000000000..a5c3de748 --- /dev/null +++ b/proposal/mutant/xdocs/design.xml @@ -0,0 +1,16 @@ + + + Conor MacNeill + Developers + + + +
+

+This page will describe the design of Mutant's core. +

+
+ + +
+ diff --git a/proposal/mutant/xdocs/developers.xml b/proposal/mutant/xdocs/developers.xml new file mode 100644 index 000000000..7d843ce81 --- /dev/null +++ b/proposal/mutant/xdocs/developers.xml @@ -0,0 +1,16 @@ + + + Conor MacNeill + Developers + + + +
+

+This page will describe the operation of Mutant from a task developers perspective. +

+
+ + +
+ diff --git a/proposal/mutant/xdocs/features.xml b/proposal/mutant/xdocs/features.xml new file mode 100644 index 000000000..1891b1aa6 --- /dev/null +++ b/proposal/mutant/xdocs/features.xml @@ -0,0 +1,599 @@ + + + Conor MacNeill + Mutant Features + + + +
+ +

+This page describes the major features in Mutant which are significantly +different from those of Ant1. These are covered from a user perspective. Other +pages describe the differences from the perspectives of a task developer and an +Ant core developer. +

+
+ +
+

+When Mutant is installed, the most immediately obvious difference will be in the +directory layout, particularly the lib directory. Where Ant1's lib directory +contained ant.jar, optional.jar and the bundled XML jars, Mutant's lib directory +contain a number of subdirectories. +

+ +

+In the root directory, there are a number of jars. These jars are the startup +jars +

+ + + + + + + + + + + + + +
init.jara set of low level utility routines required at startup
start.jarthe Mutant launcher class
ant.jarold Ant1 entry point
+ +

+The subdirectories have the following functions +

+ + + + + + + + + + + + + + + + + + + + + +
parserThe XML parser jars. This is not available to task libraries unless +they explicitly indicate that it is required.
antcoreMutant's core classes. These classes are not available to +tasks.
commonclasses which are available to both the core and all task +libraries.
syslibs/antlibsTask libraries. The distinction between the two is +discussed below.
frontendAnt Frontends. Different frontends may be plugged in by placing +jars here.
+ +

+The directory a jar is in will control the visibility of the jar's classes and +resources. This is closely related to the classloader hiearchy used by +Mutant. +

+ +
+ +
+

+Mutant supports the concept of Ant Libraries. These are collections of +components (tasks and types) and their supporting classes packaged into a +Jar. In Mutant each library has a globally unique identifier. This identifier +uses the same conventions as Java package naming - i.e. a reverse DNS name. +

+ +

The jar does not need to be exclusively for Ant. For example, it may be the +jar for a tool which wishes to provide some Ant tasks for using the tool. It +could be the main jar of an appication server that bundles Ant tasks for +deployment. The jar does not even need to be installed in Mutant's antlib +directory - Mutant can be configured to look in jars in other locations for Ant +Libraries.

+ + + +

+Whatever the jar contains and wherever it is located, Mutant looks for an XML +based descriptor in the jar at META-INF/antlib.xml. This XML file describes the +components in the jar that will be available to Mutant. +

+ +

+Here is an example of the descriptor. +

+ + + + + + + + + + + + + +]]> + +

+As a user you generally won't need to worry about this decriptor. The library +developer will have developed it to describe their library. Mutant uses the +descriptor to understand what Ant related components the library provides. +

+
+ + +

+Library management in Mutant is split into two phases - a loading phase and an +import phase. The loading phase is where Mutant loads the antlib.xml descriptor +from the library. After loading, Mutant knows where the library is located and +what components it provides. In general Mutant will not make the components +available to build scripts automatically. A build script needs to notify Mutant +what components it is using from each library. This is known as importing. +

+ +

Mutant loads libraries from two locations within the Mutant directory +structure when Mutant starts up - the lib/syslibs and lib/antlibs directories. +The distinction between these two locations is explained in the configuration +discussion below. All jars in these directories will be search for library +descriptors. All libraries providing descriptors will be available for importing +into builds

+ +

In addition to the automatically loaded libraries, it is possible to +explicitly request additional libraries to be loaded using the +<loadlib> task. Individual libraries may be loaded or a set +of libraries loaded from a directory. Libraries may also be loaded from remote +locations by specifying a URL. The loadlib task can request that all components +in the loaded library also be imported at the time of loading. Examples of the +loadlib task follow

+ + + + + + + + + +]]> + +

+In general the loading of libraries from absolute locations would be a +configuration task. These would be specified in the Mutant configuration file +and would not be used in a build file. The loading of project libraries from +relative locations may be something that you would see in a build file. +

+ +
+ + +

+Mutant is designed to allow tasks to be defined simply by dropping a jar in a +directory or configuring Mutant to look in particular places for jars. This will +allow tasks and types developed by many different developers to be used. With +many developers developing tasks, however, inevitably some tasks will end up +with the same name. +

+ +

+This is very similar to the situation faced by Java with Java class names. +Many Java classes have the same name. When a Java programmer uses a class they +must import that class with an import statement. This tells the Java compiler +which particular class is being referenced by the classname. Effectively the +import statement creates a mapping from a name used in the Java source file and +a class in the global package namespace. +

+ +

+Mutant provides an import task to specify, in a manner similar to Java's import +statement, which components are being used. When a component is imported the +library is identified by its unique id. By default the component is imported +into the frame using the name it is known by within the library. When this would +conflict with a name that has already been imported, the import task allows the +component to be given a new name, or alias, by which it will be referenced. It +is also possible to import all the components in a library. The folowing example +shows the various methods by which the import task can be used to import +components. +

+ + + + + + + + + +]]> + +

+By using library identifiers, import operations are not tied to a particular +library location. The separation of the loading and importing into separate +phases allows environment-dependent locations to be specified as configuration +information and location independent importing to be specified in the build +file. This is similar to the case of Java imports. Java classes are imported by +their global name without needing to known where the classfile is that contains +that class. That information is provided externally in the CLASSPATH variable. +

+ +
+ + +

+Many libraries will have dependencies on external jars. For example, a task +might make use of regular-expression libraries such as jakarta-regexp or a task +may provide a wrapper around some external tool. In these cases the task will +usually need to have the required classes available in the classloader from +which the task itself was loaded. It is possible to avoid these direct +dependencies using techniques such as reflection and explicitly loading the +required classes through additional classloaders but the code is often harder to +write and understand. +

+ +

It is not always possible or desirable to bundle the required classes in the +task's jar nor is it desirable that the system classpath contains the required +classes. In fact it is often preferable to run Mutant with an empty classpath. +Buildfiles which do not assume that the system classpath contains particular +classes are generally more portable. Mutant provides a task, +<libpath>, to allow additional paths to be assodicated with a +library. As with the loadlib task, the libpath task may be used to associate a +single file, all jars in a directory or remote jars with a library.

+ + +]]> + +

The above example associates all the jars in +/home/conor/jakarta-ant/lib/optional/ with the library whose unique id is +ant.ant1compat. A path must be associated with a library before any components +are imported from the library. Mutant associates the paths with the library and +at the time a component is requested from the library, Mutant will form the +classloader that will be used. The additional paths are added to the definition +of the classloader. Once a component is loaded, further paths will not have any +effect. For this reason, and since the additonal paths are likely to be absolute +paths, the <libpath> task is normally used in Mutant's +configuration phase.

+ +
+ + +

+Mutant will automatically import all components of any library whose unique +identifier begins with "ant." when the ;library is loaded. This is +mainly a convenience to provide a minimum set of tasks with which to construct +build files. +

+
+
+ +
+ +

Mutant provides a mechanism for including build file fragments into a build +file. This following example illustrates how this works

+ + + + + +fragment.ant +============ + + + + + +]]> + +

The include mechanism can be used to include a complete project file or as +shown in the example, a fragment. When including a project, any attributes on +the included <project> element are ignored and the contents +of the project inserted into the including project. In all cases the included +files must be a well formed XML file containing a root element.

+ + + +

This area of Mutant is subject to change.

+ +

At present include elements are processed at parse-time. As such they can +only occur at the top-level of the build file. They cannot occur in a target. +The use of the namespace to qualify the include element is intended to convey +the fact that this is not part of the build structure.

+ +

An alternative approach would be to define include as a regular task. When an +include is processed, the top-level tasks of the included project would be +executed immediately and the targets added to the current project +structure.

. + +
+ +
+ +
+ + +

+Mutant allows build file writers to reference properties and targets in other +projects by creating a project reference. Project references are introduced +using the ref task. +

+ + + + + + + +]]> + +

+The above example creates two project references - one to the build in main.xml +and one to the build in test.xml. When a reference is created, it must be given +a label. This label will be used to refer to items within the referenced +project (see below). Note that the ref task is a regular task and the reference +is only created when the ref task is executed. A ref task may be placed at the +top level of a build to effectively create static references. Alternatively a +reference may be created dynamically by putting the ref task in a target. +

+
+ + +

+The label given to a project reference is used when accessing items within the +project. So, to access the build.dir property in the project referenced by the +main label, you would use main:build.dir. Similarly the compile target would be +referred to as main:compile. Since the referenced projects may also create their +own project references, labels may be concatenated to access items at arbitrary +depths. For example, if main.xml referenced another project under the label +"sub", a property debug could be referenced as main:sub:debug. The +following example shows various items in the referenced project being used. +

+ + + + + + + + + + + + + + + + + + + + + +]]> + +

+When a project is referenced, the top level tasks of the referenced project are +run to allow the project to initialize itself. Mutant allows the referring +build to set a property in a referenced project before the reference is +created. When the reference is eventually created these properties are set +before initialization occurs. In normal Ant fashion, these overriding +properties take precedence. In particular properties in the referenced projects +may be set from the command line as this example shows +

+ + mutant -Dmain:build.dir=temp + + +

+The example above shows a target in the referenced project being used as a +dependency and also as a target in an antcall. Since refs are dynamic, Mutant +will only evaluate such dependencies when required. If the alt target were +never to be run, the dependency on main:fubar would never be checked. +

+ +

+The import task allows components defined in a referenced project to be brought +into the main build. For example, the following will bring the definition of +tool from the test project in the build. The imported component may also be +aliased to a new name. +

+ + + +]]> + +
+
+ +
+

+As discussed above Mutant provides a number of tasks to manage libraries and +it is appropriate to run many of these tasks as part of a user or system-wide +configuration rather than incorporating them into the build file. Mutant +provides a configuration system to support running these tasks at an appropriate +time. A Mutant configuration file looks as follows +

+ + + + + + + + + +]]> + +

+The antconfig element is the root element of the configuration file. It supports +three attributes +

+ + + + + + + + + + + + + +
allow-unset-propertiescontrols whether Mutant will fail a build which +refers to a property which has not been set. This defaults to the Ant1 behaviour +(true)
allow-remote-librarycontrols whether Mutant uses components defined in remote libraries
allow-remote-projectcontrols whether Mutant can run a project or reference a project which is +located remotely.
+ +

+The configuration provides two collections of configuration tasks, global-tasks +and project-tasks. Global-tasks are run once and are run in the context of the +main project - i.e. the build file identified on the command line (defaults to +build.xml/build.ant), whilst project-tasks are run as part of the initialization +of every project including referenced projects and antcall projects. Looking at +the above example, the global-tasks associate a path with the ant.ant1compat +library while the per-project tasks import the antopt.monitor library into every +project that Mutant processes. +

+ +

+The tasks that can be run in the configuration phase are regular tasks but not +all tasks are automatically available. This is the difference between the +syslibs and antlibs directories. The global tasks are run after the syslibs +libraries have been loaded but prior to the antlibs libraries being loaded. The +syslibs library tasks are therefore available in the configuration phase. This +arrangement is to allow the configuration tasks to setup library paths for the +libraries contained in the antlibs directory, especially libraries in the Ant +namespace which are automatically imported at the time they are loaded. +

+ +

+If it is required to use tasks from libraries installed in the antlibs +directory, the configuration tasks may explicitly load the library and import +the required tasks. The following example shows the loading and use of the echo +task in the configuration tasks. Note that the ant.home property has been set at +the time the configuration tasks are started. +

+ + + + + + + + + + +]]> + +

+When Mutant starts up it will load configurations from two locations - The file +.ant/conf/antconfig.xml in the user's home directory and the file +conf/antconfig.xml in the Mutant home directory. In addition, config files can +be specified on the command line using a -config argument. This allows project +specific configurations to be used. +

+ +
+ +
+ +

+Mutant allows any task or datatype to be placed outside of a target. All such +components are processed when the project is initialized and before any targets +are processed. In fact Mutant does not require that a project contain any +targets. In this case the only operations performed are the top level tasks at +project initialization. The following shows a simple example +

+ + + + +]]> + + +
+ +
+ +

+Normally when a task supports a nested element, Ant automatically determines the +type of the nested element and creates an instance of this type. This instance is +then configured and passed to the task. Mutant extends this scheme by allowing +a build file writer to specify the type of nested element to use rather than +relying on the core to determine it. Mutant will process attributes and further +nested elements based on the specified type. For example: +

+ + + + + + +]]> + +

+In this example the nested element is actually a classfileset which supports the +<root> nested element. The actual type is specified using the notation from +XML Schema. Mutant predclares the XML Schema namespace under the xsi prefix. You +may explicitly declare this in the build file's XML and use a different prefix +if you wish. For example, this is equivalent to the above +

+ + + + + + + + + + + + + +]]> + +
+ +
+ +

In Ant1, the default build file name is build.xml. In Mutant, the default +build file is build.ant. If build.xnt cannot be found, Mutant will then look for +build.xml. This allows you to support both Ant1 and Ant2 users. The build.xml +file can contain an Ant1 build file. The build.ant file can include or reference +this build and make use of Mutant's capabilities such as library management, +library path settings, etc. +

+ +
+ + +
diff --git a/proposal/mutant/xdocs/goals.xml b/proposal/mutant/xdocs/goals.xml new file mode 100644 index 000000000..9e8962d9d --- /dev/null +++ b/proposal/mutant/xdocs/goals.xml @@ -0,0 +1,426 @@ + + + Conor MacNeill + Mutant Goals + + + +
+

+This page describes the key goals that have shaped the development of +Mutant. +

+ +

+The first section identifies a set of issues with Ant1 that have cropped up as +Ant1 has evolved. The design implications of each issue are then summarized as a +Mutant requirement. I do not want to suggest that these problems are unsolvable +within the Ant1 design. Already I believe we have seen the Ant2 proposals +influencing people trying to extend Ant1. These issues may be solvable, although at +the risk of backward compatability impacts or further complication of the Ant1 +codebase. +

+ +

+The second section covers a set of additional requirements that have emerged as +the whole concept of Ant2 has developed. Many of these came from the discussions +on the Ant-Dev mailing list. +

+ +

+The realisation of these requirements as they impact a user is on the +next page. Th implications for task developers and +Ant developers are discussed in the following sections. +

+ +
+ +
+ +

+The interface between the Ant core and tasks is not controlled. It +allows tasks almost complete access to the internal data structures of the +core. This is poor encapsulation. Whilst most tasks do not need and do not +use this access, its existence nonetheless prevents changes being made to +the core without raising concerns about impacting backward compatability. +

+ +

+The uncontrolled nature of the task-core interface also makes it difficult +to reuse tasks and types in a different context without almost completely +duplicating the Ant core +

+ + +

+A tightly defined interface between the core and the components (tasks and +types) will allow the core implementation to be changed without the risk +of impacting tasks. It will also allow components to be reused in other +contexts. +

+
+ +
+ + +

+Ant1 does not provide strong support for embedding Ant in other systems, +particularly a GUI or IDE. The development of Antidote highlighted this +difficultly. Antidote was forced to perform its own XML parsing so it could +build its own model of the build. There is no communication medium for a GUI to +communicate with the core. Without this capability any GUI will be limited to +simply editing the XML representation of the build. +

+ + +

+The definition of a project model, a Java-based object-model of a build +description would decouple Ant from the XML representation. This allows +other representations to be used. Such an object model also forms the basis +for communications between systems which want to embed Ant. An IDE could +manipulate this project object model directly and pass to the core for +processing without needing to convert to and from an external +representations such as XML. +

+
+
+ + +

+The original implementation of Ant1 performed all task configuration at the +time the XML description of the build was parsed (parse-time). This approach +could not handle dynamically created tasks very well since in some +instances the type of the task to be configured was not known at parse-time. +This limitation was overcome with the introduction of the UnknownElement and +RuntimeConfigurable classes. While these work well, they are confusing and at +times surprising to most Ant developers. Also some operations still occur at +parse-time, notably creation of nested elements of known types. This could be +overcome by going to a fully dynamic model but the fear of backward +incompatability constrains this change from occuring. +

+ + +

+Execution-time configuration of tasks allows for the latest information to be +used for configuration. It is also necessary to support the concept of the +project model. The project model cannot contain execution-time information as it +does in Ant1 +

+ +

+The decoupling of the parsing and exection phases, communicating through the +medium of the project model will allow the core to be modularized. The parsing +and execution phases can be separated and one replaced without impacting the +other. +

+
+
+ + +

+In Ant1, a task, once configured, may be used more than once - i.e. its +execute method may be called more than once. This occurs when the Ant +command line specifies the evaluation of two targets. If those targets have +overlapping dependencies, the tasks in those overlapping dependencies will +be executed twice. This arrangement requires task writers to preserve the +state configured by Ant during the execution of the task so that the next +execution has the correct configuration. +

+ +

+Many task writers are not aware of this requirement. Frequently the task's +state is changed during the execution method, which can lead to mysterious +falures during subsequent executions. This need to preserve the configuration +state makes writing tasks much harder. +

+ + +

+Once a task is configured, it should be executed once. If the execution of +multiple targets is required, a new task instance should be created and +configured from the same project model. If reuse of task instances is desired +each instance must be reinitialized and reconfigured before use. +

+
+
+ + +

+Ant1 has a set of well-known tasks (and types). A well-known task is one +for which a mapping between the taskname and its implementing class is +predefined in Ant. This mapping is provided by the two defaults.properties +files in Ant's code. These well-known tasks do not need to be taskdef'd to +make them available in a build file. Conversely tasks which are not in this +list need to be explicitly taskdef'd. +

+ +

+Note that this distinction is not the same as the core/optional +distinction found in Ant1. An Ant1 core task is notionally supported by Ant +without requiring any additional external libraries - it just requires the +classes available in the 1.1 JDK, in Ant and in the libraries Ant uses such +as the XML parser. An optional task is a task which requires JDK 1.2+ +features or the support of an external library, such as jakarta-regexp. +

+ +

+The problem with this system is that there is no namespace management. If a +new task is added to Ant, it may invalidate buildfiles which are already +using that taskname via a taskdef. Actually the taskdef may continue to work or +it may not - it will depend on the nested elements that the task definitions +support (see above discussion of regarding cofiguration at parse-time) +

+ + +

+Tasks need to be deployed in libraries by either placing them in well known +directories of an Ant install or by telling Ant where to look for them. Removing +the central management of defined task names allows tasks libraries to be +developed and maintained independently of Ant much more easily. +

+ +

+Once centralised management of the task namespace is removed, there is, +however, the possibility of name collision. A mechanism is required to allow a +build file writer to select which particular tasks are assigned to which +tasknames. +

+
+
+ + +

+In Ant1 certain tasks may appear outside of any target. This is implemented as a +set of hardcoded conditions in the XML parsing phase. The execution and +configuration of these tasks does not involve the use of RuntimeConfigurable and +UnknownElement. +

+ +

+This hardcoding is not very inituitive. It is confusing to users who do not +know why only some tasks may be run outside of a target. Also as the list of +tasks that may be useful as a top-level task grows, further special cases must +be added to the code making the code harder to maintain. +

+ + +

+The number of special names should be kept to a minimum. Special cases should +be avoided as they are not inituitive. +

+
+
+ + +

+In Ant1, the inclusion of a set of build file definitions or targets is achieved +through the use of XML entities. This is just cumbersome. +

+ +

+A simplified include mechanism is required to replace the entity based +inclusion of Ant1. +

+
+
+ + + +

+Probably the greatest issue facing Ant1 today involves the management of the +classpath and the associated visibility of classes. Most optional tasks in Ant1 +require the supporting classes for the task to be available on the system +classpath. For example, the JUnit task is only usable if the JUnit jar is on +the classpath. If it is not, Ant will complain about being unable to create the +junit task. +

+ +

+The usual solution when a user runs into this problem is to put the required jar +into the ANT_HOME/lib directory. This just adds the required jar to the system +classpath prior to starting Ant albeit without requiring the user to explicitly +set the classpath. +

+ +

+There are a number of issues with this approach. The classes on the +classpath share the same classloader as Ant's classes and Ant's support +libraries - particularly the XML parser. If a task wishes to use a specific XML +parser, it may conflict with Ant's own parser. If two tasks require different +versions of a supporting jar, these will conflict. +

+ +

+Many tasks make use of factory objects (dynamic class instantiation, dynamic +resource loading, etc). When the factory is in the system classpath it will not +be able to load resources available in a taskdef'd task's custom classpath due +to the delegating nature of classloaders. Such errors can be very confusing to +users. More recent code is likely to attempt use of a context classloader but +this is not set by Ant1 currently. +

+ + +

+Do not require jars to be added to ANT_HOME/lib to enable tasks. Allow users to +specify the location of support jars on a per-library basis. +

+
+
+ + +

+The earliest versions Ant1 did not explicitly support any datatypes. The only +datatype, property, was actually created as a side-effect of running the +<property> task. If it were to be implemented today, property +would probably be known as a string datatype, perhaps associated with a +<load-properties> task. This is also the reason property +is one of those tasks which is allowed to exist outside of a target. +

+ +

As Ant1 evolved new types such as <path> and +<fileset> were added. The concept of datatypes has continued +to evolve to the point where users can now define new datatypes. It would be +expected that in addition to new types there will be many sub-types created, +such as new types of fileset. Ant1, however, does not strongly support such type +extensibility. When a subtype is created by extending an existing type, Ant1 +requires it to be either used by reference or all tasks which accept the base +type need to be modified to support the new type. Use by reference is not always +possible. It will depend on whether the base type has been coded to support +references.

+ + +

+Support polymorphic behaviour, allowing a build file to pass a subtype to a +task which is defined to accept the base type. Allow task interfaces to be +defined in terms of interfaces. +

+ +

+Move reference processing to the core to make it more regular removing the +burden of type developers to explicitly support references. +

+
+
+ + +

+In Ant1 the Project object takes on too many roles including all of the +following: +

+
    +
  • Holds the project model built when parsing the build file
  • +
  • Holds the run-time state of the build through the properties and current +task definitions
  • +
  • Provides context for task execution. All tasks have a reference to their +project instance and use it to access core functions
  • +
  • Provides the implementation of common task operations
  • +
  • Build event management
  • +
  • Message logging
  • +
  • Global filter definitions
  • +
  • Java Version
  • +
  • Property replacement
  • +
  • Message Levels
  • +
  • Utility functions such as boolean conversion and path translation
  • +
  • Integration point for embedding Ant
  • +
+ +

As a class, Project is not cohesive. Reuse of the Ant core functionality is +difficulty as all of these concerns bring in many other support classes. +

+ + +

+Separate the various roles of Project into more cohesive classes. +

+
+ +
+
+ +
+

+In addition to the issues which arise from Ant1 limitations, there are a number +of requirements which have emerged in the mailing list discussions about Ant2. +This isn't a complete list - just the ones I picked up for Mutant. +

+ + + +

In Ant1 the only way to reuse build file definitions is to use the +<ant> task. While useful, it is relatively coarse-grained. It +can also be tedious if you are trying to extend an existing project definition - +that is, adding new targets while retaining a user's ability to access the +existing targets.

+ +

+In addition to the extension of projects, it should be possible to compose +projects creating dependencies between the targets of the different projects, +and to access the data and definitions of one project by a controlling project +

+ + +

+Allow a project to extend and control other projects +

+
+
+ + +

+While it has always been accepted that there will be come backward compatibility +breaks in moving from Ant1 to Ant2, these should be minimized. If the changeover +from Ant1 to Ant2 is difficult, it may never happen. On the other hand, the +openness of the Ant1 interface means that some tasks will not work as expected - +the most difficult being the <script> task. +

+ + +

+Achieve a practical level of compatability without degrading the integrity of +the core's interfaces. A practical level of compatability is intentionally a +vague measure but it would require the majority of projects in Gump to be built +without noticeable differences from Ant1 +

+
+ +
+ + +

+In Ant1 configuration of Ant is achieved either through the execution of OS +dependent scripts by the launcher scripts or though properties files which have +the limited capability to set properties. +

+ + +

+Provide an XML based configuration system with rich capabilities to configure +the operation of Ant. +

+
+
+ + +

+In Ant1 there are many things which are common to a group of tasks but adding +the capability to each task is repetitive and tedious. An example would be the +failonerror attribute which controls whether a task will cause the build to stop +when it fails. This started on just one task but has since been added to many +other tasks as users want more fine control over when their builds stop. Aspects +have been discussed as a mechanism for providing a single implementation of a +concept or control that can then be applied to tasks independently. +

+ + +

+Investigate the use of an Aspect approach to provide common functionality +across tasks with a single implementation +

+
+ +
+
+ + +
+ diff --git a/proposal/mutant/xdocs/index.xml b/proposal/mutant/xdocs/index.xml new file mode 100644 index 000000000..1b0e3527f --- /dev/null +++ b/proposal/mutant/xdocs/index.xml @@ -0,0 +1,85 @@ + + + Conor MacNeill + Mutant Introduction + + + +
+

+These pages describe the design and implementation of Mutant. +

+ +

+For some time, there has been the concept of Ant 2.0, a rearchitecting of +Ant designed to address the shortcomings in the design of Ant 1.x, while +drawing the experience gained in that development. This rearchitecting +would most likely be accompanied by at least some break in backward +compatability. Over time Ant 2.0 has come to be known as Ant2 and the current +Ant codebase is generally known as Ant1. +

+ +

+Mutant is my proposal, a revolution, for Ant2. Actually, I consider it more +an evolution of the design and implementation used for Ant1, but in Jakarta +parlance, being a separate codebase, it is termed a revolution. +

+ +

+There is no special significance in the name Mutant. I chose it because, as +a word, it is an extension of the word Ant and it also signifies a change +from the previous generation +

+
+ +
+

+Mutant is not the only proposed revolution for Ant2. Peter Donald has +developed another known as +Myrmidon +which presents a different view of how Ant2 could be realized. Other +people hold the view that Ant1 can continue to evolve and that there +is no need for rearchitecture of its codebase. I recommend you +investigate all these points of view. +

+ +

+As I write this, no decision has been taken as to which codebase will be +adopted for Ant2. It may not be Mutant and it could even be some entirely +new proposal. These pages do not compare and contrast Mutant with these +other proposals or points of view, at least not explicitly. They are just +intended to describe how Mutant is designed and implemented and why it is the +way it is. +

+
+ +
+ +

Caution

+ +

+Mutant is not even an alpha release. While it is relatively stable, it is +subject to change. There are no backward compatability guarantees for any of +the classes, interfaces, build files, configuration, launch scripts, etc that +Mutant provides. +

+ +

In particular, some features in Mutant are experimental and may not, in the +long run, prove to be worthwhile.

+ +
+ +

+Start now by looking at the key requirements which have +shaped the design of Mutant. +

+ +
+

Conor MacNeill

+
+ +
+ + +
+ diff --git a/proposal/mutant/xdocs/stylesheets/project.xml b/proposal/mutant/xdocs/stylesheets/project.xml index 98f045a20..6176bb79b 100644 --- a/proposal/mutant/xdocs/stylesheets/project.xml +++ b/proposal/mutant/xdocs/stylesheets/project.xml @@ -1,50 +1,23 @@ - + - The Jakarta Site + Mutant Proposal - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + diff --git a/proposal/mutant/xdocs/stylesheets/site.vsl b/proposal/mutant/xdocs/stylesheets/site.vsl index 925e8c9c8..6a8168816 100644 --- a/proposal/mutant/xdocs/stylesheets/site.vsl +++ b/proposal/mutant/xdocs/stylesheets/site.vsl @@ -12,7 +12,7 @@ #set ($subbannerfg = "#ffffff") #set ($tablethbg = "#039acc") #set ($tabletdbg = "#a0ddf0") - + #document() @@ -35,6 +35,8 @@ #source ($items) #elseif ($items.getName().equals("table")) #table ($items) + #elseif ($items.getName().equals("box")) + #box ($items) #else $xmlout.outputString($items) #end @@ -62,6 +64,8 @@ #table ($items) #elseif ($items.getName().equals("subsection")) #subsection ($items) + #elseif ($items.getName().equals("box")) + #box ($items) #else $xmlout.outputString($items) #end diff --git a/proposal/mutant/xdocs/stylesheets/templates.vm b/proposal/mutant/xdocs/stylesheets/templates.vm index 55bab4907..b1419eed8 100644 --- a/proposal/mutant/xdocs/stylesheets/templates.vm +++ b/proposal/mutant/xdocs/stylesheets/templates.vm @@ -29,7 +29,7 @@ #if ($value.getAttributeValue("rowspan")) #set ($rowspan = $value.getAttributeValue("rowspan")) #end - #if ($value.getText().length() != 0 || $value.hasChildren()) @@ -48,7 +48,7 @@ #if ($value.getAttributeValue("rowspan")) #set ($rowspan = $value.getAttributeValue("rowspan")) #end - #if ($value.getText().length() != 0 || $value.hasChildren()) @@ -85,7 +85,7 @@ #if ($value.getAttributeValue("align")) #set ($align=$value.getAttributeValue("align")) #end - #end @@ -111,6 +111,34 @@ #end +#macro ( box $value) +
+ + + + + + + + + + + + + + + + +
+ #if ($value.getText().length() != 0 || $value.hasChildren()) + $xmlout.outputString($value, true) + #else +   + #end +
+
+#end + #macro ( makeProject ) #set ($menus = $project.getChild("body").getChildren("menu")) #foreach ( $menu in $menus ) @@ -148,16 +176,16 @@ - + #set ($authors = $root.getChild("properties").getChildren("author")) #foreach ( $au in $authors ) #metaauthor ( $au.getText() $au.getAttributeValue("email") ) #end - + $project.getChild("title").getText() - $root.getChild("properties").getChild("title").getText() - - + + @@ -168,7 +196,7 @@ - +

@@ -187,7 +215,7 @@
- Copyright © 2000-2002, Apache Software Foundation + Copyright © 2002, Apache Software Foundation