TOMEE-2972 move event to parent Delegation

Introduce new WebappNotificationManager to handle ParentBm delegation
for all events. This did not work for all cases when OWB did
directly use NotificationManger internally.
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/cdi/WebappBeanManager.java b/container/openejb-core/src/main/java/org/apache/openejb/cdi/WebappBeanManager.java
index 055afbc..ded4bee 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/cdi/WebappBeanManager.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/cdi/WebappBeanManager.java
@@ -66,17 +66,6 @@
     }
 
     @Override
-    public void fireEvent(final Object event, final EventMetadataImpl metadata, final boolean isLifecycleEvent) {
-        super.fireEvent(event, metadata, isLifecycleEvent);
-        if (isEvent(event)) {
-            final BeanManagerImpl parentBm = getParentBm();
-            if (parentBm != null) {
-                parentBm.fireEvent(event, metadata, isLifecycleEvent);
-            }
-        }
-    }
-
-    @Override
     public List<Interceptor<?>> resolveInterceptors(InterceptionType type, Annotation... interceptorBindings) {
         final List<Interceptor<?>> interceptors = super.resolveInterceptors(type, interceptorBindings);
         final List<Interceptor<?>> parentInterceptors = getParentBm().resolveInterceptors(type, interceptorBindings);
@@ -89,20 +78,6 @@
     }
 
     @Override
-    public <T> Set<ObserverMethod<? super T>> resolveObserverMethods(final T event, final EventMetadataImpl metadata) {
-        final Set<ObserverMethod<? super T>> set = new HashSet<>(super.resolveObserverMethods(event, metadata));
-
-        if (isEvent(event)) {
-            final BeanManagerImpl parentBm = getParentBm();
-            if (parentBm != null) {
-                set.addAll(parentBm.resolveObserverMethods(event, metadata));
-            }
-        } // else nothing since extensions are loaded by classloader so we already have it
-
-        return set;
-    }
-
-    @Override
     public Object getInjectableReference(final InjectionPoint injectionPoint, final CreationalContext<?> ctx) {
         Asserts.assertNotNull(injectionPoint, "injectionPoint parameter");
         if(injectionPoint == null)  {
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/cdi/WebappNotificationManager.java b/container/openejb-core/src/main/java/org/apache/openejb/cdi/WebappNotificationManager.java
new file mode 100644
index 0000000..9c9f89c
--- /dev/null
+++ b/container/openejb-core/src/main/java/org/apache/openejb/cdi/WebappNotificationManager.java
@@ -0,0 +1,58 @@
+package org.apache.openejb.cdi;
+
+import org.apache.webbeans.event.EventMetadataImpl;
+import org.apache.webbeans.event.NotificationManager;
+
+import javax.enterprise.inject.spi.ObserverMethod;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * NotificationManager which handles delegation to the parent NotifcationManager
+ */
+public final class WebappNotificationManager extends NotificationManager {
+    private final NotificationManager parentNotificationManager;
+
+    /**
+     * We need to know when we did start.
+     * Lifecycle events will only get sent to the parent NotificationManager once the boot is finished.
+     * This is necessary to e.g. handle ProcessInjectionPoint for manual InjectionPointFactory calls.
+     */
+    private boolean hasStarted = false;
+
+    public WebappNotificationManager(WebappWebBeansContext webappWebBeansContext) {
+        super(webappWebBeansContext);
+        this.parentNotificationManager = webappWebBeansContext.getParent() != null
+                ? webappWebBeansContext.getParent().getNotificationManager()
+                : null;
+    }
+
+
+    @Override
+    public void afterStart() {
+        hasStarted = true;
+        super.afterStart();
+    }
+
+    /**
+     * Collect the observer methods of the parent BeanManager plus the own.
+     */
+    @Override
+    public <T> Collection<ObserverMethod<? super T>> resolveObservers(T event, EventMetadataImpl metadata, boolean isLifecycleEvent) {
+        if (isLifecycleEvent) {
+            // we do not send lifecycle events to the parent beanmanager
+            // because the same Extensions get loaded with different instances one per BeanManager anyway
+            return super.resolveObservers(event, metadata, isLifecycleEvent);
+        }
+
+        // for standard event and some lifecycle events at RUNTIME(!),
+        // we also have to invoke the parent NotificationManager
+        List<ObserverMethod<? super T>> observerMethods =
+                parentNotificationManager != null
+                        ? new ArrayList<>(parentNotificationManager.resolveObservers(event, metadata, isLifecycleEvent))
+                        : new ArrayList<>();
+        observerMethods.addAll(super.resolveObservers(event, metadata, isLifecycleEvent));
+        return observerMethods;
+    }
+}
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/cdi/WebappWebBeansContext.java b/container/openejb-core/src/main/java/org/apache/openejb/cdi/WebappWebBeansContext.java
index 6d99a1a..6effb38 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/cdi/WebappWebBeansContext.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/cdi/WebappWebBeansContext.java
@@ -22,16 +22,19 @@
 
 import org.apache.webbeans.config.WebBeansContext;
 import org.apache.webbeans.container.BeanManagerImpl;
+import org.apache.webbeans.event.NotificationManager;
 
 import javax.enterprise.inject.spi.Bean;
 
 public class WebappWebBeansContext extends WebBeansContext {
     private final WebBeansContext parent;
     private BeanManagerImpl bm;
+    private final WebappNotificationManager webappNotificationManager;
 
     public WebappWebBeansContext(final Map<Class<?>, Object> services, final Properties properties, final WebBeansContext webBeansContext) {
         super(services, properties);
         parent = webBeansContext;
+        webappNotificationManager = new WebappNotificationManager(this);
     }
 
     @SuppressWarnings("PMD.DoubleCheckedLocking")
@@ -61,4 +64,9 @@
         }
         return false;
     }
+
+    @Override
+    public NotificationManager getNotificationManager() {
+        return webappNotificationManager;
+    }
 }
diff --git a/tck/cdi-embedded/dev-tests.xml b/tck/cdi-embedded/dev-tests.xml
index 594bddc..9f4aac7 100644
--- a/tck/cdi-embedded/dev-tests.xml
+++ b/tck/cdi-embedded/dev-tests.xml
@@ -50,8 +50,9 @@
 
     <classes>
       <!-- fails due to integration issue within openejb-http, but passes on cdi-tomee -->
-      <class name="org.jboss.cdi.tck.tests.lookup.modules.specialization.alternative.Specialization06Test">
-<!--        <methods><include name="testInterceptorMetadata"/></methods>-->
+        <!--      <class name="org.jboss.cdi.tck.tests.lookup.modules.specialization.alternative.Specialization06Test">-->
+        <class name="org.jboss.cdi.tck.tests.event.observer.inheritance.enterprise.EnterpriseObserverInheritanceTest">
+<!--        <methods><include name="testNonStaticObserverMethodInherited"/></methods>-->
       </class>
 
     </classes>