All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.greenpepper.ext.shaded.org.apache.tools.ant.AntTypeDefinition Maven / Gradle / Ivy

/*
 *  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 com.greenpepper.ext.shaded.org.apache.tools.ant;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Constructor;


/**
 * This class contains all the information
 * on a particular ant type,
 * the classname, adaptor 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;

    /**
     * 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.
     */
    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 Object.
     */
    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.
     * 
*
  • if the class can be created.
  • *
  • if an adapter class can be created
  • *
  • if the type is assignable from adapto
  • *
  • if the type can be used with the adapter class
  • *
    * @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 Object. */ 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 newclass class to create * @param project the project to use * @return a newly constructed and bound instance. * @throws NoSuchMethodException no good construtor. * @throws InstantiationException cannot initialize the object. * @throws IllegalAccessException cannot access the object. * @throws InvocationTargetException error in invocation. */ public Object innerCreateAndSet(Class newclass, Project project) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Constructor ctor = null; 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 Object 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.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))) { 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) ? "" : c.getClass().getName(); } }




    © 2015 - 2024 Weber Informatics LLC | Privacy Policy