mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-01-26 09:19:12 +01:00
implement option for plugins to use child first classloaders
This commit is contained in:
@@ -70,14 +70,17 @@ public final class Plugin extends ScmModule
|
||||
* @param information
|
||||
* @param resources
|
||||
* @param condition
|
||||
* @param childFirstClassLoader
|
||||
* @param dependencies
|
||||
*/
|
||||
public Plugin(PluginInformation information, PluginResources resources,
|
||||
PluginCondition condition, Set<String> dependencies)
|
||||
PluginCondition condition, boolean childFirstClassLoader,
|
||||
Set<String> dependencies)
|
||||
{
|
||||
this.information = information;
|
||||
this.resources = resources;
|
||||
this.condition = condition;
|
||||
this.childFirstClassLoader = childFirstClassLoader;
|
||||
this.dependencies = dependencies;
|
||||
}
|
||||
|
||||
@@ -109,6 +112,7 @@ public final class Plugin extends ScmModule
|
||||
return Objects.equal(condition, other.condition)
|
||||
&& Objects.equal(information, other.information)
|
||||
&& Objects.equal(resources, other.resources)
|
||||
&& Objects.equal(childFirstClassLoader, other.childFirstClassLoader)
|
||||
&& Objects.equal(dependencies, other.dependencies);
|
||||
}
|
||||
|
||||
@@ -121,7 +125,8 @@ public final class Plugin extends ScmModule
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hashCode(condition, information, resources, dependencies);
|
||||
return Objects.hashCode(condition, information, resources,
|
||||
childFirstClassLoader, dependencies);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,6 +143,7 @@ public final class Plugin extends ScmModule
|
||||
.add("condition", condition)
|
||||
.add("information", information)
|
||||
.add("resources", resources)
|
||||
.add("childFirstClassLoader", childFirstClassLoader)
|
||||
.add("dependencies", dependencies)
|
||||
.toString();
|
||||
//J+
|
||||
@@ -196,8 +202,23 @@ public final class Plugin extends ScmModule
|
||||
return resources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isChildFirstClassLoader()
|
||||
{
|
||||
return childFirstClassLoader;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
@XmlElement(name = "child-first-classloader")
|
||||
private boolean childFirstClassLoader;
|
||||
|
||||
/** Field description */
|
||||
@XmlElement(name = "conditions")
|
||||
private PluginCondition condition;
|
||||
|
||||
@@ -135,77 +135,6 @@ public final class PluginProcessor
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param parentClassLoader
|
||||
* @param directory
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private DefaultPluginClassLoader createClassLoader(
|
||||
ClassLoader parentClassLoader, Path directory)
|
||||
throws IOException
|
||||
{
|
||||
List<URL> urls = new ArrayList<>();
|
||||
|
||||
Path metaDir = directory.resolve(DIRECTORY_METAINF);
|
||||
|
||||
if (!Files.exists(metaDir))
|
||||
{
|
||||
throw new FileNotFoundException("could not find META-INF directory");
|
||||
}
|
||||
|
||||
Path linkDir = directory.resolve(DIRECTORY_LINK);
|
||||
|
||||
if (!Files.exists(linkDir))
|
||||
{
|
||||
Files.createDirectory(linkDir);
|
||||
}
|
||||
|
||||
Path linkMetaDir = linkDir.resolve(DIRECTORY_METAINF);
|
||||
|
||||
if (!Files.exists(linkMetaDir))
|
||||
{
|
||||
Files.deleteIfExists(linkMetaDir);
|
||||
Files.createSymbolicLink(linkMetaDir, linkMetaDir.relativize(metaDir));
|
||||
}
|
||||
|
||||
urls.add(linkDir.toUri().toURL());
|
||||
|
||||
Path webinfDir = directory.resolve(DIRECTORY_WEBINF);
|
||||
|
||||
if (Files.exists(webinfDir))
|
||||
{
|
||||
Path classesDir = webinfDir.resolve(DIRECTORY_CLASSES);
|
||||
|
||||
if (Files.exists(classesDir))
|
||||
{
|
||||
urls.add(classesDir.toUri().toURL());
|
||||
}
|
||||
|
||||
Path libDir = webinfDir.resolve(DIRECTORY_DEPENDENCIES);
|
||||
|
||||
if (Files.exists(libDir))
|
||||
{
|
||||
for (Path f : Files.newDirectoryStream(libDir, GLOB_JAR))
|
||||
{
|
||||
urls.add(f.toUri().toURL());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//J-
|
||||
return new DefaultPluginClassLoader(
|
||||
urls.toArray(new URL[urls.size()]),
|
||||
parentClassLoader
|
||||
);
|
||||
//J+
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -313,7 +242,7 @@ public final class PluginProcessor
|
||||
|
||||
PluginWrapper plugin =
|
||||
createPluginWrapper(createParentPluginClassLoader(classLoader, parents),
|
||||
smp.getPath());
|
||||
smp);
|
||||
|
||||
if (plugin != null)
|
||||
{
|
||||
@@ -335,7 +264,7 @@ public final class PluginProcessor
|
||||
ClassLoader classLoader, List<PluginNode> nodes)
|
||||
throws IOException
|
||||
{
|
||||
|
||||
|
||||
// TODO fix plugin loading order
|
||||
for (PluginNode node : nodes)
|
||||
{
|
||||
@@ -402,6 +331,91 @@ public final class PluginProcessor
|
||||
return paths.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param parentClassLoader
|
||||
* @param directory
|
||||
* @param smp
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private ClassLoader createClassLoader(ClassLoader parentClassLoader,
|
||||
ExplodedSmp smp)
|
||||
throws IOException
|
||||
{
|
||||
List<URL> urls = new ArrayList<>();
|
||||
|
||||
Path metaDir = smp.getPath().resolve(DIRECTORY_METAINF);
|
||||
|
||||
if (!Files.exists(metaDir))
|
||||
{
|
||||
throw new FileNotFoundException("could not find META-INF directory");
|
||||
}
|
||||
|
||||
Path linkDir = smp.getPath().resolve(DIRECTORY_LINK);
|
||||
|
||||
if (!Files.exists(linkDir))
|
||||
{
|
||||
Files.createDirectory(linkDir);
|
||||
}
|
||||
|
||||
Path linkMetaDir = linkDir.resolve(DIRECTORY_METAINF);
|
||||
|
||||
if (!Files.exists(linkMetaDir))
|
||||
{
|
||||
Files.deleteIfExists(linkMetaDir);
|
||||
Files.createSymbolicLink(linkMetaDir, linkMetaDir.relativize(metaDir));
|
||||
}
|
||||
|
||||
urls.add(linkDir.toUri().toURL());
|
||||
|
||||
Path webinfDir = smp.getPath().resolve(DIRECTORY_WEBINF);
|
||||
|
||||
if (Files.exists(webinfDir))
|
||||
{
|
||||
Path classesDir = webinfDir.resolve(DIRECTORY_CLASSES);
|
||||
|
||||
if (Files.exists(classesDir))
|
||||
{
|
||||
urls.add(classesDir.toUri().toURL());
|
||||
}
|
||||
|
||||
Path libDir = webinfDir.resolve(DIRECTORY_DEPENDENCIES);
|
||||
|
||||
if (Files.exists(libDir))
|
||||
{
|
||||
for (Path f : Files.newDirectoryStream(libDir, GLOB_JAR))
|
||||
{
|
||||
urls.add(f.toUri().toURL());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ClassLoader classLoader;
|
||||
URL[] urlArray = urls.toArray(new URL[urls.size()]);
|
||||
Plugin plugin = smp.getPlugin();
|
||||
|
||||
if (smp.getPlugin().isChildFirstClassLoader())
|
||||
{
|
||||
logger.debug("create child fist classloader for plugin {}",
|
||||
plugin.getInformation().getId());
|
||||
classLoader = new ChildFirstPluginClassLoader(urlArray,
|
||||
parentClassLoader);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.debug("create parent fist classloader for plugin {}",
|
||||
plugin.getInformation().getId());
|
||||
classLoader = new DefaultPluginClassLoader(urlArray, parentClassLoader);
|
||||
}
|
||||
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -413,6 +427,37 @@ public final class PluginProcessor
|
||||
return new SimpleDateFormat(FORMAT_DATE).format(new Date());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param root
|
||||
* @param parents
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private ClassLoader createParentPluginClassLoader(ClassLoader root,
|
||||
List<ClassLoader> parents)
|
||||
{
|
||||
ClassLoader result;
|
||||
int size = parents.size();
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
result = root;
|
||||
}
|
||||
else if (size == 1)
|
||||
{
|
||||
result = parents.get(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = new MultiParentClassLoader(parents);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -445,62 +490,32 @@ public final class PluginProcessor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param root
|
||||
* @param parents
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private ClassLoader createParentPluginClassLoader(ClassLoader root,
|
||||
List<ClassLoader> parents)
|
||||
{
|
||||
ClassLoader result;
|
||||
int size = parents.size();
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
result = root;
|
||||
}
|
||||
else if (size == 1)
|
||||
{
|
||||
result = parents.get(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = new MultiParentClassLoader(parents);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param classLoader
|
||||
* @param directory
|
||||
* @param smp
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private PluginWrapper createPluginWrapper(ClassLoader classLoader,
|
||||
Path directory)
|
||||
ExplodedSmp smp)
|
||||
throws IOException
|
||||
{
|
||||
PluginWrapper wrapper = null;
|
||||
Path descriptor = directory.resolve(PluginConstants.FILE_DESCRIPTOR);
|
||||
Path descriptor = smp.getPath().resolve(PluginConstants.FILE_DESCRIPTOR);
|
||||
|
||||
if (Files.exists(descriptor))
|
||||
{
|
||||
ClassLoader cl = createClassLoader(classLoader, directory);
|
||||
ClassLoader cl = createClassLoader(classLoader, smp);
|
||||
|
||||
Plugin plugin = createPlugin(cl, descriptor);
|
||||
|
||||
wrapper = new PluginWrapper(plugin, cl, directory);
|
||||
wrapper = new PluginWrapper(plugin, cl, smp.getPath());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -135,7 +135,7 @@ public class ExplodedSmpTest
|
||||
info.setArtifactId(artifactId);
|
||||
info.setVersion(version);
|
||||
|
||||
Plugin plugin = new Plugin(info, null, null, Sets.newSet(dependencies));
|
||||
Plugin plugin = new Plugin(info, null, null, false, Sets.newSet(dependencies));
|
||||
|
||||
return new ExplodedSmp(null, plugin);
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public class PluginTreeTest
|
||||
PluginCondition condition = new PluginCondition("999",
|
||||
new ArrayList<String>(), "hit");
|
||||
Plugin plugin = new Plugin(createInfo("a", "b", "1"), null, condition,
|
||||
null);
|
||||
false, null);
|
||||
ExplodedSmp smp = createSmp(plugin);
|
||||
|
||||
new PluginTree(smp).getRootNodes();
|
||||
@@ -186,7 +186,7 @@ public class PluginTreeTest
|
||||
private ExplodedSmp createSmp(String name) throws IOException
|
||||
{
|
||||
return createSmp(new Plugin(createInfo(name, name, "1.0.0"), null, null,
|
||||
null));
|
||||
false, null));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,7 +212,7 @@ public class PluginTreeTest
|
||||
}
|
||||
|
||||
Plugin plugin = new Plugin(createInfo(name, name, "1"), null, null,
|
||||
dependencySet);
|
||||
false, dependencySet);
|
||||
|
||||
return createSmp(plugin);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user