From 81e8dc428cb3ef55a6541fafbca1dd62f72932c7 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 16 Apr 2020 11:57:38 +0200 Subject: [PATCH 1/4] support requires annotation on WebElements --- .../java/sonia/scm/plugin/ClassElement.java | 5 +- .../sonia/scm/plugin/ExtensionProcessor.java | 4 +- .../scm/plugin/WebElementDescriptor.java | 159 ++++-------------- .../sonia/scm/plugin/WebElementExtension.java | 43 +++++ .../scm/plugin/WebElementDescriptorTest.java | 77 +++++++++ .../sonia/scm/filter/WebElementCollector.java | 12 +- .../lifecycle/modules/ScmServletModule.java | 8 +- .../scm/plugin/DefaultExtensionProcessor.java | 4 +- .../sonia/scm/plugin/ExtensionCollector.java | 26 ++- 9 files changed, 188 insertions(+), 150 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/plugin/WebElementExtension.java create mode 100644 scm-core/src/test/java/sonia/scm/plugin/WebElementDescriptorTest.java diff --git a/scm-core/src/main/java/sonia/scm/plugin/ClassElement.java b/scm-core/src/main/java/sonia/scm/plugin/ClassElement.java index 36855e932a..b439f80545 100644 --- a/scm-core/src/main/java/sonia/scm/plugin/ClassElement.java +++ b/scm-core/src/main/java/sonia/scm/plugin/ClassElement.java @@ -26,6 +26,7 @@ package sonia.scm.plugin; //~--- non-JDK imports -------------------------------------------------------- +import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -43,12 +44,12 @@ import java.util.Set; * @since 2.0.0 */ @Getter -@NoArgsConstructor @AllArgsConstructor @ToString @EqualsAndHashCode @XmlAccessorType(XmlAccessType.FIELD) -public final class ClassElement { +@NoArgsConstructor(access = AccessLevel.PACKAGE) +public class ClassElement { @XmlElement(name = "class") private String clazz; private String description; diff --git a/scm-core/src/main/java/sonia/scm/plugin/ExtensionProcessor.java b/scm-core/src/main/java/sonia/scm/plugin/ExtensionProcessor.java index 4901998109..0fe06f1764 100644 --- a/scm-core/src/main/java/sonia/scm/plugin/ExtensionProcessor.java +++ b/scm-core/src/main/java/sonia/scm/plugin/ExtensionProcessor.java @@ -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 -------------------------------------------------------- @@ -76,5 +76,5 @@ public interface ExtensionProcessor * * @return collected web elements */ - public Iterable getWebElements(); + public Iterable getWebElements(); } diff --git a/scm-core/src/main/java/sonia/scm/plugin/WebElementDescriptor.java b/scm-core/src/main/java/sonia/scm/plugin/WebElementDescriptor.java index e9f3cc1410..65651b1616 100644 --- a/scm-core/src/main/java/sonia/scm/plugin/WebElementDescriptor.java +++ b/scm-core/src/main/java/sonia/scm/plugin/WebElementDescriptor.java @@ -21,155 +21,60 @@ * 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 lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; import sonia.scm.xml.XmlArrayStringAdapter; -//~--- JDK imports ------------------------------------------------------------ - -import java.util.Arrays; -import java.util.Objects; - import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import java.util.Arrays; /** - * Descriptor for web elements such as filter or servlets. A web element can be registered by using the + * Descriptor for web elements such as filter or servlets. A web element can be registered by using the * {@link sonia.scm.filter.WebElement} annotation. - * + * * @author Sebastian Sdorra * @since 2.0.0 */ +@Getter +@AllArgsConstructor +@ToString +@EqualsAndHashCode @XmlRootElement(name = "web-element") @XmlAccessorType(XmlAccessType.FIELD) -public final class WebElementDescriptor -{ +@NoArgsConstructor(access = AccessLevel.PACKAGE) +public final class WebElementDescriptor extends ClassElement { - /** - * Constructs ... - * - */ - WebElementDescriptor() {} - - /** - * Constructs ... - * - * - * @param clazz - * @param pattern - * @param morePatterns - * @param regex - */ - public WebElementDescriptor(Class clazz, String pattern, - String[] morePatterns, boolean regex) - { - this.clazz = clazz; - this.pattern = pattern; - this.morePatterns = morePatterns; - this.regex = regex; - } - - //~--- get methods ---------------------------------------------------------- - - /** - * Method description - * - * - * @return - */ - public Class getClazz() - { - return clazz; - } - - /** - * Method description - * - * - * @return - */ - public String[] getMorePatterns() - { - String[] patterns; - - if (morePatterns != null) - { - patterns = Arrays.copyOf(morePatterns, morePatterns.length); - } - else - { - patterns = new String[0]; - } - - return patterns; - } - - /** - * Method description - * - * - * @return - */ - public String getPattern() - { - return pattern; - } - - /** - * Method description - * - * - * @return - */ - public boolean isRegex() - { - return regex; - } - - @Override - public int hashCode() { - return Objects.hash(clazz, pattern, Arrays.hashCode(morePatterns), regex); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - - final WebElementDescriptor other = (WebElementDescriptor) obj; - return Objects.equals(clazz, other.clazz) - && Objects.equals(pattern, other.pattern) - && Arrays.equals(morePatterns, other.morePatterns) - && this.regex == other.regex; - } - - //~--- fields --------------------------------------------------------------- - - /** Field description */ - @XmlElement(name = "class") - private Class clazz; - - /** Field description */ - @XmlJavaTypeAdapter(XmlArrayStringAdapter.class) - private String[] morePatterns; - - /** Field description */ @XmlElement(name = "value") private String pattern; - /** Field description */ + @XmlJavaTypeAdapter(XmlArrayStringAdapter.class) + private String[] morePatterns = {}; + private boolean regex = false; + + public String[] getMorePatterns() { + String[] patterns; + if (morePatterns != null) { + patterns = Arrays.copyOf(morePatterns, morePatterns.length); + } else { + patterns = new String[0]; + } + return patterns; + } + } + + diff --git a/scm-core/src/main/java/sonia/scm/plugin/WebElementExtension.java b/scm-core/src/main/java/sonia/scm/plugin/WebElementExtension.java new file mode 100644 index 0000000000..e3a83b6853 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/plugin/WebElementExtension.java @@ -0,0 +1,43 @@ +/* + * 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.plugin; + +import lombok.Value; + +/** + * WebElementExtension can be a servlet or filter which is ready to bind. + * Those extensions are loaded by the {@link ExtensionProcessor} from a {@link WebElementDescriptor}. + * + * We don't know if we can load the defined class from the descriptor, because the class could be optional + * (annotated with {@link Requires}). So we have to load the class as string with {@link WebElementDescriptor} and when + * we know that it is safe to load the class (all requirements are fulfilled), we will create our WebElementExtension. + * + * @since 2.0.0 + */ +@Value +public class WebElementExtension { + Class clazz; + WebElementDescriptor descriptor; +} diff --git a/scm-core/src/test/java/sonia/scm/plugin/WebElementDescriptorTest.java b/scm-core/src/test/java/sonia/scm/plugin/WebElementDescriptorTest.java new file mode 100644 index 0000000000..bbbefb1dcd --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/plugin/WebElementDescriptorTest.java @@ -0,0 +1,77 @@ +/* + * 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.plugin; + +import org.junit.jupiter.api.Test; + +import javax.xml.bind.JAXB; + +import java.io.StringReader; + +import static org.assertj.core.api.Assertions.assertThat; + +class WebElementDescriptorTest { + + private static final String XML_1 = String.join("\n", + "", + " com.hitchhiker.SpaceShip", + " /space/*", + " false", + " /ship/*,/star/*", + " scm-magrathea-plugin", + " scm-earth-plugin", + "" + ); + private static final String XML_2 = String.join("\n", + "", + " com.hitchhiker.SpaceShip", + " /space/.*", + " true", + "" + ); + + @Test + void shouldUnmarshall() { + WebElementDescriptor descriptor = unmarshal(XML_1); + assertThat(descriptor.getClazz()).isEqualTo("com.hitchhiker.SpaceShip"); + assertThat(descriptor.getPattern()).isEqualTo("/space/*"); + assertThat(descriptor.getMorePatterns()).containsExactly("/ship/*", "/star/*"); + assertThat(descriptor.isRegex()).isFalse(); + assertThat(descriptor.getRequires()).containsExactlyInAnyOrder("scm-magrathea-plugin", "scm-earth-plugin"); + } + + @Test + void shouldUnmarshallWithoutMorePatterns() { + WebElementDescriptor descriptor = unmarshal(XML_2); + assertThat(descriptor.getClazz()).isEqualTo("com.hitchhiker.SpaceShip"); + assertThat(descriptor.getMorePatterns()).isEmpty(); + assertThat(descriptor.isRegex()).isTrue(); + } + + private WebElementDescriptor unmarshal(String content) { + return JAXB.unmarshal(new StringReader(content), WebElementDescriptor.class); + } + +} diff --git a/scm-webapp/src/main/java/sonia/scm/filter/WebElementCollector.java b/scm-webapp/src/main/java/sonia/scm/filter/WebElementCollector.java index 90a45cc6c8..da073deefa 100644 --- a/scm-webapp/src/main/java/sonia/scm/filter/WebElementCollector.java +++ b/scm-webapp/src/main/java/sonia/scm/filter/WebElementCollector.java @@ -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,25 @@ public final class WebElementCollector * @param elements */ @SuppressWarnings("unchecked") - private WebElementCollector(Iterable elements) + private WebElementCollector(Iterable elements) { List> fl = Lists.newArrayList(); List> sl = Lists.newArrayList(); - for (WebElementDescriptor element : elements) + for (WebElementExtension element : elements) { if (Filter.class.isAssignableFrom(element.getClazz())) { fl.add( new TypedWebElementDescriptor<>( - (Class) element.getClazz(), element)); + (Class) element.getClazz(), element.getDescriptor())); } else if (Servlet.class.isAssignableFrom(element.getClazz())) { sl.add( new TypedWebElementDescriptor<>( - (Class) element.getClazz(), element)); + (Class) element.getClazz(), element.getDescriptor())); } else { diff --git a/scm-webapp/src/main/java/sonia/scm/lifecycle/modules/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/lifecycle/modules/ScmServletModule.java index 715dad4d69..ba83f5faea 100644 --- a/scm-webapp/src/main/java/sonia/scm/lifecycle/modules/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/lifecycle/modules/ScmServletModule.java @@ -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 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); diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/DefaultExtensionProcessor.java b/scm-webapp/src/main/java/sonia/scm/plugin/DefaultExtensionProcessor.java index 1b96f3b4bf..6cc7deed77 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/DefaultExtensionProcessor.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/DefaultExtensionProcessor.java @@ -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 getWebElements() + public Iterable getWebElements() { return collector.getWebElements(); } diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/ExtensionCollector.java b/scm-webapp/src/main/java/sonia/scm/plugin/ExtensionCollector.java index 99a87f5814..dadb7618a3 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/ExtensionCollector.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/ExtensionCollector.java @@ -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()); } @@ -218,7 +218,7 @@ public final class ExtensionCollector * * @return */ - public Set getWebElements() + public Set getWebElements() { return webElements; } @@ -272,6 +272,17 @@ public final class ExtensionCollector return classes; } + private Set collectWebElementExtensions(ClassLoader defaultClassLoader, Iterable descriptors) { + Set 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 webElements = Sets.newHashSet(); + private final Set webElements = Sets.newHashSet(); /** Field description */ private final Set restResources = Sets.newHashSet(); From 0d4976ecf199fd6f6e77148562437525009b4d81 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 16 Apr 2020 12:03:12 +0200 Subject: [PATCH 2/4] fixed some sonarqube findings --- .../scm/filter/TypedWebElementDescriptor.java | 53 +++---------------- .../sonia/scm/filter/WebElementCollector.java | 20 ++++--- .../sonia/scm/filter/WebElementModule.java | 15 +++--- .../sonia/scm/plugin/DefaultPluginLoader.java | 27 +++------- .../sonia/scm/plugin/ExtensionCollector.java | 4 +- 5 files changed, 30 insertions(+), 89 deletions(-) diff --git a/scm-webapp/src/main/java/sonia/scm/filter/TypedWebElementDescriptor.java b/scm-webapp/src/main/java/sonia/scm/filter/TypedWebElementDescriptor.java index 4a69c7540c..c3ef626f5c 100644 --- a/scm-webapp/src/main/java/sonia/scm/filter/TypedWebElementDescriptor.java +++ b/scm-webapp/src/main/java/sonia/scm/filter/TypedWebElementDescriptor.java @@ -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 * @since 2.0.0 */ -public final class TypedWebElementDescriptor -{ - private final Class clazz; - private final WebElementDescriptor descriptor; - - public TypedWebElementDescriptor(Class clazz, - WebElementDescriptor descriptor) - { - this.clazz = clazz; - this.descriptor = descriptor; - } - - public Class 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 { + Class clazz; + WebElementDescriptor descriptor; } diff --git a/scm-webapp/src/main/java/sonia/scm/filter/WebElementCollector.java b/scm-webapp/src/main/java/sonia/scm/filter/WebElementCollector.java index da073deefa..d37a2e90c5 100644 --- a/scm-webapp/src/main/java/sonia/scm/filter/WebElementCollector.java +++ b/scm-webapp/src/main/java/sonia/scm/filter/WebElementCollector.java @@ -69,9 +69,8 @@ public final class WebElementCollector @SuppressWarnings("unchecked") private WebElementCollector(Iterable elements) { - List> fl = Lists.newArrayList(); - List> sl = - Lists.newArrayList(); + List> fl = Lists.newArrayList(); + List> sl = Lists.newArrayList(); for (WebElementExtension element : elements) { @@ -79,13 +78,13 @@ public final class WebElementCollector { fl.add( new TypedWebElementDescriptor<>( - (Class) element.getClazz(), element.getDescriptor())); + (Class) element.getClazz(), element.getDescriptor())); } else if (Servlet.class.isAssignableFrom(element.getClazz())) { sl.add( new TypedWebElementDescriptor<>( - (Class) element.getClazz(), element.getDescriptor())); + (Class) 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> getFilters() + public Iterable> getFilters() { return filters; } @@ -137,7 +135,7 @@ public final class WebElementCollector * * @return */ - public Iterable> getServlets() + public Iterable> getServlets() { return servlets; } @@ -177,8 +175,8 @@ public final class WebElementCollector //~--- fields --------------------------------------------------------------- /** Field description */ - private final Iterable> filters; + private final Iterable> filters; /** Field description */ - private final Iterable> servlets; + private final Iterable> servlets; } diff --git a/scm-webapp/src/main/java/sonia/scm/filter/WebElementModule.java b/scm-webapp/src/main/java/sonia/scm/filter/WebElementModule.java index 482deb063b..9b19b9a7f5 100644 --- a/scm-webapp/src/main/java/sonia/scm/filter/WebElementModule.java +++ b/scm-webapp/src/main/java/sonia/scm/filter/WebElementModule.java @@ -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 -------------------------------------------------------- @@ -75,13 +75,12 @@ public class WebElementModule extends ServletModule @Override protected void configureServlets() { - for (TypedWebElementDescriptor f : collector.getFilters()) + for (TypedWebElementDescriptor f : collector.getFilters()) { bindFilter(f); } - for (TypedWebElementDescriptor s : - collector.getServlets()) + for (TypedWebElementDescriptor s : collector.getServlets()) { bindServlet(s); } @@ -93,9 +92,9 @@ public class WebElementModule extends ServletModule * * @param filter */ - private void bindFilter(TypedWebElementDescriptor filter) + private void bindFilter(TypedWebElementDescriptor filter) { - Class clazz = filter.getClazz(); + Class clazz = filter.getClazz(); logger.info("bind filter {} to filter chain", clazz); @@ -125,9 +124,9 @@ public class WebElementModule extends ServletModule * @param servlet */ private void bindServlet( - TypedWebElementDescriptor servlet) + TypedWebElementDescriptor servlet) { - Class clazz = servlet.getClazz(); + Class clazz = servlet.getClazz(); logger.info("bind servlet {} to servlet chain", clazz); diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginLoader.java b/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginLoader.java index 77f6b392b9..90f349a3b1 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginLoader.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginLoader.java @@ -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; diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/ExtensionCollector.java b/scm-webapp/src/main/java/sonia/scm/plugin/ExtensionCollector.java index dadb7618a3..2d2b11ebdb 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/ExtensionCollector.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/ExtensionCollector.java @@ -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; From 6da7efdb9b104672d39254dc90f4ae62b9e63205 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 16 Apr 2020 13:49:43 +0200 Subject: [PATCH 3/4] fixed missing servlets and filters WebElements with same attributes are not bound, because they are stored in a HashSet and the fields from the parent class were not used for hashCode and equals. The equals and hashCode methods of WebElementDescriptor are now taking the fields of ClassElement in account. --- .../scm/plugin/WebElementDescriptor.java | 4 +- .../sonia/scm/filter/WebElementModule.java | 57 +++++-------------- 2 files changed, 15 insertions(+), 46 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/plugin/WebElementDescriptor.java b/scm-core/src/main/java/sonia/scm/plugin/WebElementDescriptor.java index 65651b1616..d5dabb9698 100644 --- a/scm-core/src/main/java/sonia/scm/plugin/WebElementDescriptor.java +++ b/scm-core/src/main/java/sonia/scm/plugin/WebElementDescriptor.java @@ -49,9 +49,9 @@ import java.util.Arrays; * @since 2.0.0 */ @Getter -@AllArgsConstructor @ToString -@EqualsAndHashCode +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) @XmlRootElement(name = "web-element") @XmlAccessorType(XmlAccessType.FIELD) @NoArgsConstructor(access = AccessLevel.PACKAGE) diff --git a/scm-webapp/src/main/java/sonia/scm/filter/WebElementModule.java b/scm-webapp/src/main/java/sonia/scm/filter/WebElementModule.java index 9b19b9a7f5..eb5f2c1cc8 100644 --- a/scm-webapp/src/main/java/sonia/scm/filter/WebElementModule.java +++ b/scm-webapp/src/main/java/sonia/scm/filter/WebElementModule.java @@ -44,34 +44,18 @@ 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() { @@ -86,17 +70,10 @@ public class WebElementModule extends ServletModule } } - /** - * Method description - * - * - * @param filter - */ - private void bindFilter(TypedWebElementDescriptor filter) - { + private void bindFilter(TypedWebElementDescriptor filter) { Class 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); @@ -104,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()); } @@ -117,18 +95,10 @@ public class WebElementModule extends ServletModule builder.through(clazz); } - /** - * Method description - * - * - * @param servlet - */ - private void bindServlet( - TypedWebElementDescriptor servlet) - { + private void bindServlet(TypedWebElementDescriptor servlet) { Class 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); @@ -136,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()); } From 155d98373ea5f083d472784682e6ea51c6c1775e Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 16 Apr 2020 13:57:56 +0200 Subject: [PATCH 4/4] update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4209598c8d..b7be319e65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased +### Added +- Making WebElements (Servlet or Filter) optional by using the `@Requires` annotation ([#1101](https://github.com/scm-manager/scm-manager/pull/1101)) ### Changed - Removed the `requires` attribute on the `@Extension` annotation and instead create a new `@Requires` annotation ([#1097](https://github.com/scm-manager/scm-manager/pull/1097))