Merge branch 'develop' into feature/packaging

# Conflicts:
#	Jenkinsfile
#	pom.xml
This commit is contained in:
Sebastian Sdorra
2020-05-23 15:27:43 +02:00
339 changed files with 3978 additions and 8015 deletions

View File

@@ -21,63 +21,64 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm;
//~--- non-JDK imports --------------------------------------------------------
import ch.qos.logback.core.PropertyDefinerBase;
import com.google.common.annotations.VisibleForTesting;
import sonia.scm.util.SystemUtil;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.util.Properties;
/**
* Resolve directory path for SCM-Manager logs.
*
* @author Sebastian Sdorra
*/
public class ScmLogFilePropertyDefiner extends PropertyDefinerBase
{
public class ScmLogFilePropertyDefiner extends PropertyDefinerBase {
/** Field description */
public static final String LOG_DIRECTORY = "logs";
private final String logDirectoryPath;
//~--- constructors ---------------------------------------------------------
public ScmLogFilePropertyDefiner() {
this(SCMContext.getContext(), SystemUtil.getPlatform(), System.getProperties());
}
/**
* Constructs ...
*
*/
public ScmLogFilePropertyDefiner()
{
File logDirectory = new File(SCMContext.getContext().getBaseDirectory(),
LOG_DIRECTORY);
@VisibleForTesting
ScmLogFilePropertyDefiner(SCMContextProvider context, Platform platform, Properties properties) {
File logDirectory = resolveDirectory(context, platform, properties);
if (!logDirectory.exists() &&!logDirectory.mkdirs())
{
if (!logDirectory.exists() && !logDirectory.mkdirs()) {
throw new ConfigurationException(
"could not create log directory ".concat(logDirectory.getPath()));
"could not create log directory ".concat(logDirectory.getPath()));
}
this.logDirectoryPath = logDirectory.getAbsolutePath();
}
//~--- get methods ----------------------------------------------------------
private File resolveDirectory(SCMContextProvider context, Platform platform, Properties properties) {
if (platform.isMac()) {
return resolveOsX(properties);
} else {
return resolveDefault(context);
}
}
private File resolveOsX(Properties properties) {
return new File(properties.getProperty("user.home"), "Library/Logs/SCM-Manager");
}
private File resolveDefault(SCMContextProvider context) {
return new File(context.getBaseDirectory(), "logs");
}
/**
* Method description
*
*
* @return
*/
@Override
public String getPropertyValue()
{
public String getPropertyValue() {
return logDirectoryPath;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private String logDirectoryPath;
}

View File

@@ -21,30 +21,30 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.api.v2;
import org.jboss.resteasy.api.validation.ResteasyViolationException;
import sonia.scm.api.v2.resources.ResteasyViolationExceptionToErrorDtoMapper;
import sonia.scm.web.VndMediaType;
import javax.inject.Inject;
import javax.validation.ConstraintViolationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
@Provider
public class ResteasyValidationExceptionMapper implements ExceptionMapper<ResteasyViolationException> {
public class JavaxValidationExceptionMapper implements ExceptionMapper<ConstraintViolationException> {
private final ResteasyViolationExceptionToErrorDtoMapper mapper;
@Inject
public ResteasyValidationExceptionMapper(ResteasyViolationExceptionToErrorDtoMapper mapper) {
public JavaxValidationExceptionMapper(ResteasyViolationExceptionToErrorDtoMapper mapper) {
this.mapper = mapper;
}
@Override
public Response toResponse(ResteasyViolationException exception) {
public Response toResponse(ConstraintViolationException exception) {
return Response
.status(Response.Status.BAD_REQUEST)
.type(VndMediaType.ERROR_TYPE)

View File

@@ -178,7 +178,7 @@ public class AvailablePluginResource {
)
)
public Response installPlugin(@PathParam("name") String name, @QueryParam("restart") boolean restartAfterInstallation) {
PluginPermissions.manage().check();
PluginPermissions.write().check();
pluginManager.install(name, restartAfterInstallation);
return Response.ok().build();
}

View File

@@ -32,6 +32,7 @@ import org.mapstruct.Mapping;
import org.mapstruct.ObjectFactory;
import sonia.scm.repository.Branch;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.web.EdisonHalAppender;
import javax.inject.Inject;

View File

@@ -24,22 +24,17 @@
package sonia.scm.api.v2.resources;
import com.google.common.annotations.VisibleForTesting;
import de.otto.edison.hal.Embedded;
import de.otto.edison.hal.Links;
import org.mapstruct.Context;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.ObjectFactory;
import org.mapstruct.Qualifier;
import sonia.scm.repository.BrowserResult;
import sonia.scm.repository.FileObject;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.SubRepository;
import sonia.scm.repository.spi.BrowseCommand;
import sonia.scm.repository.spi.BrowseCommandRequest;
import sonia.scm.web.EdisonHalAppender;
import javax.inject.Inject;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -48,9 +43,6 @@ import java.time.Instant;
import java.util.Optional;
import java.util.OptionalLong;
import static de.otto.edison.hal.Embedded.embeddedBuilder;
import static de.otto.edison.hal.Link.link;
@Mapper
public abstract class BrowserResultToFileObjectDtoMapper extends BaseFileObjectDtoMapper {

View File

@@ -37,6 +37,7 @@ import sonia.scm.repository.Tag;
import sonia.scm.repository.api.Command;
import sonia.scm.repository.api.RepositoryService;
import sonia.scm.repository.api.RepositoryServiceFactory;
import sonia.scm.web.EdisonHalAppender;
import javax.inject.Inject;
import java.util.List;

View File

@@ -1,87 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.api.v2.resources;
import de.otto.edison.hal.Embedded;
import de.otto.edison.hal.HalRepresentation;
import de.otto.edison.hal.Link;
import de.otto.edison.hal.Links;
import java.util.ArrayList;
import java.util.List;
class EdisonHalAppender implements HalAppender {
private final Links.Builder linkBuilder;
private final Embedded.Builder embeddedBuilder;
EdisonHalAppender(Links.Builder linkBuilder, Embedded.Builder embeddedBuilder) {
this.linkBuilder = linkBuilder;
this.embeddedBuilder = embeddedBuilder;
}
@Override
public void appendLink(String rel, String href) {
linkBuilder.single(Link.link(rel, href));
}
@Override
public LinkArrayBuilder linkArrayBuilder(String rel) {
return new EdisonLinkArrayBuilder(linkBuilder, rel);
}
@Override
public void appendEmbedded(String rel, HalRepresentation embedded) {
embeddedBuilder.with(rel, embedded);
}
@Override
public void appendEmbedded(String rel, List<HalRepresentation> embedded) {
embeddedBuilder.with(rel, embedded);
}
private static class EdisonLinkArrayBuilder implements LinkArrayBuilder {
private final Links.Builder builder;
private final String rel;
private final List<Link> linkArray = new ArrayList<>();
private EdisonLinkArrayBuilder(Links.Builder builder, String rel) {
this.builder = builder;
this.rel = rel;
}
@Override
public LinkArrayBuilder append(String name, String href) {
linkArray.add(Link.linkBuilder(rel, href).withName(name).build());
return this;
}
@Override
public void build() {
builder.array(linkArray);
}
}
}

View File

@@ -31,6 +31,7 @@ import org.mapstruct.ObjectFactory;
import sonia.scm.group.Group;
import sonia.scm.group.GroupPermissions;
import sonia.scm.security.PermissionPermissions;
import sonia.scm.web.EdisonHalAppender;
import javax.inject.Inject;
import java.util.List;

View File

@@ -38,6 +38,7 @@ import sonia.scm.plugin.PluginPermissions;
import sonia.scm.security.Authentications;
import sonia.scm.security.PermissionPermissions;
import sonia.scm.user.UserPermissions;
import sonia.scm.web.EdisonHalAppender;
import javax.inject.Inject;
import java.util.List;
@@ -82,7 +83,7 @@ public class IndexDtoGenerator extends HalAppenderMapper {
builder.single(link("installedPlugins", resourceLinks.installedPluginCollection().self()));
builder.single(link("availablePlugins", resourceLinks.availablePluginCollection().self()));
}
if (PluginPermissions.manage().isPermitted()) {
if (PluginPermissions.write().isPermitted()) {
builder.single(link("pendingPlugins", resourceLinks.pendingPluginCollection().self()));
}
if (UserPermissions.list().isPermitted()) {

View File

@@ -34,6 +34,7 @@ import sonia.scm.security.Authentications;
import sonia.scm.user.User;
import sonia.scm.user.UserManager;
import sonia.scm.user.UserPermissions;
import sonia.scm.web.EdisonHalAppender;
import javax.inject.Inject;

View File

@@ -118,7 +118,7 @@ public class PendingPluginResource {
List<PluginDto> uninstallDtos = uninstallPlugins.map(i -> mapper.mapInstalled(i, pending)).collect(toList());
if (
PluginPermissions.manage().isPermitted() &&
PluginPermissions.write().isPermitted() &&
(!installDtos.isEmpty() || !updateDtos.isEmpty() || !uninstallDtos.isEmpty())
) {
if (restarter.isSupported()) {

View File

@@ -31,6 +31,7 @@ import de.otto.edison.hal.Links;
import sonia.scm.plugin.AvailablePlugin;
import sonia.scm.plugin.InstalledPlugin;
import sonia.scm.plugin.PluginManager;
import sonia.scm.plugin.PluginPermissions;
import java.util.List;
@@ -71,7 +72,7 @@ public class PluginDtoCollectionMapper {
Links.Builder linksBuilder = linkingTo()
.with(Links.linkingTo().self(baseUrl).build());
if (!manager.getUpdatable().isEmpty()) {
if (!manager.getUpdatable().isEmpty() && PluginPermissions.write().isPermitted()) {
linksBuilder.single(link("update", resourceLinks.installedPluginCollection().update()));
}

View File

@@ -81,7 +81,7 @@ public abstract class PluginDtoMapper {
.self(resourceLinks.availablePlugin()
.self(information.getName()));
if (!plugin.isPending() && PluginPermissions.manage().isPermitted()) {
if (!plugin.isPending() && PluginPermissions.write().isPermitted()) {
String href = resourceLinks.availablePlugin().install(information.getName());
appendLink(links, "install", href);
}
@@ -106,7 +106,7 @@ public abstract class PluginDtoMapper {
if (!plugin.isCore()
&& availablePlugin.isPresent()
&& !availablePlugin.get().isPending()
&& PluginPermissions.manage().isPermitted()
&& PluginPermissions.write().isPermitted()
) {
String href = resourceLinks.availablePlugin().install(information.getName());
appendLink(links, "update", href);
@@ -114,7 +114,7 @@ public abstract class PluginDtoMapper {
if (plugin.isUninstallable()
&& (!availablePlugin.isPresent() || !availablePlugin.get().isPending())
&& PluginPermissions.manage().isPermitted()
&& PluginPermissions.write().isPermitted()
) {
String href = resourceLinks.installedPlugin().uninstall(information.getName());
appendLink(links, "uninstall", href);

View File

@@ -30,6 +30,7 @@ import org.mapstruct.Mapper;
import org.mapstruct.ObjectFactory;
import sonia.scm.repository.RepositoryRole;
import sonia.scm.repository.RepositoryRolePermissions;
import sonia.scm.web.EdisonHalAppender;
import javax.inject.Inject;

View File

@@ -38,6 +38,7 @@ import sonia.scm.repository.api.Command;
import sonia.scm.repository.api.RepositoryService;
import sonia.scm.repository.api.RepositoryServiceFactory;
import sonia.scm.repository.api.ScmProtocol;
import sonia.scm.web.EdisonHalAppender;
import sonia.scm.web.api.RepositoryToHalMapper;
import java.util.List;

View File

@@ -21,10 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.api.v2.resources;
import org.jboss.resteasy.api.validation.ResteasyViolationException;
import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@@ -32,6 +31,7 @@ import org.mapstruct.MappingTarget;
import org.slf4j.MDC;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.stream.Collectors;
@@ -42,7 +42,8 @@ public abstract class ResteasyViolationExceptionToErrorDtoMapper {
@Mapping(target = "transactionId", ignore = true)
@Mapping(target = "context", ignore = true)
@Mapping(target = "url", ignore = true)
public abstract ErrorDto map(ResteasyViolationException exception);
@Mapping(target = "violations", ignore = true)
public abstract ErrorDto map(ConstraintViolationException exception);
@AfterMapping
void setTransactionId(@MappingTarget ErrorDto dto) {
@@ -50,7 +51,7 @@ public abstract class ResteasyViolationExceptionToErrorDtoMapper {
}
@AfterMapping
void mapViolations(ResteasyViolationException exception, @MappingTarget ErrorDto dto) {
void mapViolations(ConstraintViolationException exception, @MappingTarget ErrorDto dto) {
List<ErrorDto.ConstraintViolationDto> violations =
exception.getConstraintViolations()
.stream()

View File

@@ -32,6 +32,7 @@ import org.mapstruct.Mapping;
import org.mapstruct.ObjectFactory;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.Tag;
import sonia.scm.web.EdisonHalAppender;
import javax.inject.Inject;

View File

@@ -33,6 +33,7 @@ import sonia.scm.security.PermissionPermissions;
import sonia.scm.user.User;
import sonia.scm.user.UserManager;
import sonia.scm.user.UserPermissions;
import sonia.scm.web.EdisonHalAppender;
import javax.inject.Inject;

View File

@@ -21,11 +21,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.filter;
import java.util.Objects;
import lombok.Value;
import sonia.scm.plugin.WebElementDescriptor;
/**
@@ -34,48 +33,8 @@ import sonia.scm.plugin.WebElementDescriptor;
* @param <T>
* @since 2.0.0
*/
public final class TypedWebElementDescriptor<T>
{
private final Class<T> clazz;
private final WebElementDescriptor descriptor;
public TypedWebElementDescriptor(Class<T> clazz,
WebElementDescriptor descriptor)
{
this.clazz = clazz;
this.descriptor = descriptor;
}
public Class<T> getClazz()
{
return clazz;
}
public WebElementDescriptor getDescriptor()
{
return descriptor;
}
@Override
public int hashCode() {
return Objects.hash(clazz, descriptor);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final TypedWebElementDescriptor other = (TypedWebElementDescriptor) obj;
return Objects.equals(clazz, other.clazz)
&& Objects.equals(descriptor, other.descriptor);
}
@Value
public class TypedWebElementDescriptor<T> {
Class<T> clazz;
WebElementDescriptor descriptor;
}

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.filter;
//~--- non-JDK imports --------------------------------------------------------
@@ -35,7 +35,7 @@ import org.slf4j.LoggerFactory;
import sonia.scm.Priorities;
import sonia.scm.plugin.PluginLoader;
import sonia.scm.plugin.WebElementDescriptor;
import sonia.scm.plugin.WebElementExtension;
//~--- JDK imports ------------------------------------------------------------
@@ -67,25 +67,24 @@ public final class WebElementCollector
* @param elements
*/
@SuppressWarnings("unchecked")
private WebElementCollector(Iterable<WebElementDescriptor> elements)
private WebElementCollector(Iterable<WebElementExtension> elements)
{
List<TypedWebElementDescriptor<? extends Filter>> fl = Lists.newArrayList();
List<TypedWebElementDescriptor<? extends HttpServlet>> sl =
Lists.newArrayList();
List<TypedWebElementDescriptor<Filter>> fl = Lists.newArrayList();
List<TypedWebElementDescriptor<HttpServlet>> sl = Lists.newArrayList();
for (WebElementDescriptor element : elements)
for (WebElementExtension element : elements)
{
if (Filter.class.isAssignableFrom(element.getClazz()))
{
fl.add(
new TypedWebElementDescriptor<>(
(Class<? extends Filter>) element.getClazz(), element));
(Class<Filter>) element.getClazz(), element.getDescriptor()));
}
else if (Servlet.class.isAssignableFrom(element.getClazz()))
{
sl.add(
new TypedWebElementDescriptor<>(
(Class<? extends HttpServlet>) element.getClazz(), element));
(Class<HttpServlet>) element.getClazz(), element.getDescriptor()));
}
else
{
@@ -95,8 +94,7 @@ public final class WebElementCollector
}
}
TypedWebElementDescriptorOrdering ordering =
new TypedWebElementDescriptorOrdering();
TypedWebElementDescriptorOrdering ordering = new TypedWebElementDescriptorOrdering();
filters = ordering.immutableSortedCopy(fl);
servlets = ordering.immutableSortedCopy(sl);
@@ -126,7 +124,7 @@ public final class WebElementCollector
*
* @return
*/
public Iterable<TypedWebElementDescriptor<? extends Filter>> getFilters()
public Iterable<TypedWebElementDescriptor<Filter>> getFilters()
{
return filters;
}
@@ -137,7 +135,7 @@ public final class WebElementCollector
*
* @return
*/
public Iterable<TypedWebElementDescriptor<? extends HttpServlet>> getServlets()
public Iterable<TypedWebElementDescriptor<HttpServlet>> getServlets()
{
return servlets;
}
@@ -177,8 +175,8 @@ public final class WebElementCollector
//~--- fields ---------------------------------------------------------------
/** Field description */
private final Iterable<TypedWebElementDescriptor<? extends Filter>> filters;
private final Iterable<TypedWebElementDescriptor<Filter>> filters;
/** Field description */
private final Iterable<TypedWebElementDescriptor<? extends HttpServlet>> servlets;
private final Iterable<TypedWebElementDescriptor<HttpServlet>> servlets;
}

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.filter;
//~--- non-JDK imports --------------------------------------------------------
@@ -44,60 +44,36 @@ import javax.servlet.http.HttpServlet;
*
* @author Sebastian Sdorra
*/
public class WebElementModule extends ServletModule
{
public class WebElementModule extends ServletModule {
/**
* the logger for WebElementModule
*/
private static final Logger logger =
LoggerFactory.getLogger(WebElementModule.class);
private static final Logger LOG = LoggerFactory.getLogger(WebElementModule.class);
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param pluginLoader
*/
public WebElementModule(PluginLoader pluginLoader)
{
collector = WebElementCollector.collect(pluginLoader);
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*/
@Override
protected void configureServlets()
{
for (TypedWebElementDescriptor<? extends Filter> f : collector.getFilters())
for (TypedWebElementDescriptor<Filter> f : collector.getFilters())
{
bindFilter(f);
}
for (TypedWebElementDescriptor<? extends HttpServlet> s :
collector.getServlets())
for (TypedWebElementDescriptor<HttpServlet> s : collector.getServlets())
{
bindServlet(s);
}
}
/**
* Method description
*
*
* @param filter
*/
private void bindFilter(TypedWebElementDescriptor<? extends Filter> filter)
{
Class<? extends Filter> clazz = filter.getClazz();
private void bindFilter(TypedWebElementDescriptor<Filter> filter) {
Class<Filter> clazz = filter.getClazz();
logger.info("bind filter {} to filter chain", clazz);
LOG.info("bind filter {} to filter chain", clazz);
// filters must be in singleton scope
bind(clazz).in(Scopes.SINGLETON);
@@ -105,12 +81,13 @@ public class WebElementModule extends ServletModule
WebElementDescriptor opts = filter.getDescriptor();
FilterKeyBindingBuilder builder;
if (opts.isRegex())
{
if (opts.isRegex()) {
LOG.debug("bind regex filter {} to {} and {}", clazz, opts.getPattern(), opts.getMorePatterns());
builder = filterRegex(opts.getPattern(), opts.getMorePatterns());
}
else
{
LOG.debug("bind glob filter {} to {} and {}", clazz, opts.getPattern(), opts.getMorePatterns());
builder = filter(opts.getPattern(), opts.getMorePatterns());
}
@@ -118,18 +95,10 @@ public class WebElementModule extends ServletModule
builder.through(clazz);
}
/**
* Method description
*
*
* @param servlet
*/
private void bindServlet(
TypedWebElementDescriptor<? extends HttpServlet> servlet)
{
Class<? extends HttpServlet> clazz = servlet.getClazz();
private void bindServlet(TypedWebElementDescriptor<HttpServlet> servlet) {
Class<HttpServlet> clazz = servlet.getClazz();
logger.info("bind servlet {} to servlet chain", clazz);
LOG.info("bind servlet {} to servlet chain", clazz);
// filters must be in singleton scope
bind(clazz).in(Scopes.SINGLETON);
@@ -137,12 +106,11 @@ public class WebElementModule extends ServletModule
WebElementDescriptor opts = servlet.getDescriptor();
ServletKeyBindingBuilder builder;
if (opts.isRegex())
{
if (opts.isRegex()) {
LOG.debug("bind regex servlet {} to {} and {}", clazz, opts.getPattern(), opts.getMorePatterns());
builder = serveRegex(opts.getPattern(), opts.getMorePatterns());
}
else
{
} else {
LOG.debug("bind glob servlet {} to {} and {}", clazz, opts.getPattern(), opts.getMorePatterns());
builder = serve(opts.getPattern(), opts.getMorePatterns());
}

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.lifecycle.modules;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -193,7 +193,7 @@ class ScmServletModule extends ServletModule {
// bind sslcontext provider
bind(SSLContext.class).toProvider(SSLContextProvider.class);
// bind ahc
Multibinder<ContentTransformer> transformers =
Multibinder.newSetBinder(binder(), ContentTransformer.class);
@@ -207,7 +207,7 @@ class ScmServletModule extends ServletModule {
// bind new hook api
bind(HookContextFactory.class);
bind(HookEventFacade.class);
// bind user-agent parser
bind(UserAgentParser.class);
@@ -215,7 +215,7 @@ class ScmServletModule extends ServletModule {
if ("true".equalsIgnoreCase(System.getProperty(SYSTEM_PROPERTY_DEBUG_HTTP))) {
filter(PATTERN_ALL).through(LoggingFilter.class);
}
// debug servlet
serve(PATTERN_DEBUG).with(DebugServlet.class);

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.plugin;
//~--- non-JDK imports --------------------------------------------------------
@@ -115,7 +115,7 @@ public class DefaultExtensionProcessor implements ExtensionProcessor
* @return
*/
@Override
public Iterable<WebElementDescriptor> getWebElements()
public Iterable<WebElementExtension> getWebElements()
{
return collector.getWebElements();
}

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.plugin;
//~--- non-JDK imports --------------------------------------------------------
@@ -29,25 +29,17 @@ package sonia.scm.plugin;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.collect.Iterables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//~--- JDK imports ------------------------------------------------------------
import javax.servlet.ServletContext;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
//~--- JDK imports ------------------------------------------------------------
/**
*
@@ -62,10 +54,6 @@ public class DefaultPluginLoader implements PluginLoader
/** Field description */
public static final String PATH_PLUGINCONFIG = "META-INF/scm/plugin.xml";
/** the logger for DefaultPluginLoader */
private static final Logger logger =
LoggerFactory.getLogger(DefaultPluginLoader.class);
//~--- constructors ---------------------------------------------------------
/**
@@ -90,7 +78,7 @@ public class DefaultPluginLoader implements PluginLoader
modules = getInstalled(parent, context, PATH_MODULECONFIG);
collector = new ExtensionCollector(parent, modules, installedPlugins);
ExtensionCollector collector = new ExtensionCollector(parent, modules, installedPlugins);
extensionProcessor = new DefaultExtensionProcessor(collector);
}
catch (IOException | JAXBException ex)
@@ -198,9 +186,6 @@ public class DefaultPluginLoader implements PluginLoader
//~--- fields ---------------------------------------------------------------
/** Field description */
private final ExtensionCollector collector;
/** Field description */
private final ExtensionProcessor extensionProcessor;

View File

@@ -157,7 +157,7 @@ public class DefaultPluginManager implements PluginManager {
@Override
public void install(String name, boolean restartAfterInstallation) {
PluginPermissions.manage().check();
PluginPermissions.write().check();
getInstalled(name)
.map(InstalledPlugin::isCore)
@@ -192,7 +192,7 @@ public class DefaultPluginManager implements PluginManager {
@Override
public void uninstall(String name, boolean restartAfterInstallation) {
PluginPermissions.manage().check();
PluginPermissions.write().check();
InstalledPlugin installed = getInstalled(name)
.orElseThrow(() -> NotFoundException.notFound(entity(InstalledPlugin.class, name)));
doThrow().violation("plugin is a core plugin and cannot be uninstalled").when(installed.isCore());
@@ -231,7 +231,7 @@ public class DefaultPluginManager implements PluginManager {
@Override
public void executePendingAndRestart() {
PluginPermissions.manage().check();
PluginPermissions.write().check();
if (!pendingInstallQueue.isEmpty() || getInstalled().stream().anyMatch(InstalledPlugin::isMarkedForUninstall)) {
triggerRestart("execute pending plugin changes");
}
@@ -278,7 +278,7 @@ public class DefaultPluginManager implements PluginManager {
@Override
public void cancelPending() {
PluginPermissions.manage().check();
PluginPermissions.write().check();
pendingUninstallQueue.forEach(PendingPluginUninstallation::cancel);
pendingInstallQueue.forEach(PendingPluginInstallation::cancel);
pendingUninstallQueue.clear();
@@ -288,7 +288,7 @@ public class DefaultPluginManager implements PluginManager {
@Override
public void updateAll() {
PluginPermissions.manage().check();
PluginPermissions.write().check();
for (InstalledPlugin installedPlugin : getInstalled()) {
String pluginName = installedPlugin.getDescriptor().getInformation().getName();
if (isUpdatable(pluginName)) {

View File

@@ -21,22 +21,19 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.plugin;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//~--- JDK imports ------------------------------------------------------------
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -45,6 +42,8 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
//~--- JDK imports ------------------------------------------------------------
/**
*
* @author Sebastian Sdorra
@@ -63,6 +62,7 @@ public final class ExtensionCollector
for (ScmModule module : modules) {
collectRootElements(moduleClassLoader, module);
}
for (InstalledPlugin plugin : installedPlugins) {
collectRootElements(plugin.getClassLoader(), plugin.getDescriptor());
}
@@ -98,7 +98,7 @@ public final class ExtensionCollector
if (collection == null)
{
collection = Collections.EMPTY_SET;
collection = Collections.emptySet();
}
return collection;
@@ -123,7 +123,7 @@ public final class ExtensionCollector
}
else
{
exts = Collections.EMPTY_SET;
exts = Collections.emptySet();
}
return exts;
@@ -218,7 +218,7 @@ public final class ExtensionCollector
*
* @return
*/
public Set<WebElementDescriptor> getWebElements()
public Set<WebElementExtension> getWebElements()
{
return webElements;
}
@@ -272,6 +272,17 @@ public final class ExtensionCollector
return classes;
}
private Set<WebElementExtension> collectWebElementExtensions(ClassLoader defaultClassLoader, Iterable<WebElementDescriptor> descriptors) {
Set<WebElementExtension> webElementExtensions = new HashSet<>();
for (WebElementDescriptor descriptor : descriptors) {
if (isRequirementFulfilled(descriptor)) {
Class<?> loadedClass = loadExtension(defaultClassLoader, descriptor);
webElementExtensions.add(new WebElementExtension(loadedClass, descriptor));
}
}
return webElementExtensions;
}
private Class<?> loadExtension(ClassLoader classLoader, ClassElement extension) {
try {
return classLoader.loadClass(extension.getClazz());
@@ -307,13 +318,14 @@ public final class ExtensionCollector
restProviders.addAll(collectClasses(classLoader, module.getRestProviders()));
restResources.addAll(collectClasses(classLoader, module.getRestResources()));
Iterables.addAll(webElements, module.getWebElements());
webElements.addAll(collectWebElementExtensions(classLoader, module.getWebElements()));
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private final Set<WebElementDescriptor> webElements = Sets.newHashSet();
private final Set<WebElementExtension> webElements = Sets.newHashSet();
/** Field description */
private final Set<Class> restResources = Sets.newHashSet();