Author: rmannibucau
Date: Sat Mar 22 10:41:47 2014
New Revision: 1580190
URL: http://svn.apache.org/r1580190
Log:
TOMEE-1149 AfterEvent
Added:
tomee/tomee/trunk/container/openejb-loader/src/main/java/org/apache/openejb/observer/event/AfterEvent.java
Modified:
tomee/tomee/trunk/container/openejb-loader/src/main/java/org/apache/openejb/observer/ObserverManager.java
tomee/tomee/trunk/container/openejb-loader/src/main/java/org/apache/openejb/observer/Observes.java
tomee/tomee/trunk/container/openejb-loader/src/test/java/org/apache/openejb/loader/EventTest.java
Modified:
tomee/tomee/trunk/container/openejb-loader/src/main/java/org/apache/openejb/observer/ObserverManager.java
URL:
http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-loader/src/main/java/org/apache/openejb/observer/ObserverManager.java?rev=1580190&r1=1580189&r2=1580190&view=diff
==============================================================================
---
tomee/tomee/trunk/container/openejb-loader/src/main/java/org/apache/openejb/observer/ObserverManager.java
(original)
+++
tomee/tomee/trunk/container/openejb-loader/src/main/java/org/apache/openejb/observer/ObserverManager.java
Sat Mar 22 10:41:47 2014
@@ -16,6 +16,7 @@
*/
package org.apache.openejb.observer;
+import org.apache.openejb.observer.event.AfterEvent;
import org.apache.openejb.observer.event.ObserverAdded;
import org.apache.openejb.observer.event.ObserverFailed;
import org.apache.openejb.observer.event.ObserverRemoved;
@@ -24,19 +25,16 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.CopyOnWriteArraySet;
import java.util.logging.Level;
import java.util.logging.Logger;
-import static java.util.Arrays.asList;
-import static java.util.Collections.sort;
-
public class ObserverManager {
private final List<Observer> observers = new ArrayList<Observer>();
@@ -53,7 +51,7 @@ public class ObserverManager {
final boolean added = observers.add(obs);
if (added) {
// Observers can observe they have been added and are active
- fireEvent(new ObserverAdded(observer));
+ doFire(new ObserverAdded(observer));
}
return added;
}
@@ -64,14 +62,19 @@ public class ObserverManager {
final boolean removed = observers.remove(new Observer(observer));
if (removed) {
// Observers can observe they are to be removed
- fireEvent(new ObserverRemoved(observer));
+ doFire(new ObserverRemoved(observer));
}
return removed;
}
- public void fireEvent(Object event) {
+ public <T> void fireEvent(final T event) {
if (event == null) throw new IllegalArgumentException("event cannot be
null");
+ doFire(event);
+ doFire(new AfterEventImpl<T>(event));
+ }
+
+ private void doFire(final Object event) {
final List<Invocation> invocations = new LinkedList<Invocation>();
for (final Observer observer : observers) {
final Invocation i = observer.toInvocation(event);
@@ -80,12 +83,11 @@ public class ObserverManager {
}
}
- sort(invocations);
for (final Invocation invocation : invocations) {
try {
invocation.proceed();
} catch (final Throwable t) {
- if (!(event instanceof ObserverFailed)) {
+ if (!(event instanceof ObserverFailed) &&
!AfterEventImpl.class.isInstance(event)) {
fireEvent(new ObserverFailed(invocation.observer, event,
t));
}
if (t instanceof InvocationTargetException && t.getCause() !=
null) {
@@ -101,10 +103,10 @@ public class ObserverManager {
* @version $Rev$ $Date$
*/
public static class Observer {
- private final Map<Class, MetaMethod> methods = new HashMap<Class,
MetaMethod>();
+ private final Map<Type, Method> methods = new HashMap<Type, Method>();
private final Object observer;
private final Class<?> observerClass;
- private final MetaMethod defaultMethod;
+ private final Method defaultMethod;
public Observer(Object observer) {
if (observer == null) throw new IllegalArgumentException("observer
cannot be null");
@@ -129,29 +131,30 @@ public class ObserverManager {
throw new IllegalArgumentException("@Observes method must
be public: " + method.toString());
}
- final Class<?> type = method.getParameterTypes()[0];
+ final Type type = method.getGenericParameterTypes()[0];
+ final Class<?> raw = method.getParameterTypes()[0];
- if (type.isAnnotation()) {
+ if (raw.isAnnotation()) {
throw new IllegalArgumentException("@Observes method
parameter must be a concrete class (not an annotation): " + method.toString());
}
- if (Modifier.isAbstract(type.getModifiers())) {
+ if (Modifier.isAbstract(raw.getModifiers()) && raw == type) {
throw new IllegalArgumentException("@Observes method
parameter must be a concrete class (not an abstract class): " +
method.toString());
}
- if (type.isInterface()) {
+ if (raw.isInterface() && raw == type) {
throw new IllegalArgumentException("@Observes method
parameter must be a concrete class (not an interface): " + method.toString());
}
- if (type.isArray()) {
+ if (raw.isArray()) {
throw new IllegalArgumentException("@Observes method
parameter must be a concrete class (not an array): " + method.toString());
}
- if (type.isPrimitive()) {
+ if (raw.isPrimitive()) {
throw new IllegalArgumentException("@Observes method
parameter must be a concrete class (not a primitive): " + method.toString());
}
- methods.put(type, new MetaMethod(method, new
CopyOnWriteArraySet<Class<?>>(asList(annotation.after()))));
+ methods.put(type, method);
}
defaultMethod = methods.get(Object.class);
@@ -165,7 +168,31 @@ public class ObserverManager {
if (event == null) throw new IllegalArgumentException("event
cannot be null");
final Class eventType = event.getClass();
- final MetaMethod method = methods.get(eventType);
+ final Method method = methods.get(eventType);
+
+ if (method == null && AfterEventImpl.class.isInstance(event)) {
+ final Type type = new ParameterizedType() {
+ @Override
+ public Type[] getActualTypeArguments() {
+ return new Type[] {
AfterEventImpl.class.cast(event).getEvent().getClass() };
+ }
+
+ @Override
+ public Type getRawType() {
+ return AfterEvent.class;
+ }
+
+ @Override
+ public Type getOwnerType() {
+ return null;
+ }
+ };
+ for (final Map.Entry<Type, Method> m : methods.entrySet()) {
+ if (m.getKey().equals(type)) {
+ return new Invocation(this, m.getValue(), event);
+ }
+ }
+ }
if (method != null) {
return new Invocation(this, method, event);
@@ -213,55 +240,26 @@ public class ObserverManager {
}
}
- private static class MetaMethod {
- private final Method method;
- private final Collection<Class<?>> after;
-
- private MetaMethod(final Method method, final Collection<Class<?>>
after) {
- this.method = method;
- this.after = after;
- }
-
- @Override
- public String toString() {
- return "MetaMethod{" +
- "method=" + method +
- ", after=" + after +
- '}';
- }
- }
-
- private static class Invocation implements Comparable<Invocation> {
+ private static class Invocation {
private final Observer observer;
- private final MetaMethod metaMethod;
+ private final Method method;
private final Object event;
- private Invocation(final Observer observer, final MetaMethod method,
final Object event) {
+ private Invocation(final Observer observer, final Method method, final
Object event) {
this.observer = observer;
- this.metaMethod = method;
+ this.method = method;
this.event = event;
}
private void proceed() throws InvocationTargetException,
IllegalAccessException {
- metaMethod.method.invoke(observer.observer, event);
- }
-
- @Override // only called for a single event so only consider
observer.after
- public int compareTo(final Invocation o) {
- if (o == null) {
- return 0;
- }
- if (metaMethod.after.contains(o.observer.observerClass)) {
- return 1;
- }
- return -1;
+ method.invoke(observer.observer, event);
}
@Override
public String toString() {
return "Invocation{" +
"observer=" + observer +
- ", metaMethod=" + metaMethod +
+ ", method=" + method +
", event=" + event +
'}';
}
@@ -272,4 +270,16 @@ public class ObserverManager {
super(s);
}
}
+
+ private static class AfterEventImpl<T> implements AfterEvent<T> {
+ private final T event;
+
+ public AfterEventImpl(final T event) {
+ this.event = event;
+ }
+
+ public T getEvent() {
+ return event;
+ }
+ }
}
Modified:
tomee/tomee/trunk/container/openejb-loader/src/main/java/org/apache/openejb/observer/Observes.java
URL:
http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-loader/src/main/java/org/apache/openejb/observer/Observes.java?rev=1580190&r1=1580189&r2=1580190&view=diff
==============================================================================
---
tomee/tomee/trunk/container/openejb-loader/src/main/java/org/apache/openejb/observer/Observes.java
(original)
+++
tomee/tomee/trunk/container/openejb-loader/src/main/java/org/apache/openejb/observer/Observes.java
Sat Mar 22 10:41:47 2014
@@ -30,5 +30,4 @@ import static java.lang.annotation.Reten
@Retention(RUNTIME)
@Documented
public @interface Observes {
- Class<?>[] after() default {};
}
\ No newline at end of file
Added:
tomee/tomee/trunk/container/openejb-loader/src/main/java/org/apache/openejb/observer/event/AfterEvent.java
URL:
http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-loader/src/main/java/org/apache/openejb/observer/event/AfterEvent.java?rev=1580190&view=auto
==============================================================================
---
tomee/tomee/trunk/container/openejb-loader/src/main/java/org/apache/openejb/observer/event/AfterEvent.java
(added)
+++
tomee/tomee/trunk/container/openejb-loader/src/main/java/org/apache/openejb/observer/event/AfterEvent.java
Sat Mar 22 10:41:47 2014
@@ -0,0 +1,24 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.observer.event;
+
+import org.apache.openejb.observer.Event;
+
+@Event
+public interface AfterEvent<T> {
+ T getEvent();
+}
Modified:
tomee/tomee/trunk/container/openejb-loader/src/test/java/org/apache/openejb/loader/EventTest.java
URL:
http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-loader/src/test/java/org/apache/openejb/loader/EventTest.java?rev=1580190&r1=1580189&r2=1580190&view=diff
==============================================================================
---
tomee/tomee/trunk/container/openejb-loader/src/test/java/org/apache/openejb/loader/EventTest.java
(original)
+++
tomee/tomee/trunk/container/openejb-loader/src/test/java/org/apache/openejb/loader/EventTest.java
Sat Mar 22 10:41:47 2014
@@ -17,50 +17,62 @@
package org.apache.openejb.loader;
import org.apache.openejb.observer.Observes;
+import org.apache.openejb.observer.event.AfterEvent;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import java.util.concurrent.atomic.AtomicInteger;
-
+import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
public class EventTest {
@After
@Before
public void reset() {
SystemInstance.reset();
+ SimpleObserver.id = -1;
}
- private static final AtomicInteger ID = new AtomicInteger(0);
-
@Test
- public void order() {
+ public void simple() {
final SystemInstance s = SystemInstance.get();
assertEquals(-1, SimpleObserver.id);
- assertEquals(-1, OrderedSimpleObserver.id);
- s.addObserver(new OrderedSimpleObserver());
s.addObserver(new SimpleObserver());
s.fireEvent(new SimpleEvent());
assertEquals(1, SimpleObserver.id);
- assertEquals(2, OrderedSimpleObserver.id);
+ }
+
+ @Test
+ public void afterEvent() {
+ final SystemInstance s = SystemInstance.get();
+ assertEquals(-1, SimpleObserver.id);
+ s.addObserver(new SimpleObserver());
+ s.addObserver(new AfterSimpleObserver());
+ final SimpleEvent event = new SimpleEvent();
+ s.fireEvent(event);
+ assertEquals(1, SimpleObserver.id);
+ assertNotNull(AfterSimpleObserver.event);
+ assertEquals(event, AfterSimpleObserver.event.getEvent());
}
public static class SimpleEvent {}
- public static class SimpleObserver {
- private static int id = -1;
+ public static class AfterSimpleObserver {
+ private static AfterEvent<SimpleEvent> event;
- public void observe(final @Observes SimpleEvent event) {
- id = ID.incrementAndGet();
+ public void observe(final @Observes AfterEvent<SimpleEvent> event) {
+ AfterSimpleObserver.event = event;
+ assertThat(event.getEvent(), instanceOf(SimpleEvent.class));
}
}
- public static class OrderedSimpleObserver {
+ public static class SimpleObserver {
private static int id = -1;
- public void observe(final @Observes(after = SimpleObserver.class)
SimpleEvent event) {
- id = ID.incrementAndGet();
+ public void observe(final @Observes SimpleEvent event) {
+ id = 1;
}
}
}