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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]