diff --git a/core/src/main/java/hudson/util/MaskingClassLoader.java b/core/src/main/java/hudson/util/MaskingClassLoader.java index 2a25910de5aee8bda6634b4d6303cd52e237aa4c..3220d30a5c43479f2d5ee19e1844532b07753726 100644 --- a/core/src/main/java/hudson/util/MaskingClassLoader.java +++ b/core/src/main/java/hudson/util/MaskingClassLoader.java @@ -23,6 +23,7 @@ */ package hudson.util; +import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -41,7 +42,9 @@ public class MaskingClassLoader extends ClassLoader { /** * Prefix of the packages that should be hidden. */ - private List masks; + private List masksClasses; + + private List masksResources; public MaskingClassLoader(ClassLoader parent, String... masks) { this(parent, Arrays.asList(masks)); @@ -49,12 +52,20 @@ public class MaskingClassLoader extends ClassLoader { public MaskingClassLoader(ClassLoader parent, Collection masks) { super(parent); - this.masks = new ArrayList(masks); + this.masksClasses = new ArrayList(masks); + this.masksResources = new ArrayList(); + + /** + * The name of a resource is a '/'-separated path name + */ + for (String mask : masks) { + masksResources.add(mask.replace(".","/")); + } } @Override protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - for (String mask : masks) { + for (String mask : masksClasses) { if(name.startsWith(mask)) throw new ClassNotFoundException(); } @@ -62,7 +73,20 @@ public class MaskingClassLoader extends ClassLoader { return super.loadClass(name, resolve); } + @Override + public synchronized URL getResource(String name) { + for (String mask : masksResources) { + if(name.startsWith(mask)) + return null; + } + + return super.getResource(name); + } + public synchronized void add(String prefix) { - masks.add(prefix); + masksClasses.add(prefix); + if(prefix !=null){ + masksResources.add(prefix.replace(".","/")); + } } } diff --git a/test/src/test/java/hudson/ClassicPluginStrategyTest.java b/test/src/test/java/hudson/ClassicPluginStrategyTest.java index 3080dd7028cb9d836c0d40cb9df995979023f7fe..8075984f168a01a5b65b3a8841757d902eae4501 100644 --- a/test/src/test/java/hudson/ClassicPluginStrategyTest.java +++ b/test/src/test/java/hudson/ClassicPluginStrategyTest.java @@ -1,19 +1,19 @@ /* * 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 @@ -26,6 +26,7 @@ package hudson; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.HudsonTestCase; +import org.jvnet.hudson.test.LenientRunnable; import org.jvnet.hudson.test.recipes.LocalData; import java.net.URL; @@ -87,4 +88,19 @@ public class ClassicPluginStrategyTest extends HudsonTestCase { fail("disabled dependency should not be included"); } } + + /** + * Test finding resources under masking. + * "foo1" plugin contains attribute of Mask-Classes: org.apache.http. + */ + @LocalData + @Issue("JENKINS-27289") + public void testMaskResourceClassLoader() throws Exception { + PluginWrapper pw = jenkins.getPluginManager().getPlugin("foo1"); + Class clazz = pw.classLoader.loadClass("org.apache.http.impl.io.SocketInputBuffer"); + ClassLoader cl = clazz.getClassLoader(); + URL url = cl.getResource("org/apache/http/impl/io/SocketInputBuffer.class"); + assert url != null; + assertTrue("expected to find the class from foo1 plugin", url.toString().contains("plugins/foo1")); + } } diff --git a/test/src/test/resources/hudson/ClassicPluginStrategyTest/testMaskResourceClassLoader.zip b/test/src/test/resources/hudson/ClassicPluginStrategyTest/testMaskResourceClassLoader.zip new file mode 100644 index 0000000000000000000000000000000000000000..75913a1b42977fa73c4f1a5528986291fe313dca Binary files /dev/null and b/test/src/test/resources/hudson/ClassicPluginStrategyTest/testMaskResourceClassLoader.zip differ