Merge pull request #3946 from eclipse/jetty-9.4.x-3804-Decoration-rename
Issue #3804 CDI integration rename
This commit is contained in:
commit
e7a1978556
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<Call name="setAttribute">
|
||||
<Arg type="String">org.eclipse.jetty.cdi</Arg>
|
||||
<Arg><Property name="jetty.cdi.mode" default="CdiSpiDecorator"/></Arg>
|
||||
</Call>
|
||||
</Configure>
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<!-- =============================================================== --><!-- Mixin the Weld / CDI classes to the class loader --><!-- =============================================================== -->
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<Get class="org.eclipse.jetty.util.log.Log" name="rootLogger">
|
||||
<Call name="warn"><Arg>cdi2 module is deprecated!</Arg></Call>
|
||||
</Get>
|
||||
<Ref refid="DeploymentManager">
|
||||
<Call name="addLifeCycleBinding">
|
||||
<Arg>
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
|
||||
|
||||
[description]
|
||||
Configures Jetty to use the "CdiDecoratingListener" as the default
|
||||
CDI integration mode that allows a webapp to register it's own CDI
|
||||
decorator.
|
||||
|
||||
[tag]
|
||||
cdi
|
||||
|
||||
[provides]
|
||||
cdi-mode
|
||||
|
||||
[depend]
|
||||
cdi
|
||||
|
||||
[ini]
|
||||
jetty.cdi.mode=CdiDecoratingListener
|
|
@ -1,24 +1,17 @@
|
|||
# DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
|
||||
|
||||
[description]
|
||||
CDI SPI integration for CDI inside the webapp.
|
||||
This module does not provide CDI, but configures jetty to look for the CDI SPI within
|
||||
a webapp. If the CDI SPI is found, then a CdiDecorator will be registered to
|
||||
decorate Listeners, Filters and Servlets using the standard CDI SPI.
|
||||
The module indicates to the webapp that this mechanism is available by setting the
|
||||
"org.eclipse.jetty.cdi" context attribute to "CdiDecorator".
|
||||
This is the preferred integration for OWB.
|
||||
Configures Jetty to use the "CdiSpiDecorator" that calls the CDI SPI
|
||||
as the default CDI integration mode.
|
||||
|
||||
[tag]
|
||||
cdi
|
||||
|
||||
[depend]
|
||||
deploy
|
||||
[provides]
|
||||
cdi-mode
|
||||
|
||||
[lib]
|
||||
lib/jetty-cdi-${jetty.version}.jar
|
||||
lib/apache-jsp/org.mortbay.jasper.apache-el-*.jar
|
||||
[depend]
|
||||
cdi
|
||||
|
||||
[ini]
|
||||
jetty.webapp.addSystemClasses+=,org.eclipse.jetty.cdi.CdiServletContainerInitializer
|
||||
jetty.webapp.addServerClasses+=,-org.eclipse.jetty.cdi.CdiServletContainerInitializer
|
||||
jetty.cdi.mode=CdiSpiDecorator
|
||||
|
|
|
@ -1,10 +1,34 @@
|
|||
# DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
|
||||
|
||||
[description]
|
||||
Deprecated CDI module. Current depends on cdi-spi.
|
||||
Support for CDI inside the webapp.
|
||||
This module does not provide CDI, but configures jetty to support various
|
||||
integration modes with a CDI implementation on the webapp classpath.
|
||||
CDI integration modes can be selected per webapp with the "org.eclipse.jetty.cdi"
|
||||
init parameter or defaults to the mode set by the "org.eclipse.jetty.cdi" server
|
||||
attribute (which is initialised from the "jetty.cdi.mode" start property).
|
||||
Supported modes are:
|
||||
CdiSpiDecorator - Jetty will call the CDI SPI within the webapp to decorate
|
||||
objects (default).
|
||||
CdiDecoratingLister - The webapp may register a decorator on the context attribute
|
||||
"org.eclipse.jetty.cdi.decorator".
|
||||
|
||||
[tag]
|
||||
cdi
|
||||
|
||||
[provides]
|
||||
cdi
|
||||
|
||||
[depend]
|
||||
cdi-spi
|
||||
deploy
|
||||
|
||||
[xml]
|
||||
etc/cdi/jetty-cdi.xml
|
||||
|
||||
[lib]
|
||||
lib/jetty-cdi-${jetty.version}.jar
|
||||
lib/apache-jsp/org.mortbay.jasper.apache-el-*.jar
|
||||
|
||||
[ini]
|
||||
jetty.webapp.addSystemClasses+=,org.eclipse.jetty.cdi.CdiServletContainerInitializer
|
||||
jetty.webapp.addServerClasses+=,-org.eclipse.jetty.cdi.CdiServletContainerInitializer
|
|
@ -10,6 +10,9 @@ implementation in the webapp.
|
|||
[tag]
|
||||
cdi
|
||||
|
||||
[provides]
|
||||
cdi-mode
|
||||
|
||||
[depend]
|
||||
deploy
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.cdi;
|
||||
|
||||
import org.eclipse.jetty.servlet.DecoratingListener;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
|
||||
/**
|
||||
* A DecoratingListener that listens for "org.eclipse.jetty.cdi.decorator"
|
||||
*/
|
||||
class CdiDecoratingListener extends DecoratingListener
|
||||
{
|
||||
public static final String MODE = "CdiDecoratingListener";
|
||||
public static final String ATTRIBUTE = "org.eclipse.jetty.cdi.decorator";
|
||||
|
||||
public CdiDecoratingListener(ServletContextHandler contextHandler)
|
||||
{
|
||||
super(contextHandler, ATTRIBUTE);
|
||||
}
|
||||
}
|
|
@ -25,14 +25,24 @@ import javax.servlet.ServletContext;
|
|||
|
||||
import org.eclipse.jetty.annotations.AnnotationConfiguration;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/**
|
||||
* A {@link ServletContainerInitializer} that introspects for a CDI API
|
||||
* implementation within a web application. If the CDI API is found, then
|
||||
* a {@link CdiDecorator} is registered as a {@link org.eclipse.jetty.util.Decorator}
|
||||
* for the context.
|
||||
* <p>A {@link ServletContainerInitializer} that introspects for a CDI API
|
||||
* implementation within a web application and applies an integration
|
||||
* mode if CDI is found. CDI integration modes can be selected per webapp with
|
||||
* the "org.eclipse.jetty.cdi" init parameter or default to the mode set by the
|
||||
* "org.eclipse.jetty.cdi" server attribute. Supported modes are:</p>
|
||||
* <dl>
|
||||
* <dt>CdiSpiDecorator</dt>
|
||||
* <dd>Jetty will call the CDI SPI within the webapp to decorate objects (default).</dd>
|
||||
* <dt>CdiDecoratingLister</dt>
|
||||
* <dd>The webapp may register a decorator on the context attribute
|
||||
* "org.eclipse.jetty.cdi.decorator".</dd>
|
||||
* </dl>
|
||||
*
|
||||
* @see AnnotationConfiguration.ServletContainerInitializerOrdering
|
||||
*/
|
||||
public class CdiServletContainerInitializer implements ServletContainerInitializer
|
||||
|
@ -47,11 +57,40 @@ public class CdiServletContainerInitializer implements ServletContainerInitializ
|
|||
{
|
||||
ServletContextHandler context = ServletContextHandler.getServletContextHandler(ctx);
|
||||
Objects.requireNonNull(context);
|
||||
context.getObjectFactory().addDecorator(new CdiDecorator(context));
|
||||
context.setAttribute(CDI_INTEGRATION_ATTRIBUTE, "CdiDecorator");
|
||||
LOG.info("CdiDecorator enabled in " + ctx);
|
||||
|
||||
// Test if CDI is in the webapp by trying to load the CDI class.
|
||||
ClassLoader loader = context.getClassLoader();
|
||||
if (loader == null)
|
||||
Loader.loadClass("javax.enterprise.inject.spi.CDI");
|
||||
else
|
||||
loader.loadClass("javax.enterprise.inject.spi.CDI");
|
||||
|
||||
String mode = ctx.getInitParameter(CDI_INTEGRATION_ATTRIBUTE);
|
||||
if (mode == null)
|
||||
{
|
||||
mode = (String)context.getServer().getAttribute(CDI_INTEGRATION_ATTRIBUTE);
|
||||
if (mode == null)
|
||||
mode = CdiSpiDecorator.MODE;
|
||||
}
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case CdiSpiDecorator.MODE:
|
||||
context.getObjectFactory().addDecorator(new CdiSpiDecorator(context));
|
||||
break;
|
||||
|
||||
case CdiDecoratingListener.MODE:
|
||||
context.addEventListener(new CdiDecoratingListener(context));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalStateException(mode);
|
||||
}
|
||||
|
||||
context.setAttribute(CDI_INTEGRATION_ATTRIBUTE, mode);
|
||||
LOG.info(mode + " enabled in " + ctx);
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
catch (UnsupportedOperationException | ClassNotFoundException e)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("CDI not found in " + ctx, e);
|
||||
|
|
|
@ -30,11 +30,11 @@ import org.eclipse.jetty.util.log.Log;
|
|||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/**
|
||||
* A Decorator invokes a CDI provider within
|
||||
* a webapplication to decorate objects created by the contexts {@link org.eclipse.jetty.util.DecoratedObjectFactory}
|
||||
* A Decorator that invokes the CDI provider within a webapp to decorate objects created by
|
||||
* the contexts {@link org.eclipse.jetty.util.DecoratedObjectFactory}
|
||||
* (typically Listeners, Filters and Servlets).
|
||||
* The CDI provide is invoked using {@link MethodHandle}s to avoid any CDI instance or dependencies within the server scope.
|
||||
* The code invoked is equivalent to:
|
||||
* The CDI provider is invoked using {@link MethodHandle}s to avoid any CDI instance
|
||||
* or dependencies within the server scope. The code invoked is equivalent to:
|
||||
* <pre>
|
||||
* public <T> T decorate(T o)
|
||||
* {
|
||||
|
@ -45,9 +45,10 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public class CdiDecorator implements Decorator
|
||||
public class CdiSpiDecorator implements Decorator
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(CdiServletContainerInitializer.class);
|
||||
public static final String MODE = "CdiSpiDecorator";
|
||||
|
||||
private final ServletContextHandler _context;
|
||||
private final Map<Object, Decorated> _decorated = new HashMap<>();
|
||||
|
@ -61,7 +62,7 @@ public class CdiDecorator implements Decorator
|
|||
private final MethodHandle _dispose;
|
||||
private final MethodHandle _release;
|
||||
|
||||
public CdiDecorator(ServletContextHandler context) throws UnsupportedOperationException
|
||||
public CdiSpiDecorator(ServletContextHandler context) throws UnsupportedOperationException
|
||||
{
|
||||
_context = context;
|
||||
ClassLoader classLoader = _context.getClassLoader();
|
|
@ -1,16 +1,11 @@
|
|||
# DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
|
||||
|
||||
[description]
|
||||
Jetty setup to support Decoration of Listeners, Filters and Servlets within a deployed
|
||||
webapp (as used by some CDI integrations).
|
||||
Jetty setup to support Decoration of Listeners, Filters and Servlets within a deployed webapp.
|
||||
This module uses the DecoratingListener to register an object set as a context attribute
|
||||
as a dynamic decorator. This module sets the "org.eclipse.jetty.webapp.DecoratingListener"
|
||||
context attribute with the name of the context attribute that will be listened to.
|
||||
By default the attribute is "org.eclipse.jetty.webapp.decorator".
|
||||
This is the preferred integration for Weld >= 3.1.2
|
||||
|
||||
[tag]
|
||||
cdi
|
||||
|
||||
[depend]
|
||||
deploy
|
||||
|
|
|
@ -140,16 +140,6 @@
|
|||
<outputDirectory>${assembly-directory}/demo-base/webapps</outputDirectory>
|
||||
<destFileName>async-rest.war</destFileName>
|
||||
</artifactItem>
|
||||
<artifactItem>
|
||||
<groupId>org.eclipse.jetty.tests</groupId>
|
||||
<artifactId>test-weld-cdi-webapp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>war</type>
|
||||
<overWrite>true</overWrite>
|
||||
<includes>**</includes>
|
||||
<outputDirectory>${assembly-directory}/demo-base/webapps</outputDirectory>
|
||||
<destFileName>test-weld-cdi.war</destFileName>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
@ -358,7 +348,7 @@
|
|||
<arguments>
|
||||
<argument>jetty.home=${assembly-directory}</argument>
|
||||
<argument>jetty.base=${assembly-directory}/demo-base</argument>
|
||||
<argument>--add-to-startd=server,continuation,deploy,websocket,ext,resources,client,annotations,cdi2,decorate,jndi,servlets,jsp,jstl,http,https,threadpool</argument>
|
||||
<argument>--add-to-startd=server,continuation,deploy,websocket,ext,resources,client,annotations,jndi,servlets,jsp,jstl,http,https,threadpool</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
<goals>
|
||||
|
@ -459,13 +449,6 @@
|
|||
<type>war</type>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.tests</groupId>
|
||||
<artifactId>test-weld-cdi-webapp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>war</type>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-documentation</artifactId>
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
<li><a href="/test-spec/">Servlet 3.1 Test</a></li>
|
||||
<li><a href="/test-jaas/">JAAS Test</a></li>
|
||||
<li><a href="/test-jndi/">JNDI Test</a></li>
|
||||
<li><a href="/test-weld-cdi/">Weld CDI Test</a></li>
|
||||
<li><a href="/async-rest/">Async Rest</a></li>
|
||||
<li><a href="/oldContextPath/">Redirected Context</a></li>
|
||||
</ul>
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.servlet;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.Objects;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextAttributeEvent;
|
||||
import javax.servlet.ServletContextAttributeListener;
|
||||
|
||||
import org.eclipse.jetty.util.Decorator;
|
||||
|
||||
/**
|
||||
* A ServletContextAttributeListener that listens for a context
|
||||
* attribute to obtain a decorator instance. The instance is then either
|
||||
* coerced to a {@link Decorator} or reflected for decorator compatible methods
|
||||
* so it can be added to the {@link ServletContextHandler#getObjectFactory()} as a
|
||||
* {@link Decorator}.
|
||||
*/
|
||||
public class DecoratingListener implements ServletContextAttributeListener
|
||||
{
|
||||
private static final MethodType DECORATE_TYPE;
|
||||
private static final MethodType DESTROY_TYPE;
|
||||
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
DECORATE_TYPE = MethodType.methodType(Object.class, Object.class);
|
||||
DESTROY_TYPE = MethodType.methodType(void.class, Object.class);
|
||||
|
||||
// Check we have the right MethodTypes for the current Decorator signatures
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
lookup.findVirtual(Decorator.class, "decorate", DECORATE_TYPE);
|
||||
lookup.findVirtual(Decorator.class, "destroy", DESTROY_TYPE);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final ServletContextHandler _context;
|
||||
private final String _attributeName;
|
||||
private Decorator _decorator;
|
||||
|
||||
public DecoratingListener(ServletContextHandler context, String attributeName)
|
||||
{
|
||||
Objects.requireNonNull(context);
|
||||
Objects.requireNonNull(attributeName);
|
||||
_context = context;
|
||||
_attributeName = attributeName;
|
||||
Object decorator = _context.getAttribute(_attributeName);
|
||||
if (decorator != null)
|
||||
_context.getObjectFactory().addDecorator(asDecorator(decorator));
|
||||
}
|
||||
|
||||
public String getAttributeName()
|
||||
{
|
||||
return _attributeName;
|
||||
}
|
||||
|
||||
public ServletContext getServletContext()
|
||||
{
|
||||
return _context.getServletContext();
|
||||
}
|
||||
|
||||
private Decorator asDecorator(Object object)
|
||||
{
|
||||
if (object == null)
|
||||
return null;
|
||||
if (object instanceof Decorator)
|
||||
return (Decorator)object;
|
||||
|
||||
try
|
||||
{
|
||||
Class<?> clazz = object.getClass();
|
||||
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
MethodHandle decorate = lookup.findVirtual(clazz, "decorate", DECORATE_TYPE);
|
||||
MethodHandle destroy = lookup.findVirtual(clazz, "destroy", DESTROY_TYPE);
|
||||
return new DynamicDecorator(object, decorate, destroy);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeAdded(ServletContextAttributeEvent event)
|
||||
{
|
||||
if (_attributeName.equals(event.getName()))
|
||||
{
|
||||
_decorator = asDecorator(event.getValue());
|
||||
_context.getObjectFactory().addDecorator(_decorator);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeRemoved(ServletContextAttributeEvent event)
|
||||
{
|
||||
if (_attributeName.equals(event.getName()) && _decorator != null)
|
||||
{
|
||||
_context.getObjectFactory().removeDecorator(_decorator);
|
||||
_decorator = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeReplaced(ServletContextAttributeEvent event)
|
||||
{
|
||||
attributeRemoved(event);
|
||||
attributeAdded(event);
|
||||
}
|
||||
|
||||
private static class DynamicDecorator implements Decorator
|
||||
{
|
||||
private final Object _object;
|
||||
private final MethodHandle _decorate;
|
||||
private final MethodHandle _destroy;
|
||||
|
||||
private DynamicDecorator(Object object, MethodHandle decorate, MethodHandle destroy)
|
||||
{
|
||||
_object = object;
|
||||
_decorate = decorate;
|
||||
_destroy = destroy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T decorate(T o)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (T)_decorate.invoke(_object, o);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy(Object o)
|
||||
{
|
||||
try
|
||||
{
|
||||
_destroy.invoke(_object, o);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,60 +18,20 @@
|
|||
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.Objects;
|
||||
import javax.servlet.ServletContextAttributeEvent;
|
||||
import javax.servlet.ServletContextAttributeListener;
|
||||
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.util.Decorator;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/**
|
||||
* A ServletContextAttributeListener that listens for a specific context
|
||||
* attribute (default "org.eclipse.jetty.webapp.decorator") to obtain a
|
||||
* decorator instance from the webapp. The instance is then either coerced
|
||||
* to a Decorator or reflected for decorator compatible methods so it can
|
||||
* be added to the {@link WebAppContext#getObjectFactory()} as a
|
||||
* {@link Decorator}.
|
||||
* An extended org.eclipse.jetty.servlet.DecoratingListener.
|
||||
* The context attribute "org.eclipse.jetty.webapp.DecoratingListener" if
|
||||
* not set, is set to the name of the attribute this listener listens for.
|
||||
*/
|
||||
public class DecoratingListener implements ServletContextAttributeListener
|
||||
public class DecoratingListener extends org.eclipse.jetty.servlet.DecoratingListener
|
||||
{
|
||||
public static final String DECORATOR_ATTRIBUTE = "org.eclipse.jetty.webapp.decorator";
|
||||
private static final Logger LOG = Log.getLogger(DecoratingListener.class);
|
||||
private static final MethodType DECORATE_TYPE;
|
||||
private static final MethodType DESTROY_TYPE;
|
||||
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
DECORATE_TYPE = MethodType.methodType(Object.class, Object.class);
|
||||
DESTROY_TYPE = MethodType.methodType(Void.TYPE, Object.class);
|
||||
|
||||
// Check we have the right MethodTypes for the current Decorator signatures
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
lookup.findVirtual(Decorator.class, "decorate", DECORATE_TYPE);
|
||||
lookup.findVirtual(Decorator.class, "destroy", DESTROY_TYPE);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final ServletContextHandler _context;
|
||||
private final String _attributeName;
|
||||
private Decorator _decorator;
|
||||
|
||||
public DecoratingListener()
|
||||
{
|
||||
this((String)null);
|
||||
this(DECORATOR_ATTRIBUTE);
|
||||
}
|
||||
|
||||
public DecoratingListener(String attributeName)
|
||||
|
@ -81,116 +41,22 @@ public class DecoratingListener implements ServletContextAttributeListener
|
|||
|
||||
public DecoratingListener(ServletContextHandler context)
|
||||
{
|
||||
this(context, null);
|
||||
this(context, DECORATOR_ATTRIBUTE);
|
||||
}
|
||||
|
||||
public DecoratingListener(ServletContextHandler context, String attributeName)
|
||||
{
|
||||
_context = context;
|
||||
Objects.requireNonNull(_context);
|
||||
_attributeName = attributeName == null ? DECORATOR_ATTRIBUTE : attributeName;
|
||||
checkAndSetAttribute();
|
||||
Object decorator = _context.getAttribute(_attributeName);
|
||||
if (decorator != null)
|
||||
_context.getObjectFactory().addDecorator(asDecorator(decorator));
|
||||
super(context, attributeName);
|
||||
checkAndSetAttributeName();
|
||||
}
|
||||
|
||||
protected void checkAndSetAttribute()
|
||||
protected void checkAndSetAttributeName()
|
||||
{
|
||||
// If not set (by another DecoratingListener), flag the attribute that are
|
||||
// listening for. If more than one DecoratingListener is used then this
|
||||
// attribute reflects only the first.
|
||||
if (_context.getAttribute(getClass().getName()) != null)
|
||||
if (getServletContext().getAttribute(getClass().getName()) != null)
|
||||
throw new IllegalStateException("Multiple DecoratingListeners detected");
|
||||
_context.setAttribute(getClass().getName(), _attributeName);
|
||||
}
|
||||
|
||||
private Decorator asDecorator(Object object)
|
||||
{
|
||||
if (object == null)
|
||||
return null;
|
||||
if (object instanceof Decorator)
|
||||
return (Decorator)object;
|
||||
|
||||
try
|
||||
{
|
||||
Class<?> clazz = object.getClass();
|
||||
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
MethodHandle decorate = lookup.findVirtual(clazz, "decorate", DECORATE_TYPE);
|
||||
MethodHandle destroy = lookup.findVirtual(clazz, "destroy", DESTROY_TYPE);
|
||||
return new DynamicDecorator(decorate, destroy, object);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeAdded(ServletContextAttributeEvent event)
|
||||
{
|
||||
if (_attributeName.equals(event.getName()))
|
||||
{
|
||||
_decorator = asDecorator(event.getValue());
|
||||
_context.getObjectFactory().addDecorator(_decorator);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeRemoved(ServletContextAttributeEvent event)
|
||||
{
|
||||
if (_attributeName.equals(event.getName()) && _decorator != null)
|
||||
{
|
||||
_context.getObjectFactory().removeDecorator(_decorator);
|
||||
_decorator = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeReplaced(ServletContextAttributeEvent event)
|
||||
{
|
||||
attributeRemoved(event);
|
||||
attributeAdded(event);
|
||||
}
|
||||
|
||||
private static class DynamicDecorator implements Decorator
|
||||
{
|
||||
private final MethodHandle _decorate;
|
||||
private final MethodHandle _destroy;
|
||||
private final Object _object;
|
||||
|
||||
private DynamicDecorator(MethodHandle decorate, MethodHandle destroy, Object object)
|
||||
{
|
||||
_decorate = decorate;
|
||||
_destroy = destroy;
|
||||
_object = object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T decorate(T o)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (T)_decorate.invoke(_object, o);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy(Object o)
|
||||
{
|
||||
try
|
||||
{
|
||||
_destroy.invoke(_object, o);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
getServletContext().setAttribute(getClass().getName(), getAttributeName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,6 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
@ -57,15 +55,19 @@ public class CDITests extends AbstractDistributionTest
|
|||
}
|
||||
};
|
||||
|
||||
List<Object[]> tests = new ArrayList<>();
|
||||
return Stream.of(
|
||||
// -- Weld --
|
||||
Arguments.of("weld", "cdi2", null),
|
||||
Arguments.of("weld", "cdi-spi", null), // Weld >= 3.1.2
|
||||
Arguments.of("weld", "decorate", null), // Weld >= 3.1.2
|
||||
// TODO Arguments.of("weld", "cdi-decorate", null), // Weld >= 3.1.3
|
||||
|
||||
tests.add(new Object[]{"weld", "cdi-spi", null}); // Requires Weld >= 3.1.2
|
||||
tests.add(new Object[]{"weld", "cdi2", null});
|
||||
tests.add(new Object[]{"weld", "decorate", null}); // Requires Weld >= 3.1.2
|
||||
tests.add(new Object[]{"owb", "cdi-spi", removeJettyWebXml});
|
||||
tests.add(new Object[]{"owb", "cdi2", null});
|
||||
// tests.add(new Object[]{"owb", "decorate", null}); // Will not be supported
|
||||
return tests.stream().map(Arguments::of);
|
||||
// -- Apache OpenWebBeans --
|
||||
Arguments.of("owb", "cdi-spi", removeJettyWebXml),
|
||||
Arguments.of("owb", "cdi2", null)
|
||||
// Arguments.of("owb", "decorate", null), // Not supported
|
||||
// Arguments.of("owb", "cdi-decorate", null) // Not supported
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue