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

org.apache.tools.ant.taskdefs.Available Maven / Gradle / Ivy

There is a newer version: 1.0-rc5
Show newest version
/*
 * Copyright  2000-2005 The Apache Software Foundation
 *
 *  Licensed 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.taskdefs;

import java.io.File;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.condition.Condition;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.StringUtils;

/**
 * Will set the given property if the requested resource is available at
 * runtime. This task may also be used as a condition by the condition task.
 *
 * @since Ant 1.1
 *
 * @ant.task category="control"
 */
public class Available extends Task implements Condition {
    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();

    private String property;
    private String classname;
    private String filename;
    private File file;
    private Path filepath;
    private String resource;
    private FileDir type;
    private Path classpath;
    private AntClassLoader loader;
    private String value = "true";
    private boolean isTask = false;
    private boolean ignoreSystemclasses = false;

    /**
     * Set the classpath to be used when searching for classes and resources.
     *
     * @param classpath an Ant Path object containing the search path.
     */
    public void setClasspath(Path classpath) {
        createClasspath().append(classpath);
    }

    /**
     * Classpath to be used when searching for classes and resources.
     *
     * @return an empty Path instance to be configured by Ant.
     */
    public Path createClasspath() {
        if (this.classpath == null) {
            this.classpath = new Path(getProject());
        }
        return this.classpath.createPath();
    }

    /**
     * Set the classpath by reference.
     *
     * @param r a Reference to a Path instance to be used as the classpath
     *          value.
     */
    public void setClasspathRef(Reference r) {
        createClasspath().setRefid(r);
    }

    /**
     * Set the path to use when looking for a file.
     *
     * @param filepath a Path instance containing the search path for files.
     */
    public void setFilepath(Path filepath) {
        createFilepath().append(filepath);
    }

    /**
     * Path to search for file resources.
     *
     * @return a new Path instance which Ant will configure with a file search
     *         path.
     */
    public Path createFilepath() {
        if (this.filepath == null) {
            this.filepath = new Path(getProject());
        }
        return this.filepath.createPath();
    }

    /**
     * Set the name of the property which will be set if the particular resource
     * is available.
     *
     * @param property the name of the property to set.
     */
    public void setProperty(String property) {
        this.property = property;
    }

    /**
     * Set the value to be given to the property if the desired resource is
     * available.
     *
     * @param value the value to be given.
     */
    public void setValue(String value) {
        this.value = value;
    }

    /**
     * Set a classname of a class which must be available to set the given
     * property.
     *
     * @param classname the name of the class required.
     */
    public void setClassname(String classname) {
        if (!"".equals(classname)) {
            this.classname = classname;
        }
    }

    /**
     * Set the file which must be present in the file system to set the given
     * property.
     *
     * @param file the name of the file which is required.
     */
    public void setFile(File file) {
        this.file = file;
        this.filename = FILE_UTILS.removeLeadingPath(getProject().getBaseDir(), file);
    }

    /**
     * Set the name of a Java resource which is required to set the property.
     *
     * @param resource the name of a resource which is required to be available.
     */
    public void setResource(String resource) {
        this.resource = resource;
    }

    /**
     * @deprecated setType(String) is deprecated and is replaced with
     *             setType(Available.FileDir) to make Ant's Introspection
     *             mechanism do the work and also to encapsulate operations on
     *             the type in its own class.
     * @param type the type of resource
     */
    public void setType(String type) {
        log("DEPRECATED - The setType(String) method has been deprecated."
            + " Use setType(Available.FileDir) instead.",
            Project.MSG_WARN);
        this.type = new FileDir();
        this.type.setValue(type);
    }

    /**
     * Set what type of file is required - either directory or file.
     *
     * @param type an instance of the FileDir enumeratedAttribute indicating
     *             whether the file required is to be a directory or a plain
     *             file.
     */
    public void setType(FileDir type) {
        this.type = type;
    }

    /**
     * Set whether the search for classes should ignore the runtime classes and
     * just use the given classpath.
     *
     * @param ignore true if system classes are to be ignored.
     */
    public void setIgnoresystemclasses(boolean ignore) {
        this.ignoreSystemclasses = ignore;
    }

    /**
     * Entry point when operating as a task.
     *
     * @exception BuildException if the task is not configured correctly.
     */
    public void execute() throws BuildException {
        if (property == null) {
            throw new BuildException("property attribute is required",
                                     getLocation());
        }

        isTask = true;
        try {
            if (eval()) {
                String oldvalue = getProject().getProperty(property);
                if (null != oldvalue && !oldvalue.equals(value)) {
                    log("DEPRECATED -  used to override an existing"
                        + " property."
                        + StringUtils.LINE_SEP
                        + "  Build file should not reuse the same property"
                        + " name for different values.",
                        Project.MSG_WARN);
                }
                // NB: this makes use of Project#setProperty rather than Project#setNewProperty
                //     due to backwards compatiblity reasons
                getProject().setProperty(property, value);
            }
        } finally {
            isTask = false;
        }
    }

    /**
     * Evaluate the availability of a resource.
     *
     * @return boolean is the resource is available.
     * @exception BuildException if the condition is not configured correctly
     */
    public boolean eval() throws BuildException {
        if (classname == null && file == null && resource == null) {
            throw new BuildException("At least one of (classname|file|"
                                     + "resource) is required", getLocation());
        }
        if (type != null) {
            if (file == null) {
                throw new BuildException("The type attribute is only valid "
                                         + "when specifying the file "
                                         + "attribute.", getLocation());
            }
        }
        if (classpath != null) {
            classpath.setProject(getProject());
            this.loader = getProject().createClassLoader(classpath);
        }
        String appendix = "";
        if (isTask) {
            appendix = " to set property " + property;
        } else {
            setTaskName("available");
        }
        if ((classname != null) && !checkClass(classname)) {
            log("Unable to load class " + classname + appendix,
                Project.MSG_VERBOSE);
            return false;
        }
        if ((file != null) && !checkFile()) {
            StringBuffer buf = new StringBuffer("Unable to find ");
            if (type != null) {
                buf.append(type).append(' ');
            }
            buf.append(filename).append(appendix);
            log(buf.toString(), Project.MSG_VERBOSE);
            return false;
        }
        if ((resource != null) && !checkResource(resource)) {
            log("Unable to load resource " + resource + appendix,
                Project.MSG_VERBOSE);
            return false;
        }
        if (loader != null) {
            loader.cleanup();
            loader = null;
        }
        if (!isTask) {
            setTaskName(null);
        }
        return true;
    }

    /**
     * Search for file/directory either relative to project's
     * basedir or in the path given as filepath.
     *
     * 

filepath can be a list of directory and/or file names (gen'd * via )

* *

look for:

    *
  • full-pathname specified == path in list
  • *
  • full-pathname specified == parent dir of path in list
  • *
  • simple name specified == path in list
  • *
  • simple name specified == path in list + name
  • *
  • simple name specified == parent dir + name
  • *
  • simple name specified == parent of parent dir + name
  • *
*/ private boolean checkFile() { if (filepath == null) { return checkFile(file, filename); } else { String[] paths = filepath.list(); for (int i = 0; i < paths.length; ++i) { log("Searching " + paths[i], Project.MSG_DEBUG); File path = new File(paths[i]); // ** full-pathname specified == path in list // ** simple name specified == path in list if (path.exists() && filename.equals(paths[i])) { if (type == null) { log("Found: " + path, Project.MSG_VERBOSE); return true; } else if (type.isDir() && path.isDirectory()) { log("Found directory: " + path, Project.MSG_VERBOSE); return true; } else if (type.isFile() && path.isFile()) { log("Found file: " + path, Project.MSG_VERBOSE); return true; } // not the requested type return false; } File parent = path.getParentFile(); // ** full-pathname specified == parent dir of path in list if (parent != null && parent.exists() && filename.equals(parent.getAbsolutePath())) { if (type == null) { log("Found: " + parent, Project.MSG_VERBOSE); return true; } else if (type.isDir()) { log("Found directory: " + parent, Project.MSG_VERBOSE); return true; } // not the requested type return false; } // ** simple name specified == path in list + name if (path.exists() && path.isDirectory()) { if (checkFile(new File(path, filename), filename + " in " + path)) { return true; } } // ** simple name specified == parent dir + name if (parent != null && parent.exists()) { if (checkFile(new File(parent, filename), filename + " in " + parent)) { return true; } } // ** simple name specified == parent of parent dir + name if (parent != null) { File grandParent = parent.getParentFile(); if (grandParent != null && grandParent.exists()) { if (checkFile(new File(grandParent, filename), filename + " in " + grandParent)) { return true; } } } } } return false; } /** * Check if a given file exists and matches the required type. */ private boolean checkFile(File f, String text) { if (type != null) { if (type.isDir()) { if (f.isDirectory()) { log("Found directory: " + text, Project.MSG_VERBOSE); } return f.isDirectory(); } else if (type.isFile()) { if (f.isFile()) { log("Found file: " + text, Project.MSG_VERBOSE); } return f.isFile(); } } if (f.exists()) { log("Found: " + text, Project.MSG_VERBOSE); } return f.exists(); } /** * Check if a given resource can be loaded. */ private boolean checkResource(String resource) { if (loader != null) { return (loader.getResourceAsStream(resource) != null); } else { ClassLoader cL = this.getClass().getClassLoader(); if (cL != null) { return (cL.getResourceAsStream(resource) != null); } else { return (ClassLoader.getSystemResourceAsStream(resource) != null); } } } /** * Check if a given class can be loaded. */ private boolean checkClass(String classname) { try { Class requiredClass = null; if (ignoreSystemclasses) { loader = getProject().createClassLoader(classpath); loader.setParentFirst(false); loader.addJavaLibraries(); if (loader != null) { try { requiredClass = loader.findClass(classname); } catch (SecurityException se) { // class found but restricted name; this is // actually the case we're looking for in JDK 1.3+, // so catch the exception and return return true; } } else { return false; } } else if (loader != null) { requiredClass = loader.loadClass(classname); } else { ClassLoader l = this.getClass().getClassLoader(); // Can return null to represent the bootstrap class loader. // see API docs of Class.getClassLoader. if (l != null) { requiredClass = Class.forName(classname, true, l); } else { requiredClass = Class.forName(classname); } } return true; } catch (ClassNotFoundException e) { log("class \"" + classname + "\" was not found", Project.MSG_DEBUG); return false; } catch (NoClassDefFoundError e) { log("Could not load dependent class \"" + e.getMessage() + "\" for class \"" + classname + "\"", Project.MSG_DEBUG); return false; } } /** * EnumeratedAttribute covering the file types to be checked for, either * file or dir. */ public static class FileDir extends EnumeratedAttribute { private static final String[] VALUES = {"file", "dir"}; /** * @see EnumeratedAttribute#getValues */ public String[] getValues() { return VALUES; } /** * Indicate if the value specifies a directory. * * @return true if the value specifies a directory. */ public boolean isDir() { return "dir".equalsIgnoreCase(getValue()); } /** * Indicate if the value specifies a file. * * @return true if the value specifies a file. */ public boolean isFile() { return "file".equalsIgnoreCase(getValue()); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy