ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Peter Reilly" <peter.kitt.rei...@gmail.com>
Subject Re: classloader for 1.7
Date Tue, 12 Sep 2006 20:20:21 GMT
There is the task:
I  am not too sure if I am using the new ResourceCollection stuff
correctly!

Peter


/*
 * Copyright  2006 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.lang.reflect.Method;

import java.util.Set;
import java.util.HashSet;

import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
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.URLResource;
import org.apache.tools.ant.util.FileUtils;

/**
 * A Task to extend the project class path.
 * This task 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();

    /**
     * URLS in the attributes and the nested elements
     */
    private List urls = new ArrayList();

    //  ---    fields used in the execute method ---

    /**
     * Set used to ensure that a URL is only used once
     */
    private Set urlSet;

    /**
     * The addURL method on URLClassLoader
     */
    private Method addURLMethod;

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

    /**
     * A nested element class. The element is "url" and
     * it has one attribute - "url", this is a required
     * attribute.
     */
    public static class URLElement {
        private String urlString;

        /**
         * Set the url.
         *
         * @param urlString the value to set.
         */
        public void setURL(String urlString) {
            this.urlString = urlString;
        }

        /**
         * Get the url.
         *
         * @return the url string.
         */
        public String getURL() {
            if (urlString == null) {
                throw new BuildException(
                        "Missing required attribute url "
                                + "for nested url element");
            }
            return urlString;
        }
    }

    /**
     * Add a url to the list of urls.
     * This is an attribute of the task.
     *
     * @param urlString the value.
     */
    public void setURL(String urlString) {
        URL url;
        try {
            url = new URL(urlString);
        } catch (Exception ex) {
            throw new BuildException(
                    "Unable to convert to URL " + urlString);
        }
        urls.add(url);
    }

    /**
     * Handle a nested url element.
     * Get the url from it and call setURL to add to the
     * list of URLs.
     *
     * @param el the nested url element.
     */
    public void addConfiguredURL(URLElement el) {
        String urlString = el.getURL();
        setURL(urlString);
    }


    /**
     * Handle a nested resource collection.
     * Get the pathelements for the path, convert
     * them to url strings and call setURL to add
     * them to the list of urls.
     *
     * @param collection a nested path element.
     */
    public void addConfigured(ResourceCollection collection) {
        for (Iterator iter = collection.iterator(); iter.hasNext();) {
            Resource r = (Resource) iter.next();
            if (r instanceof FileResource) {
                FileResource file = (FileResource) r;
                String filePath = file.toString();
                try {
                    setURL(FILE_UTILS.toURI(file.toString()));
                } catch (Exception ex) {
                    throw new BuildException(
                        "Unable to convert to URL " + filePath);
                }
            } else if (r instanceof URLResource) {
                URLResource urlResource = (URLResource) r;
                urls.add(urlResource.getURL());
            } else if (r.isReference()) {
                addConfigured(r);
            } else {
                throw new BuildException(
                        "Do not know how do deal with " + r.getClass());
            }
        }
    }

    /**
     * Handle the "path" attribute.
     * This converts the path string to a Path object
     * and uses addConfigured(Path) to add the URLs.
     *
     * @param path a path string.
     */
    public void setPath(String path) {
        addConfigured(new Path(getProject(), path));
    }

    /**
     * Handle the "pathref" attribute.
     * This method adds the path referenced by the reference.
     *
     * @param ref a reference to an existing path.
     */

    public void setPathRef(Reference ref) {
        Path path = new Path(getProject());
        path.setRefid(ref);
        addConfigured(path);
    }

   /**
     * The execute method for the task.
     * This gets the addURL method, gets the project classloader,
     * iterates over the urls and appends them to the project classloader.
     */
    public void execute() {
        this.urlSet = new HashSet();
        this.addURLMethod = findAddURLMethod();
        this.projectLoader = findProjectLoader();
        populateCurrentURLS();
        for (Iterator iter = urls.iterator(); iter.hasNext();) {
            appendURLToProject((URL) iter.next());
        }
    }

    /**
     * Get the addURL method of the URLClassLoader class.
     * Change the accessiblity to true and return the method.
     * @return the addURL method.
     */
    private Method findAddURLMethod() {
        try {
            addURLMethod = URLClassLoader.class.getDeclaredMethod("addURL",
                    new Class[]{URL.class});
            addURLMethod.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);
        }
        return addURLMethod;
    }

    /**
     * Append a url to the project classloader using the
     * addURL method. If the url is alreaded added, do nothing.
     * @param url the url to append to the classloader.
     */
    private void appendURLToProject(URL url) {
        if (!urlSet.add(url)) {
            return;
        }
        try {
            addURLMethod.invoke(projectLoader, new Object[]{url});
        } catch (Exception ex) {
            throw new BuildException(
                    "Unable to add URL " + url + " to the project
classpath",
                    ex);
        }
    }

    /**
     * Populate the set of urls in the project classloader.
     */
    private void populateCurrentURLS() {
        URL[] urls = projectLoader.getURLs();
        for (int i = 0; i < urls.length; ++i) {
            urlSet.add(urls[i]);
        }
    }

    /**
     * Get the classloader of the Project class
     * and check that it is a URLClassLoader.
     * @return the project classloader.
     * @throws BuildException if the project classlaoder is not a
URLClassLoader.
     */
    private URLClassLoader findProjectLoader() {
        ClassLoader loader = getProject().getClass().getClassLoader();
        if (!(loader instanceof URLClassLoader)) {
            throw new BuildException(
                    "project classloader is not a URLClassLoader");
        }
        return (URLClassLoader) loader;
    }
}


On 9/12/06, Matt Benson <gudnabrsam@yahoo.com> wrote:
>
> The subject line is manually entered b/c I no longer
> have the mails from the original thread; I'm hoping
> the mail archive will do the right thing anyway.  So
> (and I make no pretense that this isn't DIRECTLY
> related to my other thread)...
>
> Peter, what's the status of your simplified extension
> task prototype described here:
>
> http://marc.theaimsgroup.com/?l=ant-dev&m=115695299516537&w=2
>
> ?
>
> Thanks,
> Matt
>
> __________________________________________________
> 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
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message