aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/AntTypeDefinition.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/AntTypeDefinition.java')
-rw-r--r--framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/AntTypeDefinition.java389
1 files changed, 389 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/AntTypeDefinition.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/AntTypeDefinition.java
new file mode 100644
index 00000000..104820f1
--- /dev/null
+++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/AntTypeDefinition.java
@@ -0,0 +1,389 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.tools.ant;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+
+/**
+ * This class contains all the information
+ * on a particular ant type,
+ * the classname, adapter and the class
+ * it should be assignable from.
+ * This type replaces the task/datatype split
+ * of pre ant 1.6.
+ *
+ */
+public class AntTypeDefinition {
+ private String name;
+ private Class<?> clazz;
+ private Class<?> adapterClass;
+ private Class<?> adaptToClass;
+ private String className;
+ private ClassLoader classLoader;
+ private boolean restrict = false;
+
+ /**
+ * Set the restrict attribute.
+ * @param restrict the value to set.
+ */
+ public void setRestrict(boolean restrict) {
+ this.restrict = restrict;
+ }
+
+ /**
+ * Get the restrict attribute.
+ * @return the restrict attribute.
+ */
+ public boolean isRestrict() {
+ return restrict;
+ }
+
+ /**
+ * Set the definition's name.
+ * @param name the name of the definition.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Return the definition's name.
+ * @return the name of the definition.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Set the class of the definition.
+ * As a side-effect may set the classloader and classname.
+ * @param clazz the class of this definition.
+ */
+ public void setClass(Class<?> clazz) {
+ this.clazz = clazz;
+ if (clazz == null) {
+ return;
+ }
+ this.classLoader = (classLoader == null)
+ ? clazz.getClassLoader() : classLoader;
+ this.className = (className == null) ? clazz.getName() : className;
+ }
+
+ /**
+ * Set the classname of the definition.
+ * @param className the classname of this definition.
+ */
+ public void setClassName(String className) {
+ this.className = className;
+ }
+
+ /**
+ * Get the classname of the definition.
+ * @return the name of the class of this definition.
+ */
+ public String getClassName() {
+ return className;
+ }
+
+ /**
+ * Set the adapter class for this definition.
+ * This class is used to adapt the definitions class if
+ * required.
+ * @param adapterClass the adapterClass.
+ */
+ public void setAdapterClass(Class<?> adapterClass) {
+ this.adapterClass = adapterClass;
+ }
+
+ /**
+ * Set the assignable class for this definition.
+ * @param adaptToClass the assignable class.
+ */
+
+ public void setAdaptToClass(Class<?> adaptToClass) {
+ this.adaptToClass = adaptToClass;
+ }
+
+ /**
+ * Set the classloader to use to create an instance
+ * of the definition.
+ * @param classLoader the ClassLoader.
+ */
+ public void setClassLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ /**
+ * Get the classloader for this definition.
+ * @return the classloader for this definition.
+ */
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ /**
+ * Get the exposed class for this
+ * definition. This will be a proxy class
+ * (adapted class) if there is an adapter
+ * class and the definition class is not
+ * assignable from the assignable class.
+ * @param project the current project.
+ * @return the exposed class - may return null if unable to load the class
+ */
+ public Class<?> getExposedClass(Project project) {
+ if (adaptToClass != null) {
+ Class<?> z = getTypeClass(project);
+ if (z == null || adaptToClass.isAssignableFrom(z)) {
+ return z;
+ }
+ }
+ return (adapterClass == null) ? getTypeClass(project) : adapterClass;
+ }
+
+ /**
+ * Get the definition class.
+ * @param project the current project.
+ * @return the type of the definition.
+ */
+ public Class<?> getTypeClass(Project project) {
+ try {
+ return innerGetTypeClass();
+ } catch (NoClassDefFoundError ncdfe) {
+ project.log("Could not load a dependent class ("
+ + ncdfe.getMessage() + ") for type "
+ + name, Project.MSG_DEBUG);
+ } catch (ClassNotFoundException cnfe) {
+ project.log("Could not load class (" + className
+ + ") for type " + name, Project.MSG_DEBUG);
+ }
+ return null;
+ }
+
+ /**
+ * Try and load a class, with no attempt to catch any fault.
+ * @return the class that implements this component
+ * @throws ClassNotFoundException if the class cannot be found.
+ * @throws NoClassDefFoundError if the there is an error
+ * finding the class.
+ */
+ public Class<?> innerGetTypeClass() throws ClassNotFoundException {
+ if (clazz != null) {
+ return clazz;
+ }
+ if (classLoader == null) {
+ clazz = Class.forName(className);
+ } else {
+ clazz = classLoader.loadClass(className);
+ }
+ return clazz;
+ }
+
+ /**
+ * Create an instance of the definition.
+ * The instance may be wrapped in a proxy class.
+ * @param project the current project.
+ * @return the created object.
+ */
+ public Object create(Project project) {
+ return icreate(project);
+ }
+
+ /**
+ * Create a component object based on
+ * its definition.
+ * @return the component as an <code>Object</code>.
+ */
+ private Object icreate(Project project) {
+ Class<?> c = getTypeClass(project);
+ if (c == null) {
+ return null;
+ }
+ Object o = createAndSet(project, c);
+ if (o == null || adapterClass == null) {
+ return o;
+ }
+ if (adaptToClass != null) {
+ if (adaptToClass.isAssignableFrom(o.getClass())) {
+ return o;
+ }
+ }
+ TypeAdapter adapterObject = (TypeAdapter) createAndSet(
+ project, adapterClass);
+ if (adapterObject == null) {
+ return null;
+ }
+ adapterObject.setProxy(o);
+ return adapterObject;
+ }
+
+ /**
+ * Checks if the attributes are correct.
+ * <ul>
+ * <li>if the class can be created.</li>
+ * <li>if an adapter class can be created</li>
+ * <li>if the type is assignable from adapter</li>
+ * <li>if the type can be used with the adapter class</li>
+ * </ul>
+ * @param project the current project.
+ */
+ public void checkClass(Project project) {
+ if (clazz == null) {
+ clazz = getTypeClass(project);
+ if (clazz == null) {
+ throw new BuildException(
+ "Unable to create class for " + getName());
+ }
+ }
+ // check adapter
+ if (adapterClass != null && (adaptToClass == null
+ || !adaptToClass.isAssignableFrom(clazz))) {
+ TypeAdapter adapter = (TypeAdapter) createAndSet(
+ project, adapterClass);
+ if (adapter == null) {
+ throw new BuildException("Unable to create adapter object");
+ }
+ adapter.checkProxyClass(clazz);
+ }
+ }
+
+ /**
+ * Get the constructor of the definition
+ * and invoke it.
+ * @return the instantiated <code>Object</code>.
+ */
+ private Object createAndSet(Project project, Class<?> c) {
+ try {
+ Object o = innerCreateAndSet(c, project);
+ return o;
+ } catch (InvocationTargetException ex) {
+ Throwable t = ex.getTargetException();
+ throw new BuildException(
+ "Could not create type " + name + " due to " + t, t);
+ } catch (NoClassDefFoundError ncdfe) {
+ String msg = "Type " + name + ": A class needed by class "
+ + c + " cannot be found: " + ncdfe.getMessage();
+ throw new BuildException(msg, ncdfe);
+ } catch (NoSuchMethodException nsme) {
+ throw new BuildException("Could not create type " + name
+ + " as the class " + c + " has no compatible constructor");
+ } catch (InstantiationException nsme) {
+ throw new BuildException("Could not create type "
+ + name + " as the class " + c + " is abstract");
+ } catch (IllegalAccessException e) {
+ throw new BuildException("Could not create type "
+ + name + " as the constructor " + c + " is not accessible");
+ } catch (Throwable t) {
+ throw new BuildException(
+ "Could not create type " + name + " due to " + t, t);
+ }
+ }
+
+ /**
+ * Inner implementation of the {@link #createAndSet(Project, Class)} logic, with no
+ * exception catching.
+ * @param <T> return type of the method
+ * @param newclass class to create
+ * @param project the project to use
+ * @return a newly constructed and bound instance.
+ * @throws NoSuchMethodException no good constructor.
+ * @throws InstantiationException cannot initialize the object.
+ * @throws IllegalAccessException cannot access the object.
+ * @throws InvocationTargetException error in invocation.
+ */
+ public <T> T innerCreateAndSet(Class<T> newclass, Project project)
+ throws NoSuchMethodException,
+ InstantiationException,
+ IllegalAccessException,
+ InvocationTargetException {
+ Constructor<T> ctor;
+ boolean noArg = false;
+ // DataType can have a "no arg" constructor or take a single
+ // Project argument.
+ try {
+ ctor = newclass.getConstructor(new Class[0]);
+ noArg = true;
+ } catch (NoSuchMethodException nse) {
+ //can throw the same exception, if there is no this(Project) ctor.
+ ctor = newclass.getConstructor(new Class[] {Project.class});
+ noArg = false;
+ }
+ //now we instantiate
+ T o = ctor.newInstance(
+ ((noArg) ? new Object[0] : new Object[] {project}));
+
+ //set up project references.
+ project.setProjectReference(o);
+ return o;
+ }
+
+ /**
+ * Equality method for this definition (assumes the names are the same).
+ *
+ * @param other another definition.
+ * @param project the project the definition.
+ * @return true if the definitions are the same.
+ */
+ public boolean sameDefinition(AntTypeDefinition other, Project project) {
+ return (other != null && other.getClass() == getClass()
+ && other.getTypeClass(project).equals(getTypeClass(project))
+ && other.getExposedClass(project).equals(getExposedClass(project))
+ && other.restrict == restrict
+ && other.adapterClass == adapterClass
+ && other.adaptToClass == adaptToClass);
+ }
+
+ /**
+ * Similar definition;
+ * used to compare two definitions defined twice with the same
+ * name and the same types.
+ * The classloader may be different but have the same
+ * path so #sameDefinition cannot
+ * be used.
+ * @param other the definition to compare to.
+ * @param project the current project.
+ * @return true if the definitions are the same.
+ */
+ public boolean similarDefinition(AntTypeDefinition other, Project project) {
+ if (other == null
+ || getClass() != other.getClass()
+ || !getClassName().equals(other.getClassName())
+ || !extractClassname(adapterClass).equals(
+ extractClassname(other.adapterClass))
+ || !extractClassname(adaptToClass).equals(
+ extractClassname(other.adaptToClass))
+ || restrict != other.restrict) {
+ return false;
+ }
+ // all the names are the same: check if the class path of the loader
+ // is the same
+ ClassLoader oldLoader = other.getClassLoader();
+ ClassLoader newLoader = getClassLoader();
+ return oldLoader == newLoader
+ || (oldLoader instanceof AntClassLoader
+ && newLoader instanceof AntClassLoader
+ && ((AntClassLoader) oldLoader).getClasspath()
+ .equals(((AntClassLoader) newLoader).getClasspath()));
+ }
+
+ private String extractClassname(Class<?> c) {
+ return (c == null) ? "<null>" : c.getClass().getName();
+ }
+}