ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Matt Benson <gudnabr...@yahoo.com>
Subject Re: classloader for 1.7
Date Fri, 13 Oct 2006 21:39:51 GMT
As promised, I reworked Peter's task to use
ResourceCollection stuff better, made a stupid error
when writing my tests, and forgot to come back to it
until now.  The thing works great.  Pasting inline...
are we still thinking it's possible to put this in 1.7
?  Or this thing is self-contained enough that we
could make it an antlib.  I hate the thought of
fifteen single-task antlibs, but we could create an
uber-antlib called... giant!  ;)  Thoughts?

-Matt

(different package for my testing)
/*
 *  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.antcl;

import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.DataType;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;
import
org.apache.tools.ant.types.resources.FileResource;
import org.apache.tools.ant.types.resources.Resources;
import
org.apache.tools.ant.types.resources.URLResource;
import org.apache.tools.ant.util.FileUtils;

/**
 * A Task to extend the project class path; works by
assuming that the
 * project classloader is a URLClassLoader (or derives
from URLClassloader),
 * and by using reflection to make the addURL method
public.
 */
public class AppendProjectPath extends Task {
    private static final FileUtils FILE_UTILS =
FileUtils.getFileUtils();
    private static final Method ADD_URL;

    static {
        try {
            ADD_URL =
URLClassLoader.class.getDeclaredMethod("addURL",
                    new Class[] {URL.class});
            ADD_URL.setAccessible(true);
        } catch (SecurityException ex) {
            throw new BuildException(
                    "Unable to setAccessible(true) for
method addURL", ex);
        } catch (NoSuchMethodException ex) {
            throw new BuildException(
                    "Unable to find the addURL
method", ex);
        }
    }

    /**
     * One ResourceCollection to rule them all
     */
    private Resources resources;

    /**
     * The classloader of the project class
     */
    private URLClassLoader projectLoader;

    /**
     * Construct an AppendProjectPath task instance.
     *
     * @param p the associated Project instance.
     */
    public AppendProjectPath(Project p) {
        super();
        if (p == null) {
            throw new BuildException("project is
required");
        }
        setProject(p);

        ClassLoader cl =
p.getClass().getClassLoader();
        if (cl instanceof URLClassLoader) {
            projectLoader = (URLClassLoader) cl;
        } else {
            throw new BuildException("project
classloader is not a URLClassLoader");
        }
        resources = new Resources();
        resources.setProject(p);
    }

    /**
     * Add a URL via the "url" attribute.
     *
     * @param url URLResource.
     */
    public void setURL(URLResource url) {
        addConfigured(url);
    }

    /**
     * Add a nested ResourceCollection.
     *
     * @param rc a nested ResourceCollection.
     */
    public void addConfigured(ResourceCollection rc) {
        resources.add(rc);
    }

    /**
     * Add Path components via the "path" attribute.
     *
     * @param path a path string.
     */
    public void setPath(Path path) {
        addConfigured(path);
    }

    /**
     * Add a ResourceCollection reference via the
"refid" attribute.
     *
     * @param refid a reference to an existing
ResourceCollection.
     */
    public void setRefid(Reference ref) {
        Object o =
ref.getReferencedObject(getProject());
        if (!(o instanceof ResourceCollection)) {
            throw new BuildException("reference '" +
ref.getRefId()
                    + "' is not a ResourceCollection;
value: "
                    + String.valueOf(o));
        }
        addConfigured((ResourceCollection) o);
    }

   /**
    * Execute the AppendProjectPath task.
    */
    public void execute() {
        HashSet urls = new
HashSet(Arrays.asList(projectLoader.getURLs()));

        log(resources.size() + " resources to add",
Project.MSG_VERBOSE);

        for (Iterator iter = resources.iterator();
iter.hasNext();) {
            URL url = toURL(resolveRefs(iter.next()));
            if (!urls.add(url)) {
                continue;
            }
            try {
                log("Adding URL " + url + " to project
classpath",
                        Project.MSG_VERBOSE);
                ADD_URL.invoke(projectLoader, new
Object[] {url});
            } catch (Exception ex) {
                throw new BuildException("Unable to
add URL "
                        + url + " to the project
classpath", ex);
            }
        }
    }

    private URL toURL(Object o) {
        if (o instanceof URLResource) {
            return ((URLResource) o).getURL();
        }
        Throwable t = null;
        if (o instanceof FileResource) {
            try {
                return
FILE_UTILS.getFileURL(((FileResource) o).getFile());
            } catch (MalformedURLException e) {
                t = e;
            }
        }
        throw new BuildException(
                "Cannot extract URL from " +
String.valueOf(o), t);
    }

    private Object resolveRefs(Object arg) {
        if (!(arg instanceof DataType)) {
            return arg;
        }
        DataType dt = (DataType) arg;
        DataType.invokeCircularReferenceCheck(dt,
null, getProject());

        while (dt.isReference()) {
            Object o =
dt.getRefid().getReferencedObject(getProject());
            if (o instanceof DataType) {
                dt = (DataType) o;
            } else {
                return o;
            }
        }
        return dt;
    }

}


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org


Mime
View raw message