implement option for plugins to use child first classloaders

This commit is contained in:
Sebastian Sdorra
2014-08-19 21:01:11 +02:00
parent e569d916e9
commit 301cc19290
4 changed files with 150 additions and 114 deletions

View File

@@ -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;

View File

@@ -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
{

View File

@@ -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);
}

View File

@@ -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);
}