Rename attributes and classes to have a more regular pattern.
The DecoratingListener is now extened by the
CdiDecoratingListener which is used by the cdi-decorate module

Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
Greg Wilkins 2019-08-08 15:21:06 +10:00
parent 70fcd3d145
commit 9d497084d4
4 changed files with 231 additions and 0 deletions

View File

@ -0,0 +1,11 @@
<?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">
<Call name="setAttribute">
<Arg type="String">org.eclipse.jetty.cdi</Arg>
<Arg><Property name="jetty.cdi.mode" default="CdiSpiDecorator"/></Arg>
</Call>
</Configure>

View File

@ -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

View File

@ -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.webapp.DecoratingListener;
class CdiDecoratingListener extends DecoratingListener
{
public static final String MODE = "CdiDecoratingListener";
public static final String ATTRIBUTE = "org.eclipse.jetty.cdi.decorator";
public CdiDecoratingListener()
{
super(ATTRIBUTE);
}
@Override
protected void checkAndSetAttributeName()
{}
}

View File

@ -0,0 +1,166 @@
//
// ========================================================================
// 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 java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.HashMap;
import java.util.Map;
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 Decorator invokes a CDI provider within
* a webapplication 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:
* <pre>
* public &lt;T&gt; T decorate(T o)
* {
* BeanManager manager = CDI.current().getBeanManager();
* manager.createInjectionTarget(manager.createAnnotatedType((Class&lt;T&gt;)o.getClass()))
* .inject(o,manager.createCreationalContext(null));
* return o;
* }
* </pre>
*/
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<>();
private final MethodHandle _current;
private final MethodHandle _getBeanManager;
private final MethodHandle _createAnnotatedType;
private final MethodHandle _createInjectionTarget;
private final MethodHandle _createCreationalContext;
private final MethodHandle _inject;
private final MethodHandle _dispose;
private final MethodHandle _release;
public CdiSpiDecorator(ServletContextHandler context) throws UnsupportedOperationException
{
_context = context;
ClassLoader classLoader = _context.getClassLoader();
try
{
Class<?> cdiClass = classLoader.loadClass("javax.enterprise.inject.spi.CDI");
Class<?> beanManagerClass = classLoader.loadClass("javax.enterprise.inject.spi.BeanManager");
Class<?> annotatedTypeClass = classLoader.loadClass("javax.enterprise.inject.spi.AnnotatedType");
Class<?> injectionTargetClass = classLoader.loadClass("javax.enterprise.inject.spi.InjectionTarget");
Class<?> creationalContextClass = classLoader.loadClass("javax.enterprise.context.spi.CreationalContext");
Class<?> contextualClass = classLoader.loadClass("javax.enterprise.context.spi.Contextual");
MethodHandles.Lookup lookup = MethodHandles.lookup();
_current = lookup.findStatic(cdiClass, "current", MethodType.methodType(cdiClass));
_getBeanManager = lookup.findVirtual(cdiClass, "getBeanManager", MethodType.methodType(beanManagerClass));
_createAnnotatedType = lookup.findVirtual(beanManagerClass, "createAnnotatedType", MethodType.methodType(annotatedTypeClass, Class.class));
_createInjectionTarget = lookup.findVirtual(beanManagerClass, "createInjectionTarget", MethodType.methodType(injectionTargetClass, annotatedTypeClass));
_createCreationalContext = lookup.findVirtual(beanManagerClass, "createCreationalContext", MethodType.methodType(creationalContextClass, contextualClass));
_inject = lookup.findVirtual(injectionTargetClass, "inject", MethodType.methodType(Void.TYPE, Object.class, creationalContextClass));
_dispose = lookup.findVirtual(injectionTargetClass, "dispose", MethodType.methodType(Void.TYPE, Object.class));
_release = lookup.findVirtual(creationalContextClass, "release", MethodType.methodType(Void.TYPE));
}
catch (Exception e)
{
throw new UnsupportedOperationException(e);
}
}
/**
* Decorate an object.
* <p>The signature of this method must match what is introspected for by the
* Jetty DecoratingListener class. It is invoked dynamically.</p>
*
* @param o The object to be decorated
* @param <T> The type of the object to be decorated
* @return The decorated object
*/
public <T> T decorate(T o)
{
try
{
if (LOG.isDebugEnabled())
LOG.debug("decorate {} in {}", o, _context);
_decorated.put(o, new Decorated(o));
}
catch (Throwable th)
{
LOG.warn("Unable to decorate " + o, th);
}
return o;
}
/**
* Destroy a decorated object.
* <p>The signature of this method must match what is introspected for by the
* Jetty DecoratingListener class. It is invoked dynamically.</p>
*
* @param o The object to be destroyed
*/
public void destroy(Object o)
{
try
{
Decorated decorated = _decorated.remove(o);
if (decorated != null)
decorated.destroy(o);
}
catch (Throwable th)
{
LOG.warn("Unable to destroy " + o, th);
}
}
private class Decorated
{
private final Object _injectionTarget;
private final Object _creationalContext;
Decorated(Object o) throws Throwable
{
// BeanManager manager = CDI.current().getBeanManager();
Object manager = _getBeanManager.invoke(_current.invoke());
// AnnotatedType annotatedType = manager.createAnnotatedType((Class<T>)o.getClass());
Object annotatedType = _createAnnotatedType.invoke(manager, o.getClass());
// CreationalContext creationalContext = manager.createCreationalContext(null);
_creationalContext = _createCreationalContext.invoke(manager, null);
// InjectionTarget injectionTarget = manager.createInjectionTarget();
_injectionTarget = _createInjectionTarget.invoke(manager, annotatedType);
// injectionTarget.inject(o, creationalContext);
_inject.invoke(_injectionTarget, o, _creationalContext);
}
public void destroy(Object o) throws Throwable
{
_dispose.invoke(_injectionTarget, o);
_release.invoke(_creationalContext);
}
}
}