added module to register servlets and filters by new WebElement annotation

This commit is contained in:
Sebastian Sdorra
2015-02-01 19:14:46 +01:00
parent 7877db00c9
commit 79e1e5e972
12 changed files with 785 additions and 2 deletions

View File

@@ -66,6 +66,7 @@ import java.util.Set;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import sonia.scm.filter.WebElementModule;
/**
*
@@ -255,6 +256,7 @@ public class ScmContextListener extends GuiceServletContextListener
moduleList.add(new ScmEventBusModule());
moduleList.add(new EagerSingletonModule());
moduleList.add(ShiroWebModule.guiceFilterModule());
moduleList.add(new WebElementModule(pluginLoader));
moduleList.add(new ScmServletModule(servletCtx, pluginLoader, overrides));
moduleList.add(
new ScmSecurityModule(servletCtx, pluginLoader.getExtensionProcessor())

View File

@@ -0,0 +1,60 @@
/**
* Copyright (c) 2014, 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.filter;
import sonia.scm.plugin.WebElementDescriptor;
/**
*
* @author Sebastian Sdorra
* @param <T>
*/
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;
}
}

View File

@@ -0,0 +1,191 @@
/**
* Copyright (c) 2014, 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.filter;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.google.common.primitives.Ints;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.Priorities;
import sonia.scm.plugin.PluginLoader;
import sonia.scm.plugin.WebElementDescriptor;
//~--- JDK imports ------------------------------------------------------------
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.Servlet;
import javax.servlet.http.HttpServlet;
/**
*
* @author Sebastian Sdorra
*/
public final class WebElementCollector
{
/**
* the logger for WebElementCollector
*/
private static final Logger logger =
LoggerFactory.getLogger(WebElementCollector.class);
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param elements
*/
@SuppressWarnings("unchecked")
private WebElementCollector(Iterable<WebElementDescriptor> elements)
{
List<TypedWebElementDescriptor<? extends Filter>> fl = Lists.newArrayList();
List<TypedWebElementDescriptor<? extends HttpServlet>> sl =
Lists.newArrayList();
for (WebElementDescriptor element : elements)
{
if (Filter.class.isAssignableFrom(element.getClazz()))
{
fl.add(
new TypedWebElementDescriptor<>(
(Class<? extends Filter>) element.getClazz(), element));
}
else if (Servlet.class.isAssignableFrom(element.getClazz()))
{
sl.add(
new TypedWebElementDescriptor<>(
(Class<? extends HttpServlet>) element.getClazz(), element));
}
else
{
logger.warn(
"found class {} witch is annotated with webelement annotation, but is neither an filter or servlet",
element.getClazz());
}
}
TypedWebElementDescriptorOrdering ordering =
new TypedWebElementDescriptorOrdering();
filters = ordering.immutableSortedCopy(fl);
servlets = ordering.immutableSortedCopy(sl);
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param loader
*
* @return
*/
public static WebElementCollector collect(PluginLoader loader)
{
return new WebElementCollector(
loader.getExtensionProcessor().getWebElements());
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
public Iterable<TypedWebElementDescriptor<? extends Filter>> getFilters()
{
return filters;
}
/**
* Method description
*
*
* @return
*/
public Iterable<TypedWebElementDescriptor<? extends HttpServlet>> getServlets()
{
return servlets;
}
//~--- inner classes --------------------------------------------------------
/**
* Class description
*
*
* @version Enter version here..., 15/02/01
* @author Enter your name here...
*/
private static class TypedWebElementDescriptorOrdering
extends Ordering<TypedWebElementDescriptor<?>>
{
/**
* Method description
*
*
* @param left
* @param right
*
* @return
*/
@Override
public int compare(TypedWebElementDescriptor<?> left,
TypedWebElementDescriptor<?> right)
{
return Ints.compare(Priorities.getPriority(left.getClazz()),
Priorities.getPriority(right.getClazz()));
}
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private final Iterable<TypedWebElementDescriptor<? extends Filter>> filters;
/** Field description */
private final Iterable<TypedWebElementDescriptor<? extends HttpServlet>> servlets;
}

View File

@@ -0,0 +1,164 @@
/**
* Copyright (c) 2014, 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.filter;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Scopes;
import com.google.inject.servlet.ServletModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.plugin.PluginLoader;
import sonia.scm.plugin.WebElementDescriptor;
//~--- JDK imports ------------------------------------------------------------
import javax.servlet.Filter;
import javax.servlet.http.HttpServlet;
/**
*
* @author Sebastian Sdorra
*/
public class WebElementModule extends ServletModule
{
/**
* the logger for WebElementModule
*/
private static final Logger logger =
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())
{
bindFilter(f);
}
for (TypedWebElementDescriptor<? extends HttpServlet> s :
collector.getServlets())
{
bindServlet(s);
}
}
/**
* Method description
*
*
* @param filter
*/
private void bindFilter(TypedWebElementDescriptor<? extends Filter> filter)
{
Class<? extends Filter> clazz = filter.getClazz();
logger.info("bind filter {} to filter chain", clazz);
// filters must be in singleton scope
bind(clazz).in(Scopes.SINGLETON);
WebElementDescriptor opts = filter.getDescriptor();
FilterKeyBindingBuilder builder;
if (opts.isRegex())
{
builder = filterRegex(opts.getPattern(), opts.getMorePatterns());
}
else
{
builder = filter(opts.getPattern(), opts.getMorePatterns());
}
// TODO handle init parameters
builder.through(clazz);
}
/**
* Method description
*
*
* @param servlet
*/
private void bindServlet(
TypedWebElementDescriptor<? extends HttpServlet> servlet)
{
Class<? extends HttpServlet> clazz = servlet.getClazz();
logger.info("bind servlet {} to servlet chain", clazz);
// filters must be in singleton scope
bind(clazz).in(Scopes.SINGLETON);
WebElementDescriptor opts = servlet.getDescriptor();
ServletKeyBindingBuilder builder;
if (opts.isRegex())
{
builder = serveRegex(opts.getPattern(), opts.getMorePatterns());
}
else
{
builder = serve(opts.getPattern(), opts.getMorePatterns());
}
// TODO handle init parameters
builder.with(clazz);
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private final WebElementCollector collector;
}

View File

@@ -113,6 +113,20 @@ public class DefaultExtensionProcessor implements ExtensionProcessor
logger.info("bound extensions in {}", sw.stop());
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@Override
public Iterable<WebElementDescriptor> getWebElements()
{
return collector.getWebElements();
}
//~--- fields ---------------------------------------------------------------
/** Field description */

View File

@@ -205,6 +205,17 @@ public final class ExtensionCollector
return restResources;
}
/**
* Method description
*
*
* @return
*/
public Set<WebElementDescriptor> getWebElements()
{
return webElements;
}
//~--- methods --------------------------------------------------------------
/**
@@ -263,18 +274,22 @@ public final class ExtensionCollector
restProviders.addAll(Lists.newArrayList(module.getRestProviders()));
restResources.addAll(Lists.newArrayList(module.getRestResources()));
Iterables.addAll(webElements, module.getWebElements());
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private final Set<Class> looseExtensions = Sets.newHashSet();
private final Set<WebElementDescriptor> webElements = Sets.newHashSet();
/** Field description */
private final Set<Class> restResources = Sets.newHashSet();
/** Field description */
private final Set<Class> restProviders = Sets.newHashSet();
/** Field description */
private final Set<Class> restResources = Sets.newHashSet();
private final Set<Class> looseExtensions = Sets.newHashSet();
/** Field description */
private final Multimap<ExtensionPointElement, Class> extensions =