diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionSet.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionSet.java
new file mode 100644
index 000000000..f21dc9b34
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionSet.java
@@ -0,0 +1,169 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.tools.ant.taskdefs.optional.extension;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.types.DataType;
+import org.apache.tools.ant.types.Reference;
+import org.apache.tools.ant.types.FileSet;
+
+/**
+ * The Extension set lists a set of "Optional Packages" /
+ * "Extensions".
+ *
+ * @author Peter Donald
+ * @version $Revision$ $Date$
+ * @ant.data-type name="extension-set"
+ */
+public class ExtensionSet
+ extends DataType
+{
+ /**
+ * ExtensionAdapter objects representing extensions.
+ */
+ private final ArrayList m_extensions = new ArrayList();
+
+ /**
+ * Filesets specifying all the extensions wanted.
+ */
+ private final ArrayList m_extensionsFilesets = new ArrayList();
+
+ /**
+ * Adds an extension that this library requires.
+ *
+ * @param extensionAdapter an extension that this library requires.
+ */
+ public void addExtension( final ExtensionAdapter extensionAdapter )
+ {
+ m_extensions.add( extensionAdapter );
+ }
+
+ /**
+ * Adds a set of files about which extensions data will be extracted.
+ *
+ * @param fileSet a set of files about which extensions data will be extracted.
+ */
+ public void addLibfileset( final LibFileSet fileSet )
+ {
+ m_extensionsFilesets.add( fileSet );
+ }
+
+ /**
+ * Adds a set of files about which extensions data will be extracted.
+ *
+ * @param fileSet a set of files about which extensions data will be extracted.
+ */
+ public void addFileset( final FileSet fileSet )
+ {
+ m_extensionsFilesets.add( fileSet );
+ }
+
+ /**
+ * Extract a set of Extension objects from the ExtensionSet.
+ *
+ * @throws BuildException if an error occurs
+ */
+ public Extension[] toExtensions( final Project project )
+ throws BuildException
+ {
+ final ArrayList extensions = ExtensionUtil.toExtensions( m_extensions );
+ ExtensionUtil.extractExtensions( project, extensions, m_extensionsFilesets );
+ return (Extension[])extensions.toArray( new Extension[ extensions.size() ] );
+ }
+
+ /**
+ * Makes this instance in effect a reference to another ExtensionSet
+ * instance.
+ *
+ *
You must not set another attribute or nest elements inside
+ * this element if you make it a reference.
+ *
+ * @param reference the reference to which this instance is associated
+ * @exception BuildException if this instance already has been configured.
+ */
+ public void setRefid( final Reference reference )
+ throws BuildException
+ {
+ if( !m_extensions.isEmpty() ||
+ !m_extensionsFilesets.isEmpty() )
+ {
+ throw tooManyAttributes();
+ }
+ // change this to get the objects from the other reference
+ final Object object =
+ reference.getReferencedObject( getProject() );
+ if( object instanceof ExtensionSet )
+ {
+ final ExtensionSet other = (ExtensionSet)object;
+ m_extensions.addAll( other.m_extensions );
+ m_extensionsFilesets.addAll( other.m_extensionsFilesets );
+ }
+ else
+ {
+ final String message =
+ reference.getRefId() + " doesn\'t refer to a ExtensionSet";
+ throw new BuildException( message );
+ }
+
+ super.setRefid( reference );
+ }
+
+ public String toString()
+ {
+ return "ExtensionSet" + Arrays.asList( toExtensions( getProject() ) );
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionUtil.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionUtil.java
new file mode 100644
index 000000000..6acab9433
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionUtil.java
@@ -0,0 +1,238 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.tools.ant.taskdefs.optional.extension;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.jar.JarFile;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.types.FileSet;
+
+/**
+ * A set of useful methods relating to extensions.
+ *
+ * @author Peter Donald
+ * @version $Revision$ $Date$
+ */
+public class ExtensionUtil
+{
+ /**
+ * Convert a list of extensionAdapter objects to extensions.
+ *
+ * @param adapters the list of ExtensionAdapterss to add to convert
+ * @throws BuildException if an error occurs
+ */
+ static ArrayList toExtensions( final ArrayList adapters )
+ throws BuildException
+ {
+ final ArrayList results = new ArrayList();
+
+ final int size = adapters.size();
+ for( int i = 0; i < size; i++ )
+ {
+ final ExtensionAdapter adapter =
+ (ExtensionAdapter)adapters.get( i );
+ final Extension extension = adapter.toExtension();
+ results.add( extension );
+ }
+
+ return results;
+ }
+
+ /**
+ * Generate a list of extensions from a specified fileset.
+ *
+ * @param librarys the list to add extensions to
+ * @param fileset the filesets containing librarys
+ * @throws BuildException if an error occurs
+ */
+ static void extractExtensions( final Project project,
+ final ArrayList librarys,
+ final ArrayList fileset )
+ throws BuildException
+ {
+ if( !fileset.isEmpty() )
+ {
+ final Extension[] extensions = getExtensions( project,
+ fileset );
+ for( int i = 0; i < extensions.length; i++ )
+ {
+ librarys.add( extensions[ i ] );
+ }
+ }
+ }
+
+ /**
+ * Retrieve extensions from the specified librarys.
+ *
+ * @param librarys the filesets for librarys
+ * @return the extensions contained in librarys
+ * @throws BuildException if failing to scan librarys
+ */
+ private static Extension[] getExtensions( final Project project,
+ final ArrayList librarys )
+ throws BuildException
+ {
+ final ArrayList extensions = new ArrayList();
+ final Iterator iterator = librarys.iterator();
+ while( iterator.hasNext() )
+ {
+ final FileSet fileSet = (FileSet)iterator.next();
+
+ boolean includeImpl = true;
+ boolean includeURL = true;
+
+ if( fileSet instanceof LibFileSet )
+ {
+ LibFileSet libFileSet = (LibFileSet)fileSet;
+ includeImpl = libFileSet.isIncludeImpl();
+ includeURL = libFileSet.isIncludeURL();
+ }
+
+ final DirectoryScanner scanner = fileSet.getDirectoryScanner( project );
+ final File basedir = scanner.getBasedir();
+ final String[] files = scanner.getIncludedFiles();
+ for( int i = 0; i < files.length; i++ )
+ {
+ final File file = new File( basedir, files[ i ] );
+ loadExtensions( file, extensions, includeImpl, includeURL );
+ }
+ }
+ return (Extension[])extensions.toArray( new Extension[ extensions.size() ] );
+ }
+
+ /**
+ * Load list of available extensions from specified file.
+ *
+ * @param file the file
+ * @param extensionList the list to add available extensions to
+ * @throws BuildException if there is an error
+ */
+ private static void loadExtensions( final File file,
+ final ArrayList extensionList,
+ final boolean includeImpl,
+ final boolean includeURL )
+ throws BuildException
+ {
+ try
+ {
+ final JarFile jarFile = new JarFile( file );
+ final Extension[] extensions =
+ Extension.getAvailable( jarFile.getManifest() );
+ for( int i = 0; i < extensions.length; i++ )
+ {
+ final Extension extension = extensions[ i ];
+ addExtension( extensionList, extension, includeImpl, includeURL );
+ }
+ }
+ catch( final Exception e )
+ {
+ throw new BuildException( e.getMessage(), e );
+ }
+ }
+
+ /**
+ * Add extension to list.
+ * If extension should not have implementation details but
+ * does strip them. If extension should not have url but does
+ * then strip it.
+ *
+ * @param extensionList the list of extensions to add to
+ * @param originalExtension the extension
+ * @param includeImpl false to exclude implementation details
+ * @param includeURL false to exclude implementation URL
+ */
+ private static void addExtension( final ArrayList extensionList,
+ final Extension originalExtension,
+ final boolean includeImpl,
+ final boolean includeURL )
+ {
+ Extension extension = originalExtension;
+ if( !includeURL &&
+ null != extension.getImplementationURL() )
+ {
+ extension =
+ new Extension( extension.getExtensionName(),
+ extension.getSpecificationVersion().toString(),
+ extension.getSpecificationVendor(),
+ extension.getImplementationVersion().toString(),
+ extension.getImplementationVendor(),
+ extension.getImplementationVendorID(),
+ null );
+ }
+
+ final boolean hasImplAttributes =
+ null != extension.getImplementationURL() ||
+ null != extension.getImplementationVersion() ||
+ null != extension.getImplementationVendorID() ||
+ null != extension.getImplementationVendor();
+
+ if( !includeImpl && hasImplAttributes )
+ {
+ extension =
+ new Extension( extension.getExtensionName(),
+ extension.getSpecificationVersion().toString(),
+ extension.getSpecificationVendor(),
+ null,
+ null,
+ null,
+ extension.getImplementationURL() );
+ }
+
+ extensionList.add( extension );
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/LibFileSet.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/LibFileSet.java
new file mode 100644
index 000000000..edbc86cb4
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/LibFileSet.java
@@ -0,0 +1,165 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.tools.ant.taskdefs.optional.extension;
+
+import org.apache.tools.ant.types.FileSet;
+
+/**
+ * LibFileSet represents a fileset containing libraries.
+ * Asociated with the libraries is data pertaining to
+ * how they are to be handled when building manifests.
+ *
+ * @author Peter Donald
+ * @version $Revision$ $Date$
+ */
+public class LibFileSet
+ extends FileSet
+{
+ /**
+ * Flag indicating whether should include the
+ * "Implementation-URL" attribute in manifest.
+ * Defaults to false.
+ */
+ private boolean m_includeURL;
+
+ /**
+ * Flag indicating whether should include the
+ * "Implementation-*" attributes in manifest.
+ * Defaults to false.
+ */
+ private boolean m_includeImpl;
+
+ /**
+ * String that is the base URL for the librarys
+ * when constructing the "Implementation-URL"
+ * attribute. For instance setting the base to
+ * "http://jakarta.apache.org/avalon/libs/" and then
+ * including the library "excalibur-cli-1.0.jar" in the
+ * fileset will result in the "Implementation-URL" attribute
+ * being set to "http://jakarta.apache.org/avalon/libs/excalibur-cli-1.0.jar"
+ *
+ * Note this is only used if the library does not define
+ * "Implementation-URL" itself.
+ *
+ * Note that this also implies includeURL=true
+ */
+ private String m_urlBase;
+
+ /**
+ * Flag indicating whether should include the
+ * "Implementation-URL" attribute in manifest.
+ * Defaults to false.
+ *
+ * @param includeURL the flag
+ * @see #m_includeURL
+ */
+ public void setIncludeUrl( boolean includeURL )
+ {
+ m_includeURL = includeURL;
+ }
+
+ /**
+ * Flag indicating whether should include the
+ * "Implementation-*" attributes in manifest.
+ * Defaults to false.
+ *
+ * @param includeImpl the flag
+ * @see #m_includeImpl
+ */
+ public void setIncludeImpl( boolean includeImpl )
+ {
+ m_includeImpl = includeImpl;
+ }
+
+ /**
+ * Set the url base for fileset.
+ *
+ * @param urlBase the base url
+ * @see #m_urlBase
+ */
+ public void setUrlBase( String urlBase )
+ {
+ m_urlBase = urlBase;
+ }
+
+ /**
+ * Get the includeURL flag.
+ *
+ * @return the includeURL flag.
+ */
+ boolean isIncludeURL()
+ {
+ return m_includeURL;
+ }
+
+ /**
+ * Get the includeImpl flag.
+ *
+ * @return the includeImpl flag.
+ */
+ boolean isIncludeImpl()
+ {
+ return m_includeImpl;
+ }
+
+ /**
+ * Get the urlbase.
+ *
+ * @return the urlbase.
+ */
+ String getUrlBase()
+ {
+ return m_urlBase;
+ }
+}