mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-18 03:01:05 +01:00
create new simplified PluginManager API
This commit is contained in:
20
scm-core/src/main/java/sonia/scm/plugin/AvailablePlugin.java
Normal file
20
scm-core/src/main/java/sonia/scm/plugin/AvailablePlugin.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package sonia.scm.plugin;
|
||||||
|
|
||||||
|
public class AvailablePlugin implements Plugin {
|
||||||
|
|
||||||
|
private final AvailablePluginDescriptor pluginDescriptor;
|
||||||
|
|
||||||
|
public AvailablePlugin(AvailablePluginDescriptor pluginDescriptor) {
|
||||||
|
this.pluginDescriptor = pluginDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AvailablePluginDescriptor getDescriptor() {
|
||||||
|
return pluginDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PluginState getState() {
|
||||||
|
return PluginState.AVAILABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package sonia.scm.plugin;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public class AvailablePluginDescriptor implements PluginDescriptor {
|
||||||
|
|
||||||
|
private final PluginInformation information;
|
||||||
|
private final PluginCondition condition;
|
||||||
|
private final Set<String> dependencies;
|
||||||
|
|
||||||
|
public AvailablePluginDescriptor(PluginInformation information, PluginCondition condition, Set<String> dependencies) {
|
||||||
|
this.information = information;
|
||||||
|
this.condition = condition;
|
||||||
|
this.dependencies = dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PluginInformation getInformation() {
|
||||||
|
return information;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PluginCondition getCondition() {
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getDependencies() {
|
||||||
|
return dependencies;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -52,7 +52,7 @@ import java.util.Set;
|
|||||||
*
|
*
|
||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
*/
|
*/
|
||||||
@XmlRootElement
|
@XmlRootElement(name = "plugin")
|
||||||
@XmlAccessorType(XmlAccessType.FIELD)
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
public final class InstalledPluginDescriptor extends ScmModule implements PluginDescriptor
|
public final class InstalledPluginDescriptor extends ScmModule implements PluginDescriptor
|
||||||
{
|
{
|
||||||
@@ -247,6 +247,7 @@ public final class InstalledPluginDescriptor extends ScmModule implements Plugin
|
|||||||
private Set<String> dependencies;
|
private Set<String> dependencies;
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
|
@XmlElement(name = "information")
|
||||||
private PluginInformation information;
|
private PluginInformation information;
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
|
|||||||
@@ -1,120 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.xml.bind.annotation.XmlAccessType;
|
|
||||||
import javax.xml.bind.annotation.XmlAccessorType;
|
|
||||||
import javax.xml.bind.annotation.XmlElement;
|
|
||||||
import javax.xml.bind.annotation.XmlElementWrapper;
|
|
||||||
import javax.xml.bind.annotation.XmlRootElement;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Sebastian Sdorra
|
|
||||||
*/
|
|
||||||
@XmlRootElement(name = "plugin-center")
|
|
||||||
@XmlAccessorType(XmlAccessType.FIELD)
|
|
||||||
public class PluginCenter implements Serializable
|
|
||||||
{
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private static final long serialVersionUID = -6414175308610267397L;
|
|
||||||
|
|
||||||
//~--- get methods ----------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Set<PluginInformation> getPlugins()
|
|
||||||
{
|
|
||||||
return plugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Set<PluginRepository> getRepositories()
|
|
||||||
{
|
|
||||||
return repositories;
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- set methods ----------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param plugins
|
|
||||||
*/
|
|
||||||
public void setPlugins(Set<PluginInformation> plugins)
|
|
||||||
{
|
|
||||||
this.plugins = plugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param repositories
|
|
||||||
*/
|
|
||||||
public void setRepositories(Set<PluginRepository> repositories)
|
|
||||||
{
|
|
||||||
this.repositories = repositories;
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- fields ---------------------------------------------------------------
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
@XmlElement(name = "plugin")
|
|
||||||
@XmlElementWrapper(name = "plugins")
|
|
||||||
private Set<PluginInformation> plugins = new HashSet<PluginInformation>();
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
@XmlElement(name = "repository")
|
|
||||||
@XmlElementWrapper(name = "repositories")
|
|
||||||
private Set<PluginRepository> repositories = new HashSet<PluginRepository>();
|
|
||||||
}
|
|
||||||
@@ -71,7 +71,6 @@ public class PluginInformation implements PermissionObject, Validateable, Clonea
|
|||||||
private String category;
|
private String category;
|
||||||
private String avatarUrl;
|
private String avatarUrl;
|
||||||
private PluginCondition condition;
|
private PluginCondition condition;
|
||||||
private PluginState state;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PluginInformation clone() {
|
public PluginInformation clone() {
|
||||||
@@ -83,7 +82,6 @@ public class PluginInformation implements PermissionObject, Validateable, Clonea
|
|||||||
clone.setAuthor(author);
|
clone.setAuthor(author);
|
||||||
clone.setCategory(category);
|
clone.setCategory(category);
|
||||||
clone.setAvatarUrl(avatarUrl);
|
clone.setAvatarUrl(avatarUrl);
|
||||||
clone.setState(state);
|
|
||||||
if (condition != null) {
|
if (condition != null) {
|
||||||
clone.setCondition(condition.clone());
|
clone.setCondition(condition.clone());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,101 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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 sonia.scm.util.Util;
|
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Sebastian Sdorra
|
|
||||||
* @since 1.6
|
|
||||||
*/
|
|
||||||
public class PluginInformationComparator
|
|
||||||
implements Comparator<PluginInformation>, Serializable
|
|
||||||
{
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
public static final PluginInformationComparator INSTANCE =
|
|
||||||
new PluginInformationComparator();
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private static final long serialVersionUID = -8339752498853225668L;
|
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param plugin
|
|
||||||
* @param other
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int compare(PluginInformation plugin, PluginInformation other)
|
|
||||||
{
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
result = Util.compare(plugin.getName(), other.getName());
|
|
||||||
|
|
||||||
if (result == 0)
|
|
||||||
{
|
|
||||||
PluginState state = plugin.getState();
|
|
||||||
PluginState otherState = other.getState();
|
|
||||||
|
|
||||||
if ((state != null) && (otherState != null))
|
|
||||||
{
|
|
||||||
result = state.getCompareValue() - otherState.getCompareValue();
|
|
||||||
}
|
|
||||||
else if ((state == null) && (otherState != null))
|
|
||||||
{
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
else if ((state != null) && (otherState == null))
|
|
||||||
{
|
|
||||||
result = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -33,113 +33,50 @@
|
|||||||
|
|
||||||
package sonia.scm.plugin;
|
package sonia.scm.plugin;
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import com.google.common.base.Predicate;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* The plugin manager is responsible for plugin related tasks, such as install, uninstall or updating.
|
||||||
*
|
*
|
||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
*/
|
*/
|
||||||
public interface PluginManager
|
public interface PluginManager {
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Returns the available plugin with the given name.
|
||||||
*
|
* @param name of plugin
|
||||||
|
* @return optional available plugin.
|
||||||
*/
|
*/
|
||||||
public void clearCache();
|
Optional<AvailablePlugin> getAvailable(String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Returns the installed plugin with the given name.
|
||||||
*
|
* @param name of plugin
|
||||||
*
|
* @return optional installed plugin.
|
||||||
* @param id
|
|
||||||
*/
|
*/
|
||||||
public void install(String id);
|
Optional<InstalledPlugin> getInstalled(String name);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Installs a plugin package from a inputstream.
|
* Returns all installed plugins.
|
||||||
*
|
*
|
||||||
*
|
* @return a list of installed plugins.
|
||||||
* @param packageStream package input stream
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
* @since 1.21
|
|
||||||
*/
|
*/
|
||||||
public void installPackage(InputStream packageStream) throws IOException;
|
List<InstalledPlugin> getInstalled();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Returns all available plugins. The list contains the plugins which are loaded from the plugin center, but without
|
||||||
|
* the installed plugins.
|
||||||
*
|
*
|
||||||
*
|
* @return a list of available plugins.
|
||||||
* @param id
|
|
||||||
*/
|
*/
|
||||||
public void uninstall(String id);
|
List<AvailablePlugin> getAvailable();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Installs the plugin with the given name from the list of available plugins.
|
||||||
*
|
*
|
||||||
*
|
* @param name plugin name
|
||||||
* @param id
|
|
||||||
*/
|
*/
|
||||||
public void update(String id);
|
void install(String name);
|
||||||
|
|
||||||
//~--- get methods ----------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public PluginInformation get(String id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param filter
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Collection<PluginInformation> get(Predicate<PluginInformation> filter);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Collection<PluginInformation> getAll();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Collection<PluginInformation> getAvailable();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Collection<PluginInformation> getAvailableUpdates();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Collection<PluginInformation> getInstalled();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,160 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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.MoreObjects;
|
|
||||||
import com.google.common.base.Objects;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Sebastian Sdorra
|
|
||||||
*/
|
|
||||||
public class PluginRepository implements Serializable
|
|
||||||
{
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private static final long serialVersionUID = -9504354306304731L;
|
|
||||||
|
|
||||||
//~--- constructors ---------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs ...
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
PluginRepository() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs ...
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
* @param url
|
|
||||||
*/
|
|
||||||
public PluginRepository(String id, String url)
|
|
||||||
{
|
|
||||||
this.id = id;
|
|
||||||
this.url = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param obj
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj)
|
|
||||||
{
|
|
||||||
if (obj == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getClass() != obj.getClass())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final PluginRepository other = (PluginRepository) obj;
|
|
||||||
|
|
||||||
return Objects.equal(id, other.id) && Objects.equal(url, other.url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int hashCode()
|
|
||||||
{
|
|
||||||
return Objects.hashCode(id, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return MoreObjects.toStringHelper(this).add("id", id).add("url",
|
|
||||||
url).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- get methods ----------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getId()
|
|
||||||
{
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getUrl()
|
|
||||||
{
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- fields ---------------------------------------------------------------
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private String id;
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private String url;
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Sebastian Sdorra
|
|
||||||
*/
|
|
||||||
public class StatePluginPredicate implements Predicate<PluginInformation>
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs ...
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param state
|
|
||||||
*/
|
|
||||||
public StatePluginPredicate(PluginState state)
|
|
||||||
{
|
|
||||||
this.state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param plugin
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean apply(PluginInformation plugin)
|
|
||||||
{
|
|
||||||
return state == plugin.getState();
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- fields ---------------------------------------------------------------
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private final PluginState state;
|
|
||||||
}
|
|
||||||
@@ -3,11 +3,10 @@ package sonia.scm.api.v2.resources;
|
|||||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||||
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
||||||
|
import sonia.scm.plugin.AvailablePlugin;
|
||||||
import sonia.scm.plugin.InstalledPluginDescriptor;
|
import sonia.scm.plugin.InstalledPluginDescriptor;
|
||||||
import sonia.scm.plugin.PluginInformation;
|
|
||||||
import sonia.scm.plugin.PluginManager;
|
import sonia.scm.plugin.PluginManager;
|
||||||
import sonia.scm.plugin.PluginPermissions;
|
import sonia.scm.plugin.PluginPermissions;
|
||||||
import sonia.scm.plugin.PluginState;
|
|
||||||
import sonia.scm.web.VndMediaType;
|
import sonia.scm.web.VndMediaType;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -18,9 +17,8 @@ import javax.ws.rs.Path;
|
|||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import java.util.Collection;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static sonia.scm.ContextEntry.ContextBuilder.entity;
|
import static sonia.scm.ContextEntry.ContextBuilder.entity;
|
||||||
import static sonia.scm.NotFoundException.notFound;
|
import static sonia.scm.NotFoundException.notFound;
|
||||||
@@ -53,11 +51,8 @@ public class AvailablePluginResource {
|
|||||||
@Produces(VndMediaType.PLUGIN_COLLECTION)
|
@Produces(VndMediaType.PLUGIN_COLLECTION)
|
||||||
public Response getAvailablePlugins() {
|
public Response getAvailablePlugins() {
|
||||||
PluginPermissions.read().check();
|
PluginPermissions.read().check();
|
||||||
Collection<PluginInformation> plugins = pluginManager.getAvailable()
|
List<AvailablePlugin> available = pluginManager.getAvailable();
|
||||||
.stream()
|
return Response.ok(collectionMapper.mapAvailable(available)).build();
|
||||||
.filter(plugin -> plugin.getState().equals(PluginState.AVAILABLE))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
return Response.ok(collectionMapper.map(plugins)).build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,7 +61,7 @@ public class AvailablePluginResource {
|
|||||||
* @return available plugin.
|
* @return available plugin.
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path("/{name}/{version}")
|
@Path("/{name}")
|
||||||
@StatusCodes({
|
@StatusCodes({
|
||||||
@ResponseCode(code = 200, condition = "success"),
|
@ResponseCode(code = 200, condition = "success"),
|
||||||
@ResponseCode(code = 404, condition = "not found"),
|
@ResponseCode(code = 404, condition = "not found"),
|
||||||
@@ -74,12 +69,9 @@ public class AvailablePluginResource {
|
|||||||
})
|
})
|
||||||
@TypeHint(PluginDto.class)
|
@TypeHint(PluginDto.class)
|
||||||
@Produces(VndMediaType.PLUGIN)
|
@Produces(VndMediaType.PLUGIN)
|
||||||
public Response getAvailablePlugin(@PathParam("name") String name, @PathParam("version") String version) {
|
public Response getAvailablePlugin(@PathParam("name") String name) {
|
||||||
PluginPermissions.read().check();
|
PluginPermissions.read().check();
|
||||||
Optional<PluginInformation> plugin = pluginManager.getAvailable()
|
Optional<AvailablePlugin> plugin = pluginManager.getAvailable(name);
|
||||||
.stream()
|
|
||||||
.filter(p -> p.getId().equals(name + ":" + version))
|
|
||||||
.findFirst();
|
|
||||||
if (plugin.isPresent()) {
|
if (plugin.isPresent()) {
|
||||||
return Response.ok(mapper.map(plugin.get())).build();
|
return Response.ok(mapper.map(plugin.get())).build();
|
||||||
} else {
|
} else {
|
||||||
@@ -90,19 +82,18 @@ public class AvailablePluginResource {
|
|||||||
/**
|
/**
|
||||||
* Triggers plugin installation.
|
* Triggers plugin installation.
|
||||||
* @param name plugin artefact name
|
* @param name plugin artefact name
|
||||||
* @param version plugin version
|
|
||||||
* @return HTTP Status.
|
* @return HTTP Status.
|
||||||
*/
|
*/
|
||||||
@POST
|
@POST
|
||||||
@Path("/{name}/{version}/install")
|
@Path("/{name}/install")
|
||||||
@Consumes(VndMediaType.PLUGIN)
|
@Consumes(VndMediaType.PLUGIN)
|
||||||
@StatusCodes({
|
@StatusCodes({
|
||||||
@ResponseCode(code = 200, condition = "success"),
|
@ResponseCode(code = 200, condition = "success"),
|
||||||
@ResponseCode(code = 500, condition = "internal server error")
|
@ResponseCode(code = 500, condition = "internal server error")
|
||||||
})
|
})
|
||||||
public Response installPlugin(@PathParam("name") String name, @PathParam("version") String version) {
|
public Response installPlugin(@PathParam("name") String name) {
|
||||||
PluginPermissions.manage().check();
|
PluginPermissions.manage().check();
|
||||||
pluginManager.install(name + ":" + version);
|
pluginManager.install(name);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,10 @@ package sonia.scm.api.v2.resources;
|
|||||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||||
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
||||||
|
import sonia.scm.plugin.InstalledPlugin;
|
||||||
import sonia.scm.plugin.InstalledPluginDescriptor;
|
import sonia.scm.plugin.InstalledPluginDescriptor;
|
||||||
import sonia.scm.plugin.PluginLoader;
|
|
||||||
import sonia.scm.plugin.PluginManager;
|
import sonia.scm.plugin.PluginManager;
|
||||||
import sonia.scm.plugin.PluginPermissions;
|
import sonia.scm.plugin.PluginPermissions;
|
||||||
import sonia.scm.plugin.InstalledPlugin;
|
|
||||||
import sonia.scm.web.VndMediaType;
|
import sonia.scm.web.VndMediaType;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -16,7 +15,6 @@ import javax.ws.rs.Path;
|
|||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -25,17 +23,15 @@ import static sonia.scm.NotFoundException.notFound;
|
|||||||
|
|
||||||
public class InstalledPluginResource {
|
public class InstalledPluginResource {
|
||||||
|
|
||||||
private final PluginLoader pluginLoader;
|
|
||||||
private final PluginDtoCollectionMapper collectionMapper;
|
private final PluginDtoCollectionMapper collectionMapper;
|
||||||
private final PluginDtoMapper mapper;
|
private final PluginDtoMapper mapper;
|
||||||
private final PluginManager pluginManager;
|
private final PluginManager pluginManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public InstalledPluginResource(PluginLoader pluginLoader, PluginDtoCollectionMapper collectionMapper, PluginDtoMapper mapper, PluginManager pluginManager) {
|
public InstalledPluginResource(PluginManager pluginManager, PluginDtoCollectionMapper collectionMapper, PluginDtoMapper mapper) {
|
||||||
this.pluginLoader = pluginLoader;
|
this.pluginManager = pluginManager;
|
||||||
this.collectionMapper = collectionMapper;
|
this.collectionMapper = collectionMapper;
|
||||||
this.mapper = mapper;
|
this.mapper = mapper;
|
||||||
this.pluginManager = pluginManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,8 +49,8 @@ public class InstalledPluginResource {
|
|||||||
@Produces(VndMediaType.PLUGIN_COLLECTION)
|
@Produces(VndMediaType.PLUGIN_COLLECTION)
|
||||||
public Response getInstalledPlugins() {
|
public Response getInstalledPlugins() {
|
||||||
PluginPermissions.read().check();
|
PluginPermissions.read().check();
|
||||||
List<InstalledPlugin> plugins = new ArrayList<>(pluginLoader.getInstalledPlugins());
|
List<InstalledPlugin> plugins = pluginManager.getInstalled();
|
||||||
return Response.ok(collectionMapper.map(plugins)).build();
|
return Response.ok(collectionMapper.mapInstalled(plugins)).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,13 +71,9 @@ public class InstalledPluginResource {
|
|||||||
@Produces(VndMediaType.PLUGIN)
|
@Produces(VndMediaType.PLUGIN)
|
||||||
public Response getInstalledPlugin(@PathParam("name") String name) {
|
public Response getInstalledPlugin(@PathParam("name") String name) {
|
||||||
PluginPermissions.read().check();
|
PluginPermissions.read().check();
|
||||||
Optional<PluginDto> pluginDto = pluginLoader.getInstalledPlugins()
|
Optional<InstalledPlugin> pluginDto = pluginManager.getInstalled(name);
|
||||||
.stream()
|
|
||||||
.filter(plugin -> name.equals(plugin.getDescriptor().getInformation().getName()))
|
|
||||||
.map(mapper::map)
|
|
||||||
.findFirst();
|
|
||||||
if (pluginDto.isPresent()) {
|
if (pluginDto.isPresent()) {
|
||||||
return Response.ok(pluginDto.get()).build();
|
return Response.ok(mapper.map(pluginDto.get())).build();
|
||||||
} else {
|
} else {
|
||||||
throw notFound(entity(InstalledPluginDescriptor.class, name));
|
throw notFound(entity(InstalledPluginDescriptor.class, name));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.google.inject.Inject;
|
|||||||
import de.otto.edison.hal.Embedded;
|
import de.otto.edison.hal.Embedded;
|
||||||
import de.otto.edison.hal.HalRepresentation;
|
import de.otto.edison.hal.HalRepresentation;
|
||||||
import de.otto.edison.hal.Links;
|
import de.otto.edison.hal.Links;
|
||||||
|
import sonia.scm.plugin.AvailablePlugin;
|
||||||
import sonia.scm.plugin.PluginInformation;
|
import sonia.scm.plugin.PluginInformation;
|
||||||
import sonia.scm.plugin.InstalledPlugin;
|
import sonia.scm.plugin.InstalledPlugin;
|
||||||
|
|
||||||
@@ -25,12 +26,12 @@ public class PluginDtoCollectionMapper {
|
|||||||
this.mapper = mapper;
|
this.mapper = mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HalRepresentation map(List<InstalledPlugin> plugins) {
|
public HalRepresentation mapInstalled(List<InstalledPlugin> plugins) {
|
||||||
List<PluginDto> dtos = plugins.stream().map(mapper::map).collect(toList());
|
List<PluginDto> dtos = plugins.stream().map(mapper::map).collect(toList());
|
||||||
return new HalRepresentation(createInstalledPluginsLinks(), embedDtos(dtos));
|
return new HalRepresentation(createInstalledPluginsLinks(), embedDtos(dtos));
|
||||||
}
|
}
|
||||||
|
|
||||||
public HalRepresentation map(Collection<PluginInformation> plugins) {
|
public HalRepresentation mapAvailable(List<AvailablePlugin> plugins) {
|
||||||
List<PluginDto> dtos = plugins.stream().map(mapper::map).collect(toList());
|
List<PluginDto> dtos = plugins.stream().map(mapper::map).collect(toList());
|
||||||
return new HalRepresentation(createAvailablePluginsLinks(), embedDtos(dtos));
|
return new HalRepresentation(createAvailablePluginsLinks(), embedDtos(dtos));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
package sonia.scm.api.v2.resources;
|
package sonia.scm.api.v2.resources;
|
||||||
|
|
||||||
import de.otto.edison.hal.Links;
|
import de.otto.edison.hal.Links;
|
||||||
import org.mapstruct.AfterMapping;
|
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.MappingTarget;
|
import org.mapstruct.MappingTarget;
|
||||||
import org.mapstruct.ObjectFactory;
|
import sonia.scm.plugin.Plugin;
|
||||||
import sonia.scm.plugin.PluginInformation;
|
import sonia.scm.plugin.PluginInformation;
|
||||||
import sonia.scm.plugin.PluginState;
|
import sonia.scm.plugin.PluginState;
|
||||||
import sonia.scm.plugin.InstalledPlugin;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@@ -20,23 +18,23 @@ public abstract class PluginDtoMapper {
|
|||||||
@Inject
|
@Inject
|
||||||
private ResourceLinks resourceLinks;
|
private ResourceLinks resourceLinks;
|
||||||
|
|
||||||
public PluginDto map(InstalledPlugin plugin) {
|
public abstract void map(PluginInformation plugin, @MappingTarget PluginDto dto);
|
||||||
return map(plugin.getDescriptor().getInformation());
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract PluginDto map(PluginInformation plugin);
|
public PluginDto map(Plugin plugin) {
|
||||||
|
PluginDto dto = createDto(plugin);
|
||||||
@AfterMapping
|
map(plugin.getDescriptor().getInformation(), dto);
|
||||||
protected void appendCategory(@MappingTarget PluginDto dto) {
|
|
||||||
if (dto.getCategory() == null) {
|
if (dto.getCategory() == null) {
|
||||||
dto.setCategory("Miscellaneous");
|
dto.setCategory("Miscellaneous");
|
||||||
}
|
}
|
||||||
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ObjectFactory
|
private PluginDto createDto(Plugin plugin) {
|
||||||
public PluginDto createDto(PluginInformation pluginInformation) {
|
|
||||||
Links.Builder linksBuilder;
|
Links.Builder linksBuilder;
|
||||||
if (pluginInformation.getState() != null && pluginInformation.getState().equals(PluginState.AVAILABLE)) {
|
|
||||||
|
PluginInformation pluginInformation = plugin.getDescriptor().getInformation();
|
||||||
|
|
||||||
|
if (plugin.getState() != null && plugin.getState().equals(PluginState.AVAILABLE)) {
|
||||||
linksBuilder = linkingTo()
|
linksBuilder = linkingTo()
|
||||||
.self(resourceLinks.availablePlugin()
|
.self(resourceLinks.availablePlugin()
|
||||||
.self(pluginInformation.getName(), pluginInformation.getVersion()));
|
.self(pluginInformation.getName(), pluginInformation.getVersion()));
|
||||||
|
|||||||
@@ -35,685 +35,41 @@ package sonia.scm.plugin;
|
|||||||
|
|
||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
import com.github.legman.Subscribe;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
|
||||||
import com.google.common.io.Files;
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import sonia.scm.SCMContextProvider;
|
|
||||||
import sonia.scm.cache.Cache;
|
|
||||||
import sonia.scm.cache.CacheManager;
|
|
||||||
import sonia.scm.config.ScmConfiguration;
|
|
||||||
import sonia.scm.config.ScmConfigurationChangedEvent;
|
|
||||||
import sonia.scm.io.ZipUnArchiver;
|
|
||||||
import sonia.scm.util.AssertUtil;
|
|
||||||
import sonia.scm.util.IOUtil;
|
|
||||||
import sonia.scm.util.SystemUtil;
|
|
||||||
import sonia.scm.util.Util;
|
|
||||||
import sonia.scm.version.Version;
|
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
|
import java.util.List;
|
||||||
import java.io.File;
|
import java.util.Optional;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.xml.bind.JAXB;
|
|
||||||
|
|
||||||
import sonia.scm.net.ahc.AdvancedHttpClient;
|
|
||||||
|
|
||||||
import static sonia.scm.plugin.PluginCenterDtoMapper.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO replace aether stuff.
|
|
||||||
* TODO check AdvancedPluginConfiguration from 1.x
|
|
||||||
*
|
*
|
||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class DefaultPluginManager implements PluginManager
|
public class DefaultPluginManager implements PluginManager {
|
||||||
{
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
public static final String CACHE_NAME = "sonia.cache.plugins";
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
public static final String ENCODING = "UTF-8";
|
|
||||||
|
|
||||||
/** the logger for DefaultPluginManager */
|
|
||||||
private static final Logger logger =
|
|
||||||
LoggerFactory.getLogger(DefaultPluginManager.class);
|
|
||||||
|
|
||||||
/** enable or disable remote plugins */
|
|
||||||
private static final boolean REMOTE_PLUGINS_ENABLED = true;
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
public static final Predicate<PluginInformation> FILTER_UPDATES =
|
|
||||||
new StatePluginPredicate(PluginState.UPDATE_AVAILABLE);
|
|
||||||
|
|
||||||
//~--- constructors ---------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs ...
|
|
||||||
*
|
|
||||||
* @param context
|
|
||||||
* @param configuration
|
|
||||||
* @param pluginLoader
|
|
||||||
* @param cacheManager
|
|
||||||
* @param httpClient
|
|
||||||
*/
|
|
||||||
@Inject
|
|
||||||
public DefaultPluginManager(SCMContextProvider context,
|
|
||||||
ScmConfiguration configuration, PluginLoader pluginLoader,
|
|
||||||
CacheManager cacheManager, AdvancedHttpClient httpClient)
|
|
||||||
{
|
|
||||||
this.context = context;
|
|
||||||
this.configuration = configuration;
|
|
||||||
this.cache = cacheManager.getCache(CACHE_NAME);
|
|
||||||
this.httpClient = httpClient;
|
|
||||||
installedPlugins = new HashMap<>();
|
|
||||||
|
|
||||||
for (InstalledPlugin wrapper : pluginLoader.getInstalledPlugins())
|
|
||||||
{
|
|
||||||
InstalledPluginDescriptor plugin = wrapper.getDescriptor();
|
|
||||||
PluginInformation info = plugin.getInformation();
|
|
||||||
|
|
||||||
if ((info != null) && info.isValid())
|
|
||||||
{
|
|
||||||
installedPlugins.put(info.getId(), plugin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void clearCache()
|
public Optional<AvailablePlugin> getAvailable(String name) {
|
||||||
{
|
return Optional.empty();
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
logger.debug("clear plugin cache");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param config
|
|
||||||
*/
|
|
||||||
@Subscribe
|
|
||||||
public void configChanged(ScmConfigurationChangedEvent config)
|
|
||||||
{
|
|
||||||
clearCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void install(String id)
|
public Optional<InstalledPlugin> getInstalled(String name) {
|
||||||
{
|
return Optional.empty();
|
||||||
PluginPermissions.manage().check();
|
|
||||||
|
|
||||||
PluginCenter center = getPluginCenter();
|
|
||||||
|
|
||||||
for (PluginInformation plugin : center.getPlugins())
|
|
||||||
{
|
|
||||||
String pluginId = plugin.getId();
|
|
||||||
|
|
||||||
if (Util.isNotEmpty(pluginId) && pluginId.equals(id))
|
|
||||||
{
|
|
||||||
plugin.setState(PluginState.INSTALLED);
|
|
||||||
|
|
||||||
// ugly workaround
|
|
||||||
InstalledPluginDescriptor newPlugin = new InstalledPluginDescriptor();
|
|
||||||
|
|
||||||
// TODO check
|
|
||||||
// newPlugin.setInformation(plugin);
|
|
||||||
installedPlugins.put(id, newPlugin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param packageStream
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void installPackage(InputStream packageStream) throws IOException
|
public List<InstalledPlugin> getInstalled() {
|
||||||
{
|
return null;
|
||||||
PluginPermissions.manage().check();
|
|
||||||
|
|
||||||
File tempDirectory = Files.createTempDir();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
new ZipUnArchiver().extractArchive(packageStream, tempDirectory);
|
|
||||||
|
|
||||||
InstalledPluginDescriptor plugin = JAXB.unmarshal(new File(tempDirectory, "plugin.xml"),
|
|
||||||
InstalledPluginDescriptor.class);
|
|
||||||
|
|
||||||
PluginCondition condition = plugin.getCondition();
|
|
||||||
|
|
||||||
if ((condition != null) &&!condition.isSupported())
|
|
||||||
{
|
|
||||||
throw new PluginConditionFailedException(condition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* AetherPluginHandler aph = new AetherPluginHandler(this, context,
|
|
||||||
* configuration);
|
|
||||||
* Collection<PluginRepository> repositories =
|
|
||||||
* Sets.newHashSet(new PluginRepository("package-repository",
|
|
||||||
* "file://".concat(tempDirectory.getAbsolutePath())));
|
|
||||||
*
|
|
||||||
* aph.setPluginRepositories(repositories);
|
|
||||||
*
|
|
||||||
* aph.install(plugin.getInformation().getId());
|
|
||||||
*/
|
|
||||||
plugin.getInformation().setState(PluginState.INSTALLED);
|
|
||||||
installedPlugins.put(plugin.getInformation().getId(), plugin);
|
|
||||||
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
IOUtil.delete(tempDirectory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void uninstall(String id)
|
public List<AvailablePlugin> getAvailable() {
|
||||||
{
|
return null;
|
||||||
PluginPermissions.manage().check();
|
|
||||||
|
|
||||||
InstalledPluginDescriptor plugin = installedPlugins.get(id);
|
|
||||||
|
|
||||||
if (plugin == null)
|
|
||||||
{
|
|
||||||
String pluginPrefix = getPluginIdPrefix(id);
|
|
||||||
|
|
||||||
for (String nid : installedPlugins.keySet())
|
|
||||||
{
|
|
||||||
if (nid.startsWith(pluginPrefix))
|
|
||||||
{
|
|
||||||
id = nid;
|
|
||||||
plugin = installedPlugins.get(nid);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plugin == null)
|
|
||||||
{
|
|
||||||
throw new PluginNotInstalledException(id.concat(" is not install"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* if (pluginHandler == null)
|
|
||||||
* {
|
|
||||||
* getPluginCenter();
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* pluginHandler.uninstall(id);
|
|
||||||
*/
|
|
||||||
installedPlugins.remove(id);
|
|
||||||
preparePlugins(getPluginCenter());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void update(String id)
|
public void install(String name) {
|
||||||
{
|
|
||||||
PluginPermissions.manage().check();
|
|
||||||
|
|
||||||
String[] idParts = id.split(":");
|
|
||||||
String name = idParts[0];
|
|
||||||
PluginInformation installed = null;
|
|
||||||
|
|
||||||
for (PluginInformation info : getInstalled())
|
|
||||||
{
|
|
||||||
if (name.equals(info.getName()))
|
|
||||||
{
|
|
||||||
installed = info;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (installed == null)
|
|
||||||
{
|
|
||||||
StringBuilder msg = new StringBuilder(name);
|
|
||||||
|
|
||||||
msg.append(" is not install");
|
|
||||||
|
|
||||||
throw new PluginNotInstalledException(msg.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
uninstall(installed.getId());
|
|
||||||
install(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- get methods ----------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public PluginInformation get(String id)
|
|
||||||
{
|
|
||||||
PluginPermissions.read().check();
|
|
||||||
|
|
||||||
PluginInformation result = null;
|
|
||||||
|
|
||||||
for (PluginInformation info : getPluginCenter().getPlugins())
|
|
||||||
{
|
|
||||||
if (id.equals(info.getId()))
|
|
||||||
{
|
|
||||||
result = info;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param predicate
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Set<PluginInformation> get(Predicate<PluginInformation> predicate)
|
|
||||||
{
|
|
||||||
AssertUtil.assertIsNotNull(predicate);
|
|
||||||
PluginPermissions.read().check();
|
|
||||||
|
|
||||||
Set<PluginInformation> infoSet = new HashSet<>();
|
|
||||||
|
|
||||||
filter(infoSet, getInstalled(), predicate);
|
|
||||||
filter(infoSet, getPluginCenter().getPlugins(), predicate);
|
|
||||||
|
|
||||||
return infoSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Collection<PluginInformation> getAll()
|
|
||||||
{
|
|
||||||
PluginPermissions.read().check();
|
|
||||||
|
|
||||||
Set<PluginInformation> infoSet = getInstalled();
|
|
||||||
|
|
||||||
infoSet.addAll(getPluginCenter().getPlugins());
|
|
||||||
|
|
||||||
return infoSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Collection<PluginInformation> getAvailable()
|
|
||||||
{
|
|
||||||
PluginPermissions.read().check();
|
|
||||||
|
|
||||||
Set<PluginInformation> availablePlugins = new HashSet<>();
|
|
||||||
Set<PluginInformation> centerPlugins = getPluginCenter().getPlugins();
|
|
||||||
|
|
||||||
for (PluginInformation info : centerPlugins)
|
|
||||||
{
|
|
||||||
if (!installedPlugins.containsKey(info.getName()))
|
|
||||||
{
|
|
||||||
availablePlugins.add(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return availablePlugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Set<PluginInformation> getAvailableUpdates()
|
|
||||||
{
|
|
||||||
PluginPermissions.read().check();
|
|
||||||
|
|
||||||
return get(FILTER_UPDATES);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Set<PluginInformation> getInstalled()
|
|
||||||
{
|
|
||||||
PluginPermissions.read().check();
|
|
||||||
|
|
||||||
Set<PluginInformation> infoSet = new LinkedHashSet<>();
|
|
||||||
|
|
||||||
for (InstalledPluginDescriptor plugin : installedPlugins.values())
|
|
||||||
{
|
|
||||||
infoSet.add(plugin.getInformation());
|
|
||||||
}
|
|
||||||
|
|
||||||
return infoSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param url
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private String buildPluginUrl(String url)
|
|
||||||
{
|
|
||||||
String os = SystemUtil.getOS();
|
|
||||||
String arch = SystemUtil.getArch();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
os = URLEncoder.encode(os, ENCODING);
|
|
||||||
}
|
|
||||||
catch (UnsupportedEncodingException ex)
|
|
||||||
{
|
|
||||||
logger.error(ex.getMessage(), ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return url.replace("{version}", context.getVersion()).replace("{os}",
|
|
||||||
os).replace("{arch}", arch);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param target
|
|
||||||
* @param source
|
|
||||||
* @param predicate
|
|
||||||
*/
|
|
||||||
private void filter(Set<PluginInformation> target,
|
|
||||||
Collection<PluginInformation> source,
|
|
||||||
Predicate<PluginInformation> predicate)
|
|
||||||
{
|
|
||||||
for (PluginInformation info : source)
|
|
||||||
{
|
|
||||||
if (predicate.apply(info))
|
|
||||||
{
|
|
||||||
target.add(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param available
|
|
||||||
*/
|
|
||||||
private void preparePlugin(PluginInformation available)
|
|
||||||
{
|
|
||||||
PluginState state = PluginState.AVAILABLE;
|
|
||||||
|
|
||||||
for (PluginInformation installed : getInstalled())
|
|
||||||
{
|
|
||||||
if (isSamePlugin(available, installed))
|
|
||||||
{
|
|
||||||
if (installed.getVersion().equals(available.getVersion()))
|
|
||||||
{
|
|
||||||
state = PluginState.INSTALLED;
|
|
||||||
}
|
|
||||||
else if (isNewer(available, installed))
|
|
||||||
{
|
|
||||||
state = PluginState.UPDATE_AVAILABLE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state = PluginState.NEWER_VERSION_INSTALLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
available.setState(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param pc
|
|
||||||
*/
|
|
||||||
private void preparePlugins(PluginCenter pc)
|
|
||||||
{
|
|
||||||
Set<PluginInformation> infoSet = pc.getPlugins();
|
|
||||||
|
|
||||||
if (infoSet != null)
|
|
||||||
{
|
|
||||||
Iterator<PluginInformation> pit = infoSet.iterator();
|
|
||||||
|
|
||||||
while (pit.hasNext())
|
|
||||||
{
|
|
||||||
PluginInformation available = pit.next();
|
|
||||||
|
|
||||||
if (isCorePluging(available))
|
|
||||||
{
|
|
||||||
pit.remove();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
preparePlugin(available);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- get methods ----------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private PluginCenter getPluginCenter()
|
|
||||||
{
|
|
||||||
PluginCenter center = cache.get(PluginCenter.class.getName());
|
|
||||||
|
|
||||||
if (center == null)
|
|
||||||
{
|
|
||||||
synchronized (DefaultPluginManager.class)
|
|
||||||
{
|
|
||||||
String pluginUrl = buildPluginUrl(configuration.getPluginUrl());
|
|
||||||
logger.info("fetch plugin information from {}", pluginUrl);
|
|
||||||
|
|
||||||
if (REMOTE_PLUGINS_ENABLED && Util.isNotEmpty(pluginUrl))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
center = new PluginCenter();
|
|
||||||
PluginCenterDto pluginCenterDto = httpClient.get(pluginUrl).request().contentFromJson(PluginCenterDto.class);
|
|
||||||
Set<PluginInformation> pluginInformationSet = map(pluginCenterDto.getEmbedded().getPlugins());
|
|
||||||
center.setPlugins(pluginInformationSet);
|
|
||||||
preparePlugins(center);
|
|
||||||
cache.put(PluginCenter.class.getName(), center);
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
logger.error("could not load plugins from plugin center", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(center == null) {
|
|
||||||
center = new PluginCenter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param pluginId
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private String getPluginIdPrefix(String pluginId)
|
|
||||||
{
|
|
||||||
return pluginId.substring(0, pluginId.lastIndexOf(':'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param available
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private boolean isCorePluging(PluginInformation available)
|
|
||||||
{
|
|
||||||
boolean core = false;
|
|
||||||
|
|
||||||
for (InstalledPluginDescriptor installedPlugin : installedPlugins.values())
|
|
||||||
{
|
|
||||||
PluginInformation installed = installedPlugin.getInformation();
|
|
||||||
|
|
||||||
if (isSamePlugin(available, installed)
|
|
||||||
&& (installed.getState() == PluginState.CORE))
|
|
||||||
{
|
|
||||||
core = true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return core;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param available
|
|
||||||
* @param installed
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private boolean isNewer(PluginInformation available,
|
|
||||||
PluginInformation installed)
|
|
||||||
{
|
|
||||||
boolean result = false;
|
|
||||||
Version version = Version.parse(available.getVersion());
|
|
||||||
|
|
||||||
if (version != null)
|
|
||||||
{
|
|
||||||
result = version.isNewer(installed.getVersion());
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param p1
|
|
||||||
* @param p2
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private boolean isSamePlugin(PluginInformation p1, PluginInformation p2)
|
|
||||||
{
|
|
||||||
return p1.getName().equals(p2.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- fields ---------------------------------------------------------------
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private final Cache<String, PluginCenter> cache;
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private final AdvancedHttpClient httpClient;
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private final ScmConfiguration configuration;
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private final SCMContextProvider context;
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private final Map<String, InstalledPluginDescriptor> installedPlugins;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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 com.google.common.base.Predicate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Sebastian Sdorra
|
|
||||||
*/
|
|
||||||
public class OverviewPluginPredicate implements Predicate<PluginInformation>
|
|
||||||
{
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
public static final OverviewPluginPredicate INSTANCE =
|
|
||||||
new OverviewPluginPredicate();
|
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param plugin
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean apply(PluginInformation plugin)
|
|
||||||
{
|
|
||||||
return plugin.getState() != PluginState.NEWER_VERSION_INSTALLED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -237,7 +237,7 @@ public final class PluginProcessor
|
|||||||
}
|
}
|
||||||
|
|
||||||
InstalledPlugin plugin =
|
InstalledPlugin plugin =
|
||||||
createPluginWrapper(createParentPluginClassLoader(classLoader, parents),
|
createPlugin(createParentPluginClassLoader(classLoader, parents),
|
||||||
smp);
|
smp);
|
||||||
|
|
||||||
if (plugin != null)
|
if (plugin != null)
|
||||||
@@ -431,73 +431,36 @@ public final class PluginProcessor
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private InstalledPluginDescriptor createDescriptor(ClassLoader classLoader, Path descriptor) {
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param classLoader
|
|
||||||
* @param descriptor
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private InstalledPluginDescriptor createPlugin(ClassLoader classLoader, Path descriptor)
|
|
||||||
{
|
|
||||||
ClassLoader ctxcl = Thread.currentThread().getContextClassLoader();
|
ClassLoader ctxcl = Thread.currentThread().getContextClassLoader();
|
||||||
|
|
||||||
Thread.currentThread().setContextClassLoader(classLoader);
|
Thread.currentThread().setContextClassLoader(classLoader);
|
||||||
|
try {
|
||||||
try
|
return (InstalledPluginDescriptor) context.createUnmarshaller().unmarshal(descriptor.toFile());
|
||||||
{
|
} catch (JAXBException ex) {
|
||||||
return (InstalledPluginDescriptor) context.createUnmarshaller().unmarshal(
|
throw new PluginLoadException("could not load plugin desriptor ".concat(descriptor.toString()), ex);
|
||||||
descriptor.toFile());
|
} finally {
|
||||||
}
|
|
||||||
catch (JAXBException ex)
|
|
||||||
{
|
|
||||||
throw new PluginLoadException(
|
|
||||||
"could not load plugin desriptor ".concat(descriptor.toString()), ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Thread.currentThread().setContextClassLoader(ctxcl);
|
Thread.currentThread().setContextClassLoader(ctxcl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private InstalledPlugin createPlugin(ClassLoader classLoader, ExplodedSmp smp) throws IOException {
|
||||||
* Method description
|
InstalledPlugin plugin = null;
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param classLoader
|
|
||||||
* @param smp
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private InstalledPlugin createPluginWrapper(ClassLoader classLoader,
|
|
||||||
ExplodedSmp smp)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
InstalledPlugin wrapper = null;
|
|
||||||
Path directory = smp.getPath();
|
Path directory = smp.getPath();
|
||||||
Path descriptor = directory.resolve(PluginConstants.FILE_DESCRIPTOR);
|
Path descriptorPath = directory.resolve(PluginConstants.FILE_DESCRIPTOR);
|
||||||
|
|
||||||
if (Files.exists(descriptor))
|
if (Files.exists(descriptorPath)) {
|
||||||
{
|
|
||||||
ClassLoader cl = createClassLoader(classLoader, smp);
|
ClassLoader cl = createClassLoader(classLoader, smp);
|
||||||
|
|
||||||
InstalledPluginDescriptor plugin = createPlugin(cl, descriptor);
|
InstalledPluginDescriptor descriptor = createDescriptor(cl, descriptorPath);
|
||||||
|
|
||||||
WebResourceLoader resourceLoader = createWebResourceLoader(directory);
|
WebResourceLoader resourceLoader = createWebResourceLoader(directory);
|
||||||
|
|
||||||
wrapper = new InstalledPlugin(plugin, cl, resourceLoader, directory);
|
plugin = new InstalledPlugin(descriptor, cl, resourceLoader, directory);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.warn("found plugin directory without plugin descriptor");
|
logger.warn("found plugin directory without plugin descriptor");
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrapper;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
|||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import sonia.scm.plugin.AvailablePlugin;
|
||||||
|
import sonia.scm.plugin.AvailablePluginDescriptor;
|
||||||
|
import sonia.scm.plugin.PluginCondition;
|
||||||
import sonia.scm.plugin.PluginInformation;
|
import sonia.scm.plugin.PluginInformation;
|
||||||
import sonia.scm.plugin.PluginManager;
|
import sonia.scm.plugin.PluginManager;
|
||||||
import sonia.scm.plugin.PluginState;
|
import sonia.scm.plugin.PluginState;
|
||||||
@@ -27,6 +30,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
@@ -87,10 +91,10 @@ class AvailablePluginResourceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getAvailablePlugins() throws URISyntaxException, UnsupportedEncodingException {
|
void getAvailablePlugins() throws URISyntaxException, UnsupportedEncodingException {
|
||||||
PluginInformation pluginInformation = new PluginInformation();
|
AvailablePlugin plugin = createPlugin();
|
||||||
pluginInformation.setState(PluginState.AVAILABLE);
|
|
||||||
when(pluginManager.getAvailable()).thenReturn(Collections.singletonList(pluginInformation));
|
when(pluginManager.getAvailable()).thenReturn(Collections.singletonList(plugin));
|
||||||
when(collectionMapper.map(Collections.singletonList(pluginInformation))).thenReturn(new MockedResultDto());
|
when(collectionMapper.mapAvailable(Collections.singletonList(plugin))).thenReturn(new MockedResultDto());
|
||||||
|
|
||||||
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/available");
|
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/available");
|
||||||
request.accept(VndMediaType.PLUGIN_COLLECTION);
|
request.accept(VndMediaType.PLUGIN_COLLECTION);
|
||||||
@@ -105,16 +109,18 @@ class AvailablePluginResourceTest {
|
|||||||
@Test
|
@Test
|
||||||
void getAvailablePlugin() throws UnsupportedEncodingException, URISyntaxException {
|
void getAvailablePlugin() throws UnsupportedEncodingException, URISyntaxException {
|
||||||
PluginInformation pluginInformation = new PluginInformation();
|
PluginInformation pluginInformation = new PluginInformation();
|
||||||
pluginInformation.setState(PluginState.AVAILABLE);
|
|
||||||
pluginInformation.setName("pluginName");
|
pluginInformation.setName("pluginName");
|
||||||
pluginInformation.setVersion("2.0.0");
|
pluginInformation.setVersion("2.0.0");
|
||||||
when(pluginManager.getAvailable()).thenReturn(Collections.singletonList(pluginInformation));
|
|
||||||
|
AvailablePlugin plugin = createPlugin(pluginInformation);
|
||||||
|
|
||||||
|
when(pluginManager.getAvailable("pluginName")).thenReturn(Optional.of(plugin));
|
||||||
|
|
||||||
PluginDto pluginDto = new PluginDto();
|
PluginDto pluginDto = new PluginDto();
|
||||||
pluginDto.setName("pluginName");
|
pluginDto.setName("pluginName");
|
||||||
when(mapper.map(pluginInformation)).thenReturn(pluginDto);
|
when(mapper.map(plugin)).thenReturn(pluginDto);
|
||||||
|
|
||||||
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/available/pluginName/2.0.0");
|
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/available/pluginName");
|
||||||
request.accept(VndMediaType.PLUGIN);
|
request.accept(VndMediaType.PLUGIN);
|
||||||
MockHttpResponse response = new MockHttpResponse();
|
MockHttpResponse response = new MockHttpResponse();
|
||||||
|
|
||||||
@@ -126,17 +132,26 @@ class AvailablePluginResourceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void installPlugin() throws URISyntaxException {
|
void installPlugin() throws URISyntaxException {
|
||||||
MockHttpRequest request = MockHttpRequest.post("/v2/plugins/available/pluginName/2.0.0/install");
|
MockHttpRequest request = MockHttpRequest.post("/v2/plugins/available/pluginName/install");
|
||||||
request.accept(VndMediaType.PLUGIN);
|
request.accept(VndMediaType.PLUGIN);
|
||||||
MockHttpResponse response = new MockHttpResponse();
|
MockHttpResponse response = new MockHttpResponse();
|
||||||
|
|
||||||
dispatcher.invoke(request, response);
|
dispatcher.invoke(request, response);
|
||||||
|
|
||||||
verify(pluginManager).install("pluginName:2.0.0");
|
verify(pluginManager).install("pluginName");
|
||||||
assertThat(HttpServletResponse.SC_OK).isEqualTo(response.getStatus());
|
assertThat(HttpServletResponse.SC_OK).isEqualTo(response.getStatus());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AvailablePlugin createPlugin() {
|
||||||
|
return createPlugin(new PluginInformation());
|
||||||
|
}
|
||||||
|
|
||||||
|
private AvailablePlugin createPlugin(PluginInformation pluginInformation) {
|
||||||
|
AvailablePluginDescriptor descriptor = new AvailablePluginDescriptor(pluginInformation, new PluginCondition(), Collections.emptySet());
|
||||||
|
return new AvailablePlugin(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
class WithoutAuthorization {
|
class WithoutAuthorization {
|
||||||
|
|
||||||
@@ -156,7 +171,7 @@ class AvailablePluginResourceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldNotGetAvailablePluginIfMissingPermission() throws URISyntaxException {
|
void shouldNotGetAvailablePluginIfMissingPermission() throws URISyntaxException {
|
||||||
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/available/pluginName/2.0.0");
|
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/available/pluginName");
|
||||||
request.accept(VndMediaType.PLUGIN);
|
request.accept(VndMediaType.PLUGIN);
|
||||||
MockHttpResponse response = new MockHttpResponse();
|
MockHttpResponse response = new MockHttpResponse();
|
||||||
|
|
||||||
@@ -166,7 +181,7 @@ class AvailablePluginResourceTest {
|
|||||||
@Test
|
@Test
|
||||||
void shouldNotInstallPluginIfMissingPermission() throws URISyntaxException {
|
void shouldNotInstallPluginIfMissingPermission() throws URISyntaxException {
|
||||||
ThreadContext.unbindSubject();
|
ThreadContext.unbindSubject();
|
||||||
MockHttpRequest request = MockHttpRequest.post("/v2/plugins/available/pluginName/2.0.0/install");
|
MockHttpRequest request = MockHttpRequest.post("/v2/plugins/available/pluginName/install");
|
||||||
request.accept(VndMediaType.PLUGIN);
|
request.accept(VndMediaType.PLUGIN);
|
||||||
MockHttpResponse response = new MockHttpResponse();
|
MockHttpResponse response = new MockHttpResponse();
|
||||||
|
|
||||||
|
|||||||
@@ -16,11 +16,10 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
|||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import sonia.scm.plugin.InstalledPlugin;
|
||||||
import sonia.scm.plugin.InstalledPluginDescriptor;
|
import sonia.scm.plugin.InstalledPluginDescriptor;
|
||||||
import sonia.scm.plugin.PluginInformation;
|
import sonia.scm.plugin.PluginInformation;
|
||||||
import sonia.scm.plugin.PluginLoader;
|
import sonia.scm.plugin.PluginManager;
|
||||||
import sonia.scm.plugin.PluginState;
|
|
||||||
import sonia.scm.plugin.InstalledPlugin;
|
|
||||||
import sonia.scm.web.VndMediaType;
|
import sonia.scm.web.VndMediaType;
|
||||||
|
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
@@ -28,12 +27,12 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.*;
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class InstalledPluginResourceTest {
|
class InstalledPluginResourceTest {
|
||||||
@@ -46,15 +45,15 @@ class InstalledPluginResourceTest {
|
|||||||
@Mock
|
@Mock
|
||||||
Provider<AvailablePluginResource> availablePluginResourceProvider;
|
Provider<AvailablePluginResource> availablePluginResourceProvider;
|
||||||
|
|
||||||
@Mock
|
|
||||||
private PluginLoader pluginLoader;
|
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private PluginDtoCollectionMapper collectionMapper;
|
private PluginDtoCollectionMapper collectionMapper;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private PluginDtoMapper mapper;
|
private PluginDtoMapper mapper;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private PluginManager pluginManager;
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
InstalledPluginResource installedPluginResource;
|
InstalledPluginResource installedPluginResource;
|
||||||
|
|
||||||
@@ -86,9 +85,9 @@ class InstalledPluginResourceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getInstalledPlugins() throws URISyntaxException, UnsupportedEncodingException {
|
void getInstalledPlugins() throws URISyntaxException, UnsupportedEncodingException {
|
||||||
InstalledPlugin installedPlugin = new InstalledPlugin(null, null, null, null);
|
InstalledPlugin installedPlugin = createPlugin();
|
||||||
when(pluginLoader.getInstalledPlugins()).thenReturn(Collections.singletonList(installedPlugin));
|
when(pluginManager.getInstalled()).thenReturn(Collections.singletonList(installedPlugin));
|
||||||
when(collectionMapper.map(Collections.singletonList(installedPlugin))).thenReturn(new MockedResultDto());
|
when(collectionMapper.mapInstalled(Collections.singletonList(installedPlugin))).thenReturn(new MockedResultDto());
|
||||||
|
|
||||||
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/installed");
|
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/installed");
|
||||||
request.accept(VndMediaType.PLUGIN_COLLECTION);
|
request.accept(VndMediaType.PLUGIN_COLLECTION);
|
||||||
@@ -105,10 +104,9 @@ class InstalledPluginResourceTest {
|
|||||||
PluginInformation pluginInformation = new PluginInformation();
|
PluginInformation pluginInformation = new PluginInformation();
|
||||||
pluginInformation.setVersion("2.0.0");
|
pluginInformation.setVersion("2.0.0");
|
||||||
pluginInformation.setName("pluginName");
|
pluginInformation.setName("pluginName");
|
||||||
pluginInformation.setState(PluginState.INSTALLED);
|
InstalledPlugin installedPlugin = createPlugin(pluginInformation);
|
||||||
InstalledPluginDescriptor plugin = new InstalledPluginDescriptor(2, pluginInformation, null, null, false, null);
|
|
||||||
InstalledPlugin installedPlugin = new InstalledPlugin(plugin, null, null, null);
|
when(pluginManager.getInstalled("pluginName")).thenReturn(Optional.of(installedPlugin));
|
||||||
when(pluginLoader.getInstalledPlugins()).thenReturn(Collections.singletonList(installedPlugin));
|
|
||||||
|
|
||||||
PluginDto pluginDto = new PluginDto();
|
PluginDto pluginDto = new PluginDto();
|
||||||
pluginDto.setName("pluginName");
|
pluginDto.setName("pluginName");
|
||||||
@@ -125,6 +123,18 @@ class InstalledPluginResourceTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private InstalledPlugin createPlugin() {
|
||||||
|
return createPlugin(new PluginInformation());
|
||||||
|
}
|
||||||
|
|
||||||
|
private InstalledPlugin createPlugin(PluginInformation information) {
|
||||||
|
InstalledPlugin plugin = mock(InstalledPlugin.class);
|
||||||
|
InstalledPluginDescriptor descriptor = mock(InstalledPluginDescriptor.class);
|
||||||
|
lenient().when(descriptor.getInformation()).thenReturn(information);
|
||||||
|
lenient().when(plugin.getDescriptor()).thenReturn(descriptor);
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
class WithoutAuthorization {
|
class WithoutAuthorization {
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,19 @@ import org.junit.jupiter.api.BeforeEach;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mockito;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import sonia.scm.plugin.Plugin;
|
||||||
|
import sonia.scm.plugin.PluginDescriptor;
|
||||||
import sonia.scm.plugin.PluginInformation;
|
import sonia.scm.plugin.PluginInformation;
|
||||||
import sonia.scm.plugin.PluginState;
|
import sonia.scm.plugin.PluginState;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.in;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class PluginDtoMapperTest {
|
class PluginDtoMapperTest {
|
||||||
@@ -25,7 +31,8 @@ class PluginDtoMapperTest {
|
|||||||
void shouldMapInformation() {
|
void shouldMapInformation() {
|
||||||
PluginInformation information = createPluginInformation();
|
PluginInformation information = createPluginInformation();
|
||||||
|
|
||||||
PluginDto dto = mapper.map(information);
|
PluginDto dto = new PluginDto();
|
||||||
|
mapper.map(information, dto);
|
||||||
|
|
||||||
assertThat(dto.getName()).isEqualTo("scm-cas-plugin");
|
assertThat(dto.getName()).isEqualTo("scm-cas-plugin");
|
||||||
assertThat(dto.getVersion()).isEqualTo("1.0.0");
|
assertThat(dto.getVersion()).isEqualTo("1.0.0");
|
||||||
@@ -48,41 +55,51 @@ class PluginDtoMapperTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldAppendInstalledSelfLink() {
|
void shouldAppendInstalledSelfLink() {
|
||||||
PluginInformation information = createPluginInformation();
|
Plugin plugin = createPlugin(PluginState.INSTALLED);
|
||||||
information.setState(PluginState.INSTALLED);
|
|
||||||
|
|
||||||
PluginDto dto = mapper.map(information);
|
PluginDto dto = mapper.map(plugin);
|
||||||
assertThat(dto.getLinks().getLinkBy("self").get().getHref())
|
assertThat(dto.getLinks().getLinkBy("self").get().getHref())
|
||||||
.isEqualTo("https://hitchhiker.com/v2/plugins/installed/scm-cas-plugin");
|
.isEqualTo("https://hitchhiker.com/v2/plugins/installed/scm-cas-plugin");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldAppendAvailableSelfLink() {
|
void shouldAppendAvailableSelfLink() {
|
||||||
PluginInformation information = createPluginInformation();
|
Plugin plugin = createPlugin(PluginState.AVAILABLE);
|
||||||
information.setState(PluginState.AVAILABLE);
|
|
||||||
|
|
||||||
PluginDto dto = mapper.map(information);
|
PluginDto dto = mapper.map(plugin);
|
||||||
assertThat(dto.getLinks().getLinkBy("self").get().getHref())
|
assertThat(dto.getLinks().getLinkBy("self").get().getHref())
|
||||||
.isEqualTo("https://hitchhiker.com/v2/plugins/available/scm-cas-plugin/1.0.0");
|
.isEqualTo("https://hitchhiker.com/v2/plugins/available/scm-cas-plugin");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldAppendInstallLink() {
|
void shouldAppendInstallLink() {
|
||||||
PluginInformation information = createPluginInformation();
|
Plugin plugin = createPlugin(PluginState.AVAILABLE);
|
||||||
information.setState(PluginState.AVAILABLE);
|
|
||||||
|
|
||||||
PluginDto dto = mapper.map(information);
|
PluginDto dto = mapper.map(plugin);
|
||||||
assertThat(dto.getLinks().getLinkBy("install").get().getHref())
|
assertThat(dto.getLinks().getLinkBy("install").get().getHref())
|
||||||
.isEqualTo("https://hitchhiker.com/v2/plugins/available/scm-cas-plugin/1.0.0/install");
|
.isEqualTo("https://hitchhiker.com/v2/plugins/available/scm-cas-plugin/install");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldReturnMiscellaneousIfCategoryIsNull() {
|
void shouldReturnMiscellaneousIfCategoryIsNull() {
|
||||||
PluginInformation information = createPluginInformation();
|
PluginInformation information = createPluginInformation();
|
||||||
information.setCategory(null);
|
information.setCategory(null);
|
||||||
|
Plugin plugin = createPlugin(information, PluginState.AVAILABLE);
|
||||||
PluginDto dto = mapper.map(information);
|
PluginDto dto = mapper.map(plugin);
|
||||||
assertThat(dto.getCategory()).isEqualTo("Miscellaneous");
|
assertThat(dto.getCategory()).isEqualTo("Miscellaneous");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Plugin createPlugin(PluginState state) {
|
||||||
|
return createPlugin(createPluginInformation(), state);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Plugin createPlugin(PluginInformation information, PluginState state) {
|
||||||
|
Plugin plugin = Mockito.mock(Plugin.class);
|
||||||
|
when(plugin.getState()).thenReturn(state);
|
||||||
|
PluginDescriptor descriptor = mock(PluginDescriptor.class);
|
||||||
|
when(descriptor.getInformation()).thenReturn(information);
|
||||||
|
when(plugin.getDescriptor()).thenReturn(descriptor);
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user