diff --git a/core/src/main/java/hudson/ClassicPluginStrategy.java b/core/src/main/java/hudson/ClassicPluginStrategy.java index 7772ca4487b79c38d677cf236f55009646403ce7..8df5bab1a42c3d69635592da1d3fa1e2137c93b9 100644 --- a/core/src/main/java/hudson/ClassicPluginStrategy.java +++ b/core/src/main/java/hudson/ClassicPluginStrategy.java @@ -39,9 +39,12 @@ import java.io.Closeable; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; -import java.util.List; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; import java.util.jar.Manifest; import java.util.jar.Attributes; import java.util.logging.Logger; @@ -380,7 +383,20 @@ public class ClassicPluginStrategy implements PluginStrategy { throw new ClassNotFoundException(name); } - // TODO: delegate resources? watch out for diamond dependencies + @Override + protected Enumeration findResources(String name) throws IOException { + HashSet result = new HashSet(); + for (Dependency dep : dependencies) { + PluginWrapper p = pluginManager.getPlugin(dep.shortName); + if (p!=null) { + Enumeration urls = p.classLoader.getResources(name); + while (urls != null && urls.hasMoreElements()) + result.add(urls.nextElement()); + } + } + + return Collections.enumeration(result); + } @Override protected URL findResource(String name) { diff --git a/core/src/main/java/hudson/PluginWrapper.java b/core/src/main/java/hudson/PluginWrapper.java index b637c3720f9289d40b0e73456bfaddcab19cade1..2c0a5164149ddebcfbd9e3a472299b9c369663eb 100644 --- a/core/src/main/java/hudson/PluginWrapper.java +++ b/core/src/main/java/hudson/PluginWrapper.java @@ -37,6 +37,7 @@ import java.io.OutputStream; import java.io.Closeable; import java.net.URL; import java.util.ArrayList; +import java.util.Enumeration; import java.util.List; import java.util.jar.Manifest; import java.util.logging.Logger; @@ -192,7 +193,15 @@ public final class PluginWrapper implements Comparable { * Returns the URL of the index page jelly script. */ public URL getIndexPage() { - return classLoader.getResource("index.jelly"); + // In the current impl dependencies are checked first, so the plugin itself + // will add the last entry in the getResources result. + URL idx = null; + try { + Enumeration en = classLoader.getResources("index.jelly"); + while (en.hasMoreElements()) + idx = en.nextElement(); + } catch (IOException ignore) { } + return idx; } private String computeShortName(Manifest manifest, File archive) { diff --git a/test/src/test/java/hudson/ClassicPluginStrategyTest.java b/test/src/test/java/hudson/ClassicPluginStrategyTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8af56a2a998ab010715c485f03777af9f5f6de01 --- /dev/null +++ b/test/src/test/java/hudson/ClassicPluginStrategyTest.java @@ -0,0 +1,73 @@ +/* + * The MIT License + * + * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, + * Alan Harder + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson; + +import hudson.PluginWrapper; +import org.jvnet.hudson.test.HudsonTestCase; +import org.jvnet.hudson.test.recipes.LocalData; + +import java.io.File; +import java.net.URL; +import java.util.Enumeration; + +/** + * @author Alan Harder + */ +public class ClassicPluginStrategyTest extends HudsonTestCase { + + @Override + protected void setUp() throws Exception { + useLocalPluginManager = true; + super.setUp(); + } + + /** + * Test finding resources via DependencyClassLoader. + */ + @LocalData + public void testDependencyClassLoader() throws Exception { + // Test data has: foo3 depends on foo2,foo1; foo2 depends on foo1 + // (thus findResources from foo3 can find foo1 resources via 2 dependency paths) + PluginWrapper p = hudson.getPluginManager().getPlugin("foo3"); + String res = p.getIndexPage().toString(); + assertTrue(res + "should be foo3", res.contains("/foo3/")); + + // In the current impl, the dependencies are the parent ClassLoader so resources + // are found there before checking the plugin itself. Adjust the expected results + // below if this is ever changed to check the plugin first. + Enumeration en = p.classLoader.getResources("index.jelly"); + for (int i = 0; en.hasMoreElements(); i++) { + res = en.nextElement().toString(); + if (i < 2) + assertTrue("In current impl, " + res + "should be foo1 or foo2", + res.contains("/foo1/") || res.contains("/foo2/")); + else + assertTrue("In current impl, " + res + "should be foo3", res.contains("/foo3/")); + } + res = p.classLoader.getResource("index.jelly").toString(); + assertTrue("In current impl, " + res + " should be foo1 or foo2", + res.contains("/foo1/") || res.contains("/foo2/")); + } +} diff --git a/test/src/test/resources/hudson/ClassicPluginStrategyTest/testDependencyClassLoader.zip b/test/src/test/resources/hudson/ClassicPluginStrategyTest/testDependencyClassLoader.zip new file mode 100644 index 0000000000000000000000000000000000000000..63ebd2dc442beae0df1cea754e95e77f73ea00ee Binary files /dev/null and b/test/src/test/resources/hudson/ClassicPluginStrategyTest/testDependencyClassLoader.zip differ