mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-14 17:26:22 +01:00
create new Endpoints and Resources for Plugins
This commit is contained in:
@@ -37,6 +37,8 @@ public class VndMediaType {
|
|||||||
public static final String REPOSITORY_VERB_COLLECTION = PREFIX + "repositoryVerbCollection" + SUFFIX;
|
public static final String REPOSITORY_VERB_COLLECTION = PREFIX + "repositoryVerbCollection" + SUFFIX;
|
||||||
public static final String REPOSITORY_TYPE_COLLECTION = PREFIX + "repositoryTypeCollection" + SUFFIX;
|
public static final String REPOSITORY_TYPE_COLLECTION = PREFIX + "repositoryTypeCollection" + SUFFIX;
|
||||||
public static final String REPOSITORY_TYPE = PREFIX + "repositoryType" + SUFFIX;
|
public static final String REPOSITORY_TYPE = PREFIX + "repositoryType" + SUFFIX;
|
||||||
|
public static final String PLUGIN = PREFIX + "plugin" + SUFFIX;
|
||||||
|
public static final String PLUGIN_COLLECTION = PREFIX + "pluginCollection" + SUFFIX;
|
||||||
public static final String UI_PLUGIN = PREFIX + "uiPlugin" + SUFFIX;
|
public static final String UI_PLUGIN = PREFIX + "uiPlugin" + SUFFIX;
|
||||||
public static final String UI_PLUGIN_COLLECTION = PREFIX + "uiPluginCollection" + SUFFIX;
|
public static final String UI_PLUGIN_COLLECTION = PREFIX + "uiPluginCollection" + SUFFIX;
|
||||||
@SuppressWarnings("squid:S2068")
|
@SuppressWarnings("squid:S2068")
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package sonia.scm.api.v2.resources;
|
||||||
|
|
||||||
|
import de.otto.edison.hal.HalRepresentation;
|
||||||
|
import de.otto.edison.hal.Links;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class PluginDto extends HalRepresentation {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String type;
|
||||||
|
private String version;
|
||||||
|
private String author;
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HalRepresentation add(Links links) {
|
||||||
|
return super.add(links);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package sonia.scm.api.v2.resources;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import de.otto.edison.hal.Embedded;
|
||||||
|
import de.otto.edison.hal.HalRepresentation;
|
||||||
|
import de.otto.edison.hal.Links;
|
||||||
|
import sonia.scm.plugin.PluginWrapper;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static de.otto.edison.hal.Embedded.embeddedBuilder;
|
||||||
|
import static de.otto.edison.hal.Links.linkingTo;
|
||||||
|
import static java.util.stream.Collectors.toList;
|
||||||
|
|
||||||
|
public class PluginDtoCollectionMapper {
|
||||||
|
|
||||||
|
private final ResourceLinks resourceLinks;
|
||||||
|
private final PluginDtoMapper mapper;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public PluginDtoCollectionMapper(ResourceLinks resourceLinks, PluginDtoMapper mapper) {
|
||||||
|
this.resourceLinks = resourceLinks;
|
||||||
|
this.mapper = mapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HalRepresentation map(Collection<PluginWrapper> plugins) {
|
||||||
|
List<PluginDto> dtos = plugins.stream().map(mapper::map).collect(toList());
|
||||||
|
return new HalRepresentation(createLinks(), embedDtos(dtos));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Links createLinks() {
|
||||||
|
String baseUrl = resourceLinks.pluginCollection().self();
|
||||||
|
|
||||||
|
Links.Builder linksBuilder = linkingTo()
|
||||||
|
.with(Links.linkingTo().self(baseUrl).build());
|
||||||
|
return linksBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Embedded embedDtos(List<PluginDto> dtos) {
|
||||||
|
return embeddedBuilder()
|
||||||
|
.with("plugins", dtos)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package sonia.scm.api.v2.resources;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import de.otto.edison.hal.Links;
|
||||||
|
import sonia.scm.plugin.PluginWrapper;
|
||||||
|
import sonia.scm.util.HttpUtil;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static de.otto.edison.hal.Links.linkingTo;
|
||||||
|
|
||||||
|
public class PluginDtoMapper {
|
||||||
|
|
||||||
|
private final ResourceLinks resourceLinks;
|
||||||
|
private final HttpServletRequest request;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public PluginDtoMapper(ResourceLinks resourceLinks, HttpServletRequest request) {
|
||||||
|
this.resourceLinks = resourceLinks;
|
||||||
|
this.request = request;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginDto map(PluginWrapper plugin) {
|
||||||
|
PluginDto pluginDto = new PluginDto();
|
||||||
|
pluginDto.setName(plugin.getPlugin().getInformation().getName());
|
||||||
|
pluginDto.setType(plugin.getPlugin().getInformation().getCategory() != null ? plugin.getPlugin().getInformation().getCategory() : "Sonstige/Miscellaneous");
|
||||||
|
pluginDto.setVersion(plugin.getPlugin().getInformation().getVersion());
|
||||||
|
pluginDto.setAuthor(plugin.getPlugin().getInformation().getAuthor());
|
||||||
|
pluginDto.setDescription(plugin.getPlugin().getInformation().getDescription());
|
||||||
|
|
||||||
|
Links.Builder linksBuilder = linkingTo()
|
||||||
|
.self(resourceLinks.uiPlugin()
|
||||||
|
.self(plugin.getId()));
|
||||||
|
|
||||||
|
pluginDto.add(linksBuilder.build());
|
||||||
|
|
||||||
|
return pluginDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> getScriptResources(PluginWrapper wrapper) {
|
||||||
|
Set<String> scriptResources = wrapper.getPlugin().getResources().getScriptResources();
|
||||||
|
if (scriptResources != null) {
|
||||||
|
return scriptResources.stream()
|
||||||
|
.map(this::addContextPath)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String addContextPath(String resource) {
|
||||||
|
String ctxPath = request.getContextPath();
|
||||||
|
if (Strings.isNullOrEmpty(ctxPath)) {
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
return HttpUtil.append(ctxPath, resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package sonia.scm.api.v2.resources;
|
||||||
|
|
||||||
|
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||||
|
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||||
|
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
||||||
|
import sonia.scm.plugin.PluginLoader;
|
||||||
|
import sonia.scm.plugin.PluginWrapper;
|
||||||
|
import sonia.scm.web.VndMediaType;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class PluginResource {
|
||||||
|
|
||||||
|
private final PluginLoader pluginLoader;
|
||||||
|
private final PluginDtoCollectionMapper collectionMapper;
|
||||||
|
private final PluginDtoMapper mapper;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public PluginResource(PluginLoader pluginLoader, PluginDtoCollectionMapper collectionMapper, PluginDtoMapper mapper) {
|
||||||
|
this.pluginLoader = pluginLoader;
|
||||||
|
this.collectionMapper = collectionMapper;
|
||||||
|
this.mapper = mapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a collection of installed plugins.
|
||||||
|
*
|
||||||
|
* @return collection of installed plugins.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("")
|
||||||
|
@StatusCodes({
|
||||||
|
@ResponseCode(code = 200, condition = "success"),
|
||||||
|
@ResponseCode(code = 500, condition = "internal server error")
|
||||||
|
})
|
||||||
|
@TypeHint(CollectionDto.class)
|
||||||
|
@Produces(VndMediaType.PLUGIN_COLLECTION)
|
||||||
|
public Response getInstalledPlugins() {
|
||||||
|
List<PluginWrapper> plugins = pluginLoader.getInstalledPlugins()
|
||||||
|
.stream()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
return Response.ok(collectionMapper.map(plugins)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the installed plugin with the given id.
|
||||||
|
*
|
||||||
|
* @param id id of plugin
|
||||||
|
*
|
||||||
|
* @return installed plugin with specified id
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("{id}")
|
||||||
|
@StatusCodes({
|
||||||
|
@ResponseCode(code = 200, condition = "success"),
|
||||||
|
@ResponseCode(code = 404, condition = "not found"),
|
||||||
|
@ResponseCode(code = 500, condition = "internal server error")
|
||||||
|
})
|
||||||
|
@TypeHint(PluginDto.class)
|
||||||
|
@Produces(VndMediaType.PLUGIN)
|
||||||
|
public Response getInstalledPlugin(@PathParam("id") String id) {
|
||||||
|
Optional<PluginDto> pluginDto = pluginLoader.getInstalledPlugins()
|
||||||
|
.stream()
|
||||||
|
.filter(plugin -> id.equals(plugin.getId()))
|
||||||
|
.map(mapper::map)
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
if (pluginDto.isPresent()) {
|
||||||
|
return Response.ok(pluginDto.get()).build();
|
||||||
|
} else {
|
||||||
|
return Response.status(Response.Status.NOT_FOUND).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package sonia.scm.api.v2.resources;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Provider;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
|
||||||
|
@Path("v2/")
|
||||||
|
public class PluginRootResource {
|
||||||
|
|
||||||
|
private Provider<PluginResource> pluginResourceProvider;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public PluginRootResource(Provider<PluginResource> pluginResourceProvider) {
|
||||||
|
this.pluginResourceProvider = pluginResourceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Path("plugins")
|
||||||
|
public PluginResource plugins() {
|
||||||
|
return pluginResourceProvider.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -651,6 +651,38 @@ class ResourceLinks {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PluginLinks plugin() {
|
||||||
|
return new PluginLinks(scmPathInfoStore.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
static class PluginLinks {
|
||||||
|
private final LinkBuilder pluginLinkBuilder;
|
||||||
|
|
||||||
|
PluginLinks(ScmPathInfo pathInfo) {
|
||||||
|
pluginLinkBuilder = new LinkBuilder(pathInfo, PluginRootResource.class, PluginResource.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
String self(String id) {
|
||||||
|
return pluginLinkBuilder.method("plugins").parameters().method("getInstalledPlugin").parameters(id).href();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginCollectionLinks pluginCollection() {
|
||||||
|
return new PluginCollectionLinks(scmPathInfoStore.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
static class PluginCollectionLinks {
|
||||||
|
private final LinkBuilder pluginCollectionLinkBuilder;
|
||||||
|
|
||||||
|
PluginCollectionLinks(ScmPathInfo pathInfo) {
|
||||||
|
pluginCollectionLinkBuilder = new LinkBuilder(pathInfo, UIRootResource.class, UIPluginResource.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
String self() {
|
||||||
|
return pluginCollectionLinkBuilder.method("plugins").parameters().method("getInstalledPlugins").parameters().href();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public AuthenticationLinks authentication() {
|
public AuthenticationLinks authentication() {
|
||||||
return new AuthenticationLinks(scmPathInfoStore.get());
|
return new AuthenticationLinks(scmPathInfoStore.get());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user