mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-07 22:15:45 +01:00
build plugin tree
This commit is contained in:
@@ -226,7 +226,7 @@ public class DefaultPluginLoader implements PluginLoader
|
||||
{
|
||||
injectionModules.add((Module) extensionClass.newInstance());
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (IllegalAccessException | InstantiationException ex)
|
||||
{
|
||||
logger.error("could not create instance of module", ex);
|
||||
}
|
||||
|
||||
191
scm-webapp/src/main/java/sonia/scm/plugin/PluginNode.java
Normal file
191
scm-webapp/src/main/java/sonia/scm/plugin/PluginNode.java
Normal file
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer. 2. Redistributions in
|
||||
* binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
|
||||
* nor the names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.plugin;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public final class PluginNode
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param plugin
|
||||
*/
|
||||
public PluginNode(ExplodedSmp plugin)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param node
|
||||
*/
|
||||
public void addChild(PluginNode node)
|
||||
{
|
||||
this.children.add(node);
|
||||
node.addParent(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param node
|
||||
*/
|
||||
private void addParent(PluginNode node)
|
||||
{
|
||||
this.parents.add(node);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public PluginNode getChild(final String id)
|
||||
{
|
||||
return Iterables.find(children, new Predicate<PluginNode>()
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean apply(PluginNode node)
|
||||
{
|
||||
return node.getId().equals(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<PluginNode> getChildren()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getId()
|
||||
{
|
||||
return plugin.getPlugin().getInformation().getId(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<PluginNode> getParents()
|
||||
{
|
||||
return parents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ExplodedSmp getPlugin()
|
||||
{
|
||||
return plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public PluginWrapper getWrapper()
|
||||
{
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param wrapper
|
||||
*/
|
||||
public void setWrapper(PluginWrapper wrapper)
|
||||
{
|
||||
this.wrapper = wrapper;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private final List<PluginNode> parents = Lists.newArrayList();
|
||||
|
||||
/** Field description */
|
||||
private final List<PluginNode> children = Lists.newArrayList();
|
||||
|
||||
/** Field description */
|
||||
private final ExplodedSmp plugin;
|
||||
|
||||
/** Field description */
|
||||
private PluginWrapper wrapper;
|
||||
}
|
||||
@@ -37,7 +37,6 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableList.Builder;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.hash.Hashing;
|
||||
|
||||
@@ -147,7 +146,7 @@ public final class PluginProcessor
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private static DefaultPluginClassLoader createClassLoader(
|
||||
private DefaultPluginClassLoader createClassLoader(
|
||||
ClassLoader parentClassLoader, Path directory)
|
||||
throws IOException
|
||||
{
|
||||
@@ -256,17 +255,97 @@ public final class PluginProcessor
|
||||
}
|
||||
|
||||
List<ExplodedSmp> smps = Lists.transform(dirs, new PathTransformer());
|
||||
Iterable<ExplodedSmp> smpOrdered = Ordering.natural().sortedCopy(smps);
|
||||
|
||||
Set<PluginWrapper> pluginWrappers = createPluginWrappers(classLoader,
|
||||
smpOrdered);
|
||||
logger.trace("start building plugin tree");
|
||||
|
||||
List<PluginNode> rootNodes = new PluginTree(smps).getRootNodes();
|
||||
|
||||
logger.trace("create plugin wrappers and build classloaders");
|
||||
|
||||
Set<PluginWrapper> wrappers = createPluginWrappers(classLoader, rootNodes);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("collected {} plugins", pluginWrappers.size());
|
||||
logger.debug("collected {} plugins", wrappers.size());
|
||||
}
|
||||
|
||||
return ImmutableSet.copyOf(pluginWrappers);
|
||||
return ImmutableSet.copyOf(wrappers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param plugins
|
||||
* @param classLoader
|
||||
* @param node
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private void appendPluginWrapper(Set<PluginWrapper> plugins,
|
||||
ClassLoader classLoader, PluginNode node)
|
||||
throws IOException
|
||||
{
|
||||
ExplodedSmp smp = node.getPlugin();
|
||||
|
||||
List<ClassLoader> parents = Lists.newArrayList();
|
||||
|
||||
for (PluginNode parent : node.getParents())
|
||||
{
|
||||
PluginWrapper wrapper = parent.getWrapper();
|
||||
|
||||
if (wrapper != null)
|
||||
{
|
||||
parents.add(wrapper.getClassLoader());
|
||||
}
|
||||
else
|
||||
{
|
||||
//J-
|
||||
throw new PluginLoadException(
|
||||
String.format(
|
||||
"parent %s of plugin %s is not ready", parent.getId(), node.getId()
|
||||
)
|
||||
);
|
||||
//J+
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PluginWrapper plugin =
|
||||
createPluginWrapper(createParentPluginClassLoader(classLoader, parents),
|
||||
smp.getPath());
|
||||
|
||||
if (plugin != null)
|
||||
{
|
||||
plugins.add(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param plugins
|
||||
* @param classLoader
|
||||
* @param nodes
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private void appendPluginWrappers(Set<PluginWrapper> plugins,
|
||||
ClassLoader classLoader, List<PluginNode> nodes)
|
||||
throws IOException
|
||||
{
|
||||
|
||||
// TODO fix plugin loading order
|
||||
for (PluginNode node : nodes)
|
||||
{
|
||||
appendPluginWrapper(plugins, classLoader, node);
|
||||
}
|
||||
|
||||
for (PluginNode node : nodes)
|
||||
{
|
||||
appendPluginWrappers(plugins, classLoader, node.getChildren());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -366,6 +445,37 @@ 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
|
||||
*
|
||||
@@ -407,26 +517,19 @@ public final class PluginProcessor
|
||||
*
|
||||
* @param classLoader
|
||||
* @param smps
|
||||
* @param rootNodes
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private Set<PluginWrapper> createPluginWrappers(ClassLoader classLoader,
|
||||
Iterable<ExplodedSmp> smps)
|
||||
List<PluginNode> rootNodes)
|
||||
throws IOException
|
||||
{
|
||||
Set<PluginWrapper> plugins = Sets.newHashSet();
|
||||
|
||||
for (ExplodedSmp smp : smps)
|
||||
{
|
||||
PluginWrapper plugin = createPluginWrapper(classLoader, smp.getPath());
|
||||
|
||||
if (plugin != null)
|
||||
{
|
||||
plugins.add(plugin);
|
||||
}
|
||||
}
|
||||
appendPluginWrappers(plugins, classLoader, rootNodes);
|
||||
|
||||
return plugins;
|
||||
}
|
||||
|
||||
210
scm-webapp/src/main/java/sonia/scm/plugin/PluginTree.java
Normal file
210
scm-webapp/src/main/java/sonia/scm/plugin/PluginTree.java
Normal file
@@ -0,0 +1,210 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer. 2. Redistributions in
|
||||
* binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
|
||||
* nor the names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.plugin;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Ordering;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public final class PluginTree
|
||||
{
|
||||
|
||||
/**
|
||||
* the logger for PluginTree
|
||||
*/
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(PluginTree.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param smps
|
||||
*/
|
||||
public PluginTree(ExplodedSmp... smps)
|
||||
{
|
||||
this(Arrays.asList(smps));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param smps
|
||||
*/
|
||||
public PluginTree(List<ExplodedSmp> smps)
|
||||
{
|
||||
Iterable<ExplodedSmp> smpOrdered = Ordering.natural().sortedCopy(smps);
|
||||
|
||||
for (ExplodedSmp smp : smpOrdered)
|
||||
{
|
||||
Plugin plugin = smp.getPlugin();
|
||||
PluginCondition condition = plugin.getCondition();
|
||||
|
||||
if ((condition == null) || condition.isSupported())
|
||||
{
|
||||
Set<String> dependencies = plugin.getDependencies();
|
||||
|
||||
if ((dependencies == null) || dependencies.isEmpty())
|
||||
{
|
||||
rootNodes.add(new PluginNode(smp));
|
||||
}
|
||||
else
|
||||
{
|
||||
appendNode(rootNodes, dependencies, smp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//J-
|
||||
throw new PluginConditionFailedException(
|
||||
condition,
|
||||
String.format(
|
||||
"could not load plugin %s, the plugin condition does not match",
|
||||
plugin.getInformation().getId()
|
||||
)
|
||||
);
|
||||
//J+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<PluginNode> getRootNodes()
|
||||
{
|
||||
return rootNodes;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param nodes
|
||||
* @param dependencies
|
||||
* @param smp
|
||||
*/
|
||||
private void appendNode(List<PluginNode> nodes, Set<String> dependencies,
|
||||
ExplodedSmp smp)
|
||||
{
|
||||
PluginNode child = new PluginNode(smp);
|
||||
|
||||
for (String dependency : dependencies)
|
||||
{
|
||||
if (!appendNode(nodes, child, dependency))
|
||||
{
|
||||
//J-
|
||||
throw new PluginNotInstalledException(
|
||||
String.format(
|
||||
"dependency %s of %s is not installed",
|
||||
dependency,
|
||||
child.getId()
|
||||
)
|
||||
);
|
||||
//J+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param nodes
|
||||
* @param child
|
||||
* @param dependency
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private boolean appendNode(List<PluginNode> nodes, PluginNode child,
|
||||
String dependency)
|
||||
{
|
||||
logger.debug("check for {} {}", dependency, child.getId());
|
||||
|
||||
boolean found = false;
|
||||
|
||||
for (PluginNode node : nodes)
|
||||
{
|
||||
if (node.getId().equals(dependency))
|
||||
{
|
||||
logger.debug("add plugin {} as child of {}", child.getId(),
|
||||
node.getId());
|
||||
node.addChild(child);
|
||||
found = true;
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (appendNode(node.getChildren(), child, dependency))
|
||||
{
|
||||
found = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private final List<PluginNode> rootNodes = Lists.newArrayList();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer. 2. Redistributions in
|
||||
* binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
|
||||
* nor the names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
package sonia.scm.plugin;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class PluginProcessorTest
|
||||
{
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temp = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void testBuildPluginTree() throws IOException
|
||||
{
|
||||
PluginProcessor processor = new PluginProcessor(temp.newFolder().toPath());
|
||||
}
|
||||
|
||||
}
|
||||
268
scm-webapp/src/test/java/sonia/scm/plugin/PluginTreeTest.java
Normal file
268
scm-webapp/src/test/java/sonia/scm/plugin/PluginTreeTest.java
Normal file
@@ -0,0 +1,268 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer. 2. Redistributions in
|
||||
* binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
|
||||
* nor the names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.plugin;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class PluginTreeTest
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test(expected = PluginConditionFailedException.class)
|
||||
public void testPluginConditionFailed() throws IOException
|
||||
{
|
||||
PluginCondition condition = new PluginCondition("999",
|
||||
new ArrayList<String>(), "hit");
|
||||
Plugin plugin = new Plugin(createInfo("a", "b", "1"), null, condition,
|
||||
null);
|
||||
ExplodedSmp smp = createSmp(plugin);
|
||||
|
||||
new PluginTree(smp).getRootNodes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test(expected = PluginNotInstalledException.class)
|
||||
public void testPluginNotInstalled() throws IOException
|
||||
{
|
||||
new PluginTree(createSmpWithDependency("b", "a")).getRootNodes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testRootNotes() throws IOException
|
||||
{
|
||||
List<ExplodedSmp> smps = createSmps("a", "b", "c");
|
||||
List<String> nodes = unwrapIds(new PluginTree(smps).getRootNodes());
|
||||
|
||||
assertThat(nodes, containsInAnyOrder("a:a", "b:b", "c:c"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testSimpleDependencies() throws IOException
|
||||
{
|
||||
//J-
|
||||
ExplodedSmp[] smps = new ExplodedSmp[] {
|
||||
createSmpWithDependency("a"),
|
||||
createSmpWithDependency("b", "a"),
|
||||
createSmpWithDependency("c", "a", "b")
|
||||
};
|
||||
//J+
|
||||
|
||||
PluginTree tree = new PluginTree(smps);
|
||||
List<PluginNode> rootNodes = tree.getRootNodes();
|
||||
|
||||
assertThat(unwrapIds(rootNodes), containsInAnyOrder("a:a"));
|
||||
|
||||
PluginNode a = rootNodes.get(0);
|
||||
|
||||
assertThat(unwrapIds(a.getChildren()), containsInAnyOrder("b:b", "c:c"));
|
||||
|
||||
PluginNode b = a.getChild("b:b");
|
||||
|
||||
assertThat(unwrapIds(b.getChildren()), containsInAnyOrder("c:c"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param groupId
|
||||
* @param artifactId
|
||||
* @param version
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private PluginInformation createInfo(String groupId, String artifactId,
|
||||
String version)
|
||||
{
|
||||
PluginInformation info = new PluginInformation();
|
||||
|
||||
info.setGroupId(groupId);
|
||||
info.setArtifactId(artifactId);
|
||||
info.setVersion(version);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param plugin
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private ExplodedSmp createSmp(Plugin plugin) throws IOException
|
||||
{
|
||||
return new ExplodedSmp(tempFolder.newFile().toPath(), plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private ExplodedSmp createSmp(String name) throws IOException
|
||||
{
|
||||
return createSmp(new Plugin(createInfo(name, name, "1.0.0"), null, null,
|
||||
null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* @param dependencies
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private ExplodedSmp createSmpWithDependency(String name,
|
||||
String... dependencies)
|
||||
throws IOException
|
||||
{
|
||||
Set<String> dependencySet = new HashSet<>();
|
||||
|
||||
for (String d : dependencies)
|
||||
{
|
||||
dependencySet.add(d.concat(":").concat(d));
|
||||
}
|
||||
|
||||
Plugin plugin = new Plugin(createInfo(name, name, "1"), null, null,
|
||||
dependencySet);
|
||||
|
||||
return createSmp(plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param names
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private List<ExplodedSmp> createSmps(String... names) throws IOException
|
||||
{
|
||||
List<ExplodedSmp> smps = Lists.newArrayList();
|
||||
|
||||
for (String name : names)
|
||||
{
|
||||
smps.add(createSmp(name));
|
||||
}
|
||||
|
||||
return smps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param nodes
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<String> unwrapIds(List<PluginNode> nodes)
|
||||
{
|
||||
return Lists.transform(nodes, new Function<PluginNode, String>()
|
||||
{
|
||||
|
||||
@Override
|
||||
public String apply(PluginNode input)
|
||||
{
|
||||
return input.getId();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
@Rule
|
||||
public TemporaryFolder tempFolder = new TemporaryFolder();
|
||||
}
|
||||
Reference in New Issue
Block a user