提交 87e2a7e8 编写于 作者: I ikedam

[FIXED JENKINS-19976] Enable plugins to load classes from optionally depending...

[FIXED JENKINS-19976] Enable plugins to load classes from optionally depending plugins even without restarting after depended ones installed.
上级 c0d67f5e
......@@ -377,6 +377,45 @@ public class ClassicPluginStrategy implements PluginStrategy {
plugin.getPlugin().start();
}
/**
* Called when a plugin is deployed, and there is a plugin optionally depending on that plugin.
* The class loader of the existing depending plugin should be updated
* to load classes from the newly deployed plugin.
*
* @param depender the plugin to update its class loader
* @param dependee
* @see hudson.PluginStrategy#updateDependency(hudson.PluginWrapper, hudson.PluginWrapper)
*/
@Override
public void updateDependency(PluginWrapper depender, PluginWrapper dependee) {
DependencyClassLoader classLoader = findAncestorDependencyClassLoader(depender.classLoader);
if (classLoader != null) {
classLoader.updateTransientDependencies();
LOGGER.log(Level.INFO, "Updated dependency of {0}", depender.getShortName());
}
}
private DependencyClassLoader findAncestorDependencyClassLoader(ClassLoader classLoader)
{
for (; classLoader != null; classLoader = classLoader.getParent()) {
if (classLoader instanceof DependencyClassLoader) {
return (DependencyClassLoader)classLoader;
}
if (classLoader instanceof AntClassLoader) {
// AntClassLoaders hold parents not only as AntClassLoader#getParent()
// but also as AntClassLoader#getConfiguredParent()
DependencyClassLoader ret = findAncestorDependencyClassLoader(
((AntClassLoader)classLoader).getConfiguredParent()
);
if (ret != null) {
return ret;
}
}
}
return null;
}
private static File resolve(File base, String relative) {
File rel = new File(relative);
if(rel.isAbsolute())
......@@ -523,6 +562,11 @@ public class ClassicPluginStrategy implements PluginStrategy {
this.dependencies = dependencies;
}
private void updateTransientDependencies() {
// This will be recalculated at the next time.
transientDependencies = null;
}
private List<PluginWrapper> getTransitiveDependencies() {
if (transientDependencies==null) {
CyclicGraphDetector<PluginWrapper> cgd = new CyclicGraphDetector<PluginWrapper>() {
......
......@@ -450,6 +450,23 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas
} catch (ReactorException e) {
throw new IOException("Failed to initialize "+ sn +" plugin",e);
}
// recalculate dependencies of plugins optionally depending the newly deployed one.
for (PluginWrapper depender: plugins) {
if (depender.equals(p)) {
// skip itself.
continue;
}
for (Dependency d: depender.getOptionalDependencies()) {
if (d.shortName.equals(p.getShortName())) {
// this plugin depends on the newly loaded one!
// recalculate dependencies!
getPluginStrategy().updateDependency(depender, p);
break;
}
}
}
LOGGER.info("Plugin " + sn + " dynamically installed");
}
......
......@@ -77,4 +77,12 @@ public interface PluginStrategy extends ExtensionPoint {
* @since 1.400
*/
<T> List<ExtensionComponent<T>> findComponents(Class<T> type, Hudson hudson);
/**
* Called when a plugin that is depended by another plugin is newly deployed.
*
* @param depender plugin depending on dependee.
* @param dependee newly loaded plugin.
*/
void updateDependency(PluginWrapper depender, PluginWrapper dependee);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册