提交 caedb49c 编写于 作者: J Jesse Glick

[JENKINS-27289] Noting merge of #1598.

...@@ -55,7 +55,9 @@ Upcoming changes</a> ...@@ -55,7 +55,9 @@ Upcoming changes</a>
<!-- Record your changes in the trunk here. --> <!-- Record your changes in the trunk here. -->
<div id="trunk" style="display:none"><!--=TRUNK-BEGIN=--> <div id="trunk" style="display:none"><!--=TRUNK-BEGIN=-->
<ul class=image> <ul class=image>
<li class=> <li class=bug>
Plugins using class loader masking did not work properly over the slave channel.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-27289">issue 27289</a>)
</ul> </ul>
</div><!--=TRUNK-END=--> </div><!--=TRUNK-END=-->
<h3><a name=v1.613>What's new in 1.613</a> (2015/05/10)</h3> <h3><a name=v1.613>What's new in 1.613</a> (2015/05/10)</h3>
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
*/ */
package hudson.util; package hudson.util;
import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
...@@ -41,7 +42,9 @@ public class MaskingClassLoader extends ClassLoader { ...@@ -41,7 +42,9 @@ public class MaskingClassLoader extends ClassLoader {
/** /**
* Prefix of the packages that should be hidden. * Prefix of the packages that should be hidden.
*/ */
private List<String> masks; private final List<String> masksClasses = new ArrayList<String>();
private final List<String> masksResources = new ArrayList<String>();
public MaskingClassLoader(ClassLoader parent, String... masks) { public MaskingClassLoader(ClassLoader parent, String... masks) {
this(parent, Arrays.asList(masks)); this(parent, Arrays.asList(masks));
...@@ -49,12 +52,19 @@ public class MaskingClassLoader extends ClassLoader { ...@@ -49,12 +52,19 @@ public class MaskingClassLoader extends ClassLoader {
public MaskingClassLoader(ClassLoader parent, Collection<String> masks) { public MaskingClassLoader(ClassLoader parent, Collection<String> masks) {
super(parent); super(parent);
this.masks = new ArrayList<String>(masks); this.masksClasses.addAll(masks);
/**
* The name of a resource is a '/'-separated path name
*/
for (String mask : masks) {
masksResources.add(mask.replace(".","/"));
}
} }
@Override @Override
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
for (String mask : masks) { for (String mask : masksClasses) {
if(name.startsWith(mask)) if(name.startsWith(mask))
throw new ClassNotFoundException(); throw new ClassNotFoundException();
} }
...@@ -62,7 +72,20 @@ public class MaskingClassLoader extends ClassLoader { ...@@ -62,7 +72,20 @@ public class MaskingClassLoader extends ClassLoader {
return super.loadClass(name, resolve); 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) { public synchronized void add(String prefix) {
masks.add(prefix); masksClasses.add(prefix);
if(prefix !=null){
masksResources.add(prefix.replace(".","/"));
}
} }
} }
/* /*
* The MIT License * The MIT License
* *
* Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi,
* Alan Harder * Alan Harder
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
...@@ -26,6 +26,7 @@ package hudson; ...@@ -26,6 +26,7 @@ package hudson;
import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.HudsonTestCase; import org.jvnet.hudson.test.HudsonTestCase;
import org.jvnet.hudson.test.LenientRunnable;
import org.jvnet.hudson.test.recipes.LocalData; import org.jvnet.hudson.test.recipes.LocalData;
import java.net.URL; import java.net.URL;
...@@ -87,4 +88,19 @@ public class ClassicPluginStrategyTest extends HudsonTestCase { ...@@ -87,4 +88,19 @@ public class ClassicPluginStrategyTest extends HudsonTestCase {
fail("disabled dependency should not be included"); 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");
assertNotNull(url);
assertTrue("expected to find the class from foo1 plugin", url.toString().contains("plugins/foo1"));
}
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册