blob: 234dccf11d68d3d4d758718cc9e0bf8e5b29877a [file] [log] [blame]
/*
* 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
* <http://www.apache.org/>.
*/
package org.apache.ant.antcore.antlib;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.ant.common.antlib.AntContext;
import org.apache.ant.common.antlib.AntLibFactory;
import org.apache.ant.common.util.ExecutionException;
/**
* This class represents the Ant library.
*
* @author Conor MacNeill
* @created 14 January 2002
*/
public class AntLibrary implements ComponentLibrary {
/**
* This is the globally unique name of this library. It uses the same
* conventions as the Java package space - i.e. reverse order DNS names
* This name is used when importing tasks from this library
*/
private String libraryId;
/** THe URL of the antlib.xml library spec which defines this library */
private URL definitionURL;
/**
* The URLs to use when contructing a classloader for the components in
* this library.
*/
private List libraryURLs = new ArrayList();
/** The list of converter classnames defined in this library */
private List converterClassNames = new ArrayList();
/** The class name of this library's factory class, if any */
private String factoryClassName;
/** The parent classloader to use when contructing classloaders */
private ClassLoader parentLoader;
/** The library which this library extends, if any */
private AntLibrary extendsLibrary;
/** Indicates if each Task Instance should use its own classloader */
private boolean isolated = false;
/** The classloader for this library if it can be reused */
private ClassLoader loader = null;
/** The definitions in the library */
private Map definitions = null;
/**
* Constructor for the AntLibrary object
*
* @param spec the specification from which this library is created.
*/
public AntLibrary(AntLibrarySpec spec) {
this.libraryId = spec.getLibraryId();
this.definitions = spec.getDefinitions();
this.isolated = spec.isIsolated();
this.converterClassNames.addAll(spec.getConverters());
this.factoryClassName = spec.getFactory();
this.definitionURL = spec.getLibraryURL();
}
/**
* Sets the Library which this library extends
*
* @param extendsLibrary The new ExtendsLibrary value
*/
public void setExtendsLibrary(AntLibrary extendsLibrary) {
this.extendsLibrary = extendsLibrary;
}
/**
* Sets the ParentLoader of the AntLibrary
*
* @param parentLoader The new ParentLoader value
*/
public void setParentLoader(ClassLoader parentLoader) {
this.parentLoader = parentLoader;
}
/**
* Gets the libraryId of the AntLibrary
*
* @return the libraryId value
*/
public String getLibraryId() {
return libraryId;
}
/**
* Gets the ClassLoader of the AntLibrary
*
* @return The ClassLoader value
*/
public ClassLoader getClassLoader() {
if (isolated) {
return createLoader();
} else if (loader == null) {
loader = createLoader();
}
return loader;
}
/**
* Gets the definitions (taskdefs and typedefs) of the AntLibrary
*
* @return an iterator over the definition names
*/
public Iterator getDefinitionNames() {
return definitions.keySet().iterator();
}
/**
* Get the definition of a particular component
*
* @param definitionName the name of the component within the library
* @return an AntLibDefinition instance with information about the
* component's definition
*/
public AntLibDefinition getDefinition(String definitionName) {
return (AntLibDefinition) definitions.get(definitionName);
}
/**
* Gets an the converter class names of the AntLibrary
*
* @return an iterator over a list of String class names
*/
public Iterator getConverterClassNames() {
return converterClassNames.iterator();
}
/**
* Get the URL to where the library was loaded from
*
* @return the library's URL
*/
public URL getDefinitionURL() {
return definitionURL;
}
/**
* Gat an instance of a factory object for creating objects in this
* library.
*
* @param context the context to use for the factory creation if
* required
* @return an instance of the factory, or null if this library does not
* support a factory
* @exception ExecutionException if the factory cannot be created
*/
public AntLibFactory getFactory(AntContext context)
throws ExecutionException {
try {
AntLibFactory libFactory = null;
if (factoryClassName != null) {
Class factoryClass = Class.forName(factoryClassName,
true, getClassLoader());
libFactory
= (AntLibFactory) factoryClass.newInstance();
libFactory.init(context);
}
return libFactory;
} catch (ClassNotFoundException e) {
throw new ExecutionException("Unable to create factory "
+ factoryClassName + " for the \"" + libraryId
+ "\" Ant library", e);
} catch (NoClassDefFoundError e) {
throw new ExecutionException("Could not load a dependent class ("
+ e.getMessage() + ") to create the factory "
+ factoryClassName + " for the \"" + libraryId
+ "\" Ant library", e);
} catch (InstantiationException e) {
throw new ExecutionException("Unable to instantiate factory "
+ factoryClassName + " for the \"" + libraryId
+ "\" Ant library", e);
} catch (IllegalAccessException e) {
throw new ExecutionException("Unable to access factory "
+ factoryClassName + " for the \"" + libraryId
+ "\" Ant library", e);
}
}
/**
* Indicate whether this library has any converters defined
*
* @return true if any converters have been defined
*/
public boolean hasConverters() {
return !converterClassNames.isEmpty();
}
/**
* Add a library to path to this AntLibrary definition
*
* @param libraryURL the URL to the library to be added
*/
public void addLibraryURL(URL libraryURL) {
libraryURLs.add(libraryURL);
}
/**
* Create classloader which can be used to load the classes of this ant
* library
*
* @return the classloader for this ant library
*/
private ClassLoader createLoader() {
ClassLoader ourParent
= extendsLibrary == null ? parentLoader
: extendsLibrary.getClassLoader();
return new URLClassLoader((URL[]) libraryURLs.toArray(new URL[0]),
ourParent);
}
}