qpid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bo...@apache.org
Subject [1/2] qpid-proton git commit: PROTON-964: Proton-J extensible event types
Date Tue, 18 Aug 2015 11:55:01 GMT
Repository: qpid-proton
Updated Branches:
  refs/heads/master 5dd68448f -> 35680ce54


PROTON-964: Proton-J extensible event types


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/94c571f0
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/94c571f0
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/94c571f0

Branch: refs/heads/master
Commit: 94c571f00612b8cffb63dc3a873f6f121653d579
Parents: 5dd6844
Author: Bozo Dragojevic <bozzo@digiverse.si>
Authored: Mon Jul 13 12:57:13 2015 +0200
Committer: Bozo Dragojevic <bozzo@digiverse.si>
Committed: Tue Aug 18 13:35:11 2015 +0200

----------------------------------------------------------------------
 .../apache/qpid/proton/engine/BaseHandler.java  | 130 +++++-
 .../apache/qpid/proton/engine/CoreHandler.java  |  71 ++++
 .../org/apache/qpid/proton/engine/Event.java    |  46 ++-
 .../apache/qpid/proton/engine/EventType.java    |  40 ++
 .../org/apache/qpid/proton/engine/Handler.java  |  64 +--
 .../qpid/proton/engine/RecordAccessor.java      |  26 ++
 .../qpid/proton/engine/impl/CollectorImpl.java  |  11 +-
 .../qpid/proton/engine/impl/EventImpl.java      | 158 ++------
 .../qpid/proton/reactor/impl/ReactorImpl.java   |  11 +-
 proton-j/src/main/resources/cengine.py          |   2 +-
 .../proton/engine/EventExtensibilityTest.java   | 396 +++++++++++++++++++
 .../apache/qpid/proton/reactor/ReactorTest.java |   1 +
 12 files changed, 769 insertions(+), 187 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/94c571f0/proton-j/src/main/java/org/apache/qpid/proton/engine/BaseHandler.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/BaseHandler.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/BaseHandler.java
index c9c5d51..7c518a0 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/BaseHandler.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/BaseHandler.java
@@ -29,7 +29,7 @@ import java.util.Iterator;
  *
  */
 
-public class BaseHandler implements Handler
+public class BaseHandler implements CoreHandler
 {
 
     public static Handler getHandler(Record r) {
@@ -109,4 +109,132 @@ public class BaseHandler implements Handler
         return children.iterator();
     }
 
+	@Override
+	public void handle(Event e) {
+        switch (e.getType()) {
+        case CONNECTION_INIT:
+            onConnectionInit(e);
+            break;
+        case CONNECTION_LOCAL_OPEN:
+            onConnectionLocalOpen(e);
+            break;
+        case CONNECTION_REMOTE_OPEN:
+            onConnectionRemoteOpen(e);
+            break;
+        case CONNECTION_LOCAL_CLOSE:
+            onConnectionLocalClose(e);
+            break;
+        case CONNECTION_REMOTE_CLOSE:
+            onConnectionRemoteClose(e);
+            break;
+        case CONNECTION_BOUND:
+            onConnectionBound(e);
+            break;
+        case CONNECTION_UNBOUND:
+            onConnectionUnbound(e);
+            break;
+        case CONNECTION_FINAL:
+            onConnectionFinal(e);
+            break;
+        case SESSION_INIT:
+            onSessionInit(e);
+            break;
+        case SESSION_LOCAL_OPEN:
+            onSessionLocalOpen(e);
+            break;
+        case SESSION_REMOTE_OPEN:
+            onSessionRemoteOpen(e);
+            break;
+        case SESSION_LOCAL_CLOSE:
+            onSessionLocalClose(e);
+            break;
+        case SESSION_REMOTE_CLOSE:
+            onSessionRemoteClose(e);
+            break;
+        case SESSION_FINAL:
+            onSessionFinal(e);
+            break;
+        case LINK_INIT:
+            onLinkInit(e);
+            break;
+        case LINK_LOCAL_OPEN:
+            onLinkLocalOpen(e);
+            break;
+        case LINK_REMOTE_OPEN:
+            onLinkRemoteOpen(e);
+            break;
+        case LINK_LOCAL_DETACH:
+            onLinkLocalDetach(e);
+            break;
+        case LINK_REMOTE_DETACH:
+            onLinkRemoteDetach(e);
+            break;
+        case LINK_LOCAL_CLOSE:
+            onLinkLocalClose(e);
+            break;
+        case LINK_REMOTE_CLOSE:
+            onLinkRemoteClose(e);
+            break;
+        case LINK_FLOW:
+            onLinkFlow(e);
+            break;
+        case LINK_FINAL:
+            onLinkFinal(e);
+            break;
+        case DELIVERY:
+            onDelivery(e);
+            break;
+        case TRANSPORT:
+            onTransport(e);
+            break;
+        case TRANSPORT_ERROR:
+            onTransportError(e);
+            break;
+        case TRANSPORT_HEAD_CLOSED:
+            onTransportHeadClosed(e);
+            break;
+        case TRANSPORT_TAIL_CLOSED:
+            onTransportTailClosed(e);
+            break;
+        case TRANSPORT_CLOSED:
+            onTransportClosed(e);
+            break;
+        case REACTOR_FINAL:
+            onReactorFinal(e);
+            break;
+        case REACTOR_QUIESCED:
+            onReactorQuiesced(e);
+            break;
+        case REACTOR_INIT:
+            onReactorInit(e);
+            break;
+        case SELECTABLE_ERROR:
+            onSelectableError(e);
+            break;
+        case SELECTABLE_EXPIRED:
+            onSelectableExpired(e);
+            break;
+        case SELECTABLE_FINAL:
+            onSelectableFinal(e);
+            break;
+        case SELECTABLE_INIT:
+            onSelectableInit(e);
+            break;
+        case SELECTABLE_READABLE:
+            onSelectableReadable(e);
+            break;
+        case SELECTABLE_UPDATED:
+            onSelectableWritable(e);
+            break;
+        case SELECTABLE_WRITABLE:
+            onSelectableWritable(e);
+            break;
+        case TIMER_TASK:
+            onTimerTask(e);
+            break;
+        case NON_CORE_EVENT:
+            onUnhandled(e);
+            break;
+        }
+	}
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/94c571f0/proton-j/src/main/java/org/apache/qpid/proton/engine/CoreHandler.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/CoreHandler.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/CoreHandler.java
new file mode 100644
index 0000000..81c66db
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/CoreHandler.java
@@ -0,0 +1,71 @@
+/*
+ *
+ * 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.qpid.proton.engine;
+
+public interface CoreHandler extends Handler {
+    void onConnectionInit(Event e);
+    void onConnectionLocalOpen(Event e);
+    void onConnectionRemoteOpen(Event e);
+    void onConnectionLocalClose(Event e);
+    void onConnectionRemoteClose(Event e);
+    void onConnectionBound(Event e);
+    void onConnectionUnbound(Event e);
+    void onConnectionFinal(Event e);
+
+    void onSessionInit(Event e);
+    void onSessionLocalOpen(Event e);
+    void onSessionRemoteOpen(Event e);
+    void onSessionLocalClose(Event e);
+    void onSessionRemoteClose(Event e);
+    void onSessionFinal(Event e);
+
+    void onLinkInit(Event e);
+    void onLinkLocalOpen(Event e);
+    void onLinkRemoteOpen(Event e);
+    void onLinkLocalDetach(Event e);
+    void onLinkRemoteDetach(Event e);
+    void onLinkLocalClose(Event e);
+    void onLinkRemoteClose(Event e);
+    void onLinkFlow(Event e);
+    void onLinkFinal(Event e);
+
+    void onDelivery(Event e);
+    void onTransport(Event e);
+    void onTransportError(Event e);
+    void onTransportHeadClosed(Event e);
+    void onTransportTailClosed(Event e);
+    void onTransportClosed(Event e);
+
+    void onReactorInit(Event e);
+    void onReactorQuiesced(Event e);
+    void onReactorFinal(Event e);
+
+    void onTimerTask(Event e);
+
+    void onSelectableInit(Event e);
+    void onSelectableUpdated(Event e);
+    void onSelectableReadable(Event e);
+    void onSelectableWritable(Event e);
+    void onSelectableExpired(Event e);
+    void onSelectableError(Event e);
+    void onSelectableFinal(Event e);
+
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/94c571f0/proton-j/src/main/java/org/apache/qpid/proton/engine/Event.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/Event.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/Event.java
index d351eed..9a1c69d 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/Event.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/Event.java
@@ -32,8 +32,10 @@ import org.apache.qpid.proton.reactor.Task;
 
 public interface Event extends Extendable
 {
-
-    public enum Type {
+    /**
+     * Event types built into the library.
+     */
+    public enum Type implements EventType {
         REACTOR_INIT,
         REACTOR_QUIESCED,
         REACTOR_FINAL,
@@ -80,15 +82,53 @@ public interface Event extends Extendable
         SELECTABLE_WRITABLE,
         SELECTABLE_EXPIRED,
         SELECTABLE_ERROR,
-        SELECTABLE_FINAL
+        SELECTABLE_FINAL,
+        
+        /**
+         * This value must never be used to generate an event, it's only used as
+         * a guard when casting custom EventTypes to core {@link Type} via
+         * {@link Event#getType()}.
+         */
+        NON_CORE_EVENT {
+            @Override
+            public boolean isValid() { return false; }
+        };
+
+        @Override
+        public boolean isValid() {
+            return true;
+        }
     }
 
+    /**
+     * @return type of the event. The event type can be defined outside of the
+     *         proton library.
+     */
+    EventType getEventType();
+
+    /**
+     * A concrete event type of core events.
+     * 
+     * @return type of the event for core events. For events generated by
+     *         extensions a {@link Type#NON_CORE_EVENT} will be returned
+     */
     Type getType();
 
     Object getContext();
 
     void dispatch(Handler handler) throws HandlerException;
 
+    /**
+     * Synchronously redispatch the current event as a new {@link EventType} on the provided
handler and it's children.
+     * <p>
+     * Note: the redispatch will happen before children of the current handler have had the
current event dispatched.
+     *
+     * @param as_type Type of event to dispatch
+     * @param handler The handler where to start the dispatch
+     * @throws HandlerException A wrapper exception of any unhandled exception thrown by
<code>handler</code>
+     */
+    void redispatch(EventType as_type, Handler handler) throws HandlerException;
+
     Connection getConnection();
 
     Session getSession();

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/94c571f0/proton-j/src/main/java/org/apache/qpid/proton/engine/EventType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/EventType.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/EventType.java
new file mode 100644
index 0000000..68ec6e4
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/EventType.java
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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.qpid.proton.engine;
+
+/**
+ * Entry point for external libraries to add event types. Event types should be
+ * <code>final static</code> fields. EventType instances are compared by
+ * reference.
+ * <p>
+ * Event types are best described by an <code>enum</code> that implements the
+ * {@link EventType} interface, see {@link Event.Type}.
+ * 
+ */
+public interface EventType {
+
+    /**
+     * @return false if this particular EventType instance does not represent a
+     *         real event type but a guard value, example: extra enum value for
+     *         switch statements, see {@link Event.Type#NON_CORE_EVENT}
+     */
+    public boolean isValid();
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/94c571f0/proton-j/src/main/java/org/apache/qpid/proton/engine/Handler.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/Handler.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/Handler.java
index fe72091..3a8e5ae 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/Handler.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/Handler.java
@@ -30,56 +30,26 @@ import java.util.Iterator;
 
 public interface Handler
 {
-
-    void onConnectionInit(Event e);
-    void onConnectionLocalOpen(Event e);
-    void onConnectionRemoteOpen(Event e);
-    void onConnectionLocalClose(Event e);
-    void onConnectionRemoteClose(Event e);
-    void onConnectionBound(Event e);
-    void onConnectionUnbound(Event e);
-    void onConnectionFinal(Event e);
-
-    void onSessionInit(Event e);
-    void onSessionLocalOpen(Event e);
-    void onSessionRemoteOpen(Event e);
-    void onSessionLocalClose(Event e);
-    void onSessionRemoteClose(Event e);
-    void onSessionFinal(Event e);
-
-    void onLinkInit(Event e);
-    void onLinkLocalOpen(Event e);
-    void onLinkRemoteOpen(Event e);
-    void onLinkLocalDetach(Event e);
-    void onLinkRemoteDetach(Event e);
-    void onLinkLocalClose(Event e);
-    void onLinkRemoteClose(Event e);
-    void onLinkFlow(Event e);
-    void onLinkFinal(Event e);
-
-    void onDelivery(Event e);
-    void onTransport(Event e);
-    void onTransportError(Event e);
-    void onTransportHeadClosed(Event e);
-    void onTransportTailClosed(Event e);
-    void onTransportClosed(Event e);
-
-    void onReactorInit(Event e);
-    void onReactorQuiesced(Event e);
-    void onReactorFinal(Event e);
-
-    void onTimerTask(Event e);
-
-    void onSelectableInit(Event e);
-    void onSelectableUpdated(Event e);
-    void onSelectableReadable(Event e);
-    void onSelectableWritable(Event e);
-    void onSelectableExpired(Event e);
-    void onSelectableError(Event e);
-    void onSelectableFinal(Event e);
+    /**
+     * Handle the event in this instance. This is the second half of
+     * {@link Event#dispatch(Handler)}. The method must invoke a concrete onXxx
+     * method for the given event, or invoke it's {@link #onUnhandled(Event)}
+     * method if the {@link EventType} of the event is not recognized by the
+     * handler.
+     * <p>
+     * <b>Note:</b> The handler is not supposed to invoke the
+     * {@link #handle(Event)} method on it's {@link #children()}, that is the
+     * responsibility of the {@link Event#dispatch(Handler)}
+     *
+     * @see BaseHandler
+     * @param e
+     *            The event to handle
+     */
+    void handle(Event e);
 
     void onUnhandled(Event e);
 
     void add(Handler child);
+
     Iterator<Handler> children();
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/94c571f0/proton-j/src/main/java/org/apache/qpid/proton/engine/RecordAccessor.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/RecordAccessor.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/RecordAccessor.java
new file mode 100644
index 0000000..4896b21
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/RecordAccessor.java
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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.qpid.proton.engine;
+
+public interface RecordAccessor<T> {
+    public T get(Record r);
+    public void set(Record r, T value);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/94c571f0/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/CollectorImpl.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/CollectorImpl.java
b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/CollectorImpl.java
index fe09a23..b4d3925 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/CollectorImpl.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/CollectorImpl.java
@@ -22,6 +22,7 @@ package org.apache.qpid.proton.engine.impl;
 
 import org.apache.qpid.proton.engine.Collector;
 import org.apache.qpid.proton.engine.Event;
+import org.apache.qpid.proton.engine.EventType;
 
 
 /**
@@ -57,9 +58,15 @@ public class CollectorImpl implements Collector
         }
     }
 
-    public EventImpl put(Event.Type type, Object context)
+    public EventImpl put(EventType type, Object context)
     {
-        if (tail != null && tail.getType() == type &&
+        if (type == null) {
+            throw new IllegalArgumentException("Type cannot be null");
+        }
+        if (!type.isValid()) {
+            throw new IllegalArgumentException("Cannot put events of type " + type);
+        }
+        if (tail != null && tail.getEventType() == type &&
             tail.getContext() == context) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/94c571f0/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/EventImpl.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/EventImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/EventImpl.java
index 4e97332..d516f6e 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/EventImpl.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/EventImpl.java
@@ -25,6 +25,7 @@ import java.util.Iterator;
 import org.apache.qpid.proton.engine.Connection;
 import org.apache.qpid.proton.engine.Delivery;
 import org.apache.qpid.proton.engine.Event;
+import org.apache.qpid.proton.engine.EventType;
 import org.apache.qpid.proton.engine.Handler;
 import org.apache.qpid.proton.engine.HandlerException;
 import org.apache.qpid.proton.engine.Link;
@@ -43,7 +44,7 @@ import org.apache.qpid.proton.reactor.Task;
 class EventImpl implements Event
 {
 
-    Type type;
+    EventType type;
     Object context;
     EventImpl next;
     RecordImpl attachments = new RecordImpl();
@@ -53,7 +54,7 @@ class EventImpl implements Event
         this.type = null;
     }
 
-    void init(Event.Type type, Object context)
+    void init(EventType type, Object context)
     {
         this.type = type;
         this.context = context;
@@ -68,12 +69,20 @@ class EventImpl implements Event
     }
 
     @Override
-    public Type getType()
+    public EventType getEventType()
     {
         return type;
     }
 
     @Override
+    public Type getType() {
+        if (type instanceof Type) {
+            return (Type)type;
+        }
+        return Type.NON_CORE_EVENT;
+    }
+
+    @Override
     public Object getContext()
     {
         return context;
@@ -83,131 +92,7 @@ class EventImpl implements Event
     public void dispatch(Handler handler)
     {
         try {
-            switch (type) {
-            case CONNECTION_INIT:
-                handler.onConnectionInit(this);
-                break;
-            case CONNECTION_LOCAL_OPEN:
-                handler.onConnectionLocalOpen(this);
-                break;
-            case CONNECTION_REMOTE_OPEN:
-                handler.onConnectionRemoteOpen(this);
-                break;
-            case CONNECTION_LOCAL_CLOSE:
-                handler.onConnectionLocalClose(this);
-                break;
-            case CONNECTION_REMOTE_CLOSE:
-                handler.onConnectionRemoteClose(this);
-                break;
-            case CONNECTION_BOUND:
-                handler.onConnectionBound(this);
-                break;
-            case CONNECTION_UNBOUND:
-                handler.onConnectionUnbound(this);
-                break;
-            case CONNECTION_FINAL:
-                handler.onConnectionFinal(this);
-                break;
-            case SESSION_INIT:
-                handler.onSessionInit(this);
-                break;
-            case SESSION_LOCAL_OPEN:
-                handler.onSessionLocalOpen(this);
-                break;
-            case SESSION_REMOTE_OPEN:
-                handler.onSessionRemoteOpen(this);
-                break;
-            case SESSION_LOCAL_CLOSE:
-                handler.onSessionLocalClose(this);
-                break;
-            case SESSION_REMOTE_CLOSE:
-                handler.onSessionRemoteClose(this);
-                break;
-            case SESSION_FINAL:
-                handler.onSessionFinal(this);
-                break;
-            case LINK_INIT:
-                handler.onLinkInit(this);
-                break;
-            case LINK_LOCAL_OPEN:
-                handler.onLinkLocalOpen(this);
-                break;
-            case LINK_REMOTE_OPEN:
-                handler.onLinkRemoteOpen(this);
-                break;
-            case LINK_LOCAL_DETACH:
-                handler.onLinkLocalDetach(this);
-                break;
-            case LINK_REMOTE_DETACH:
-                handler.onLinkRemoteDetach(this);
-                break;
-            case LINK_LOCAL_CLOSE:
-                handler.onLinkLocalClose(this);
-                break;
-            case LINK_REMOTE_CLOSE:
-                handler.onLinkRemoteClose(this);
-                break;
-            case LINK_FLOW:
-                handler.onLinkFlow(this);
-                break;
-            case LINK_FINAL:
-                handler.onLinkFinal(this);
-                break;
-            case DELIVERY:
-                handler.onDelivery(this);
-                break;
-            case TRANSPORT:
-                handler.onTransport(this);
-                break;
-            case TRANSPORT_ERROR:
-                handler.onTransportError(this);
-                break;
-            case TRANSPORT_HEAD_CLOSED:
-                handler.onTransportHeadClosed(this);
-                break;
-            case TRANSPORT_TAIL_CLOSED:
-                handler.onTransportTailClosed(this);
-                break;
-            case TRANSPORT_CLOSED:
-                handler.onTransportClosed(this);
-                break;
-            case REACTOR_FINAL:
-                handler.onReactorFinal(this);
-                break;
-            case REACTOR_QUIESCED:
-                handler.onReactorQuiesced(this);
-                break;
-            case REACTOR_INIT:
-                handler.onReactorInit(this);
-                break;
-            case SELECTABLE_ERROR:
-                handler.onSelectableError(this);
-                break;
-            case SELECTABLE_EXPIRED:
-                handler.onSelectableExpired(this);
-                break;
-            case SELECTABLE_FINAL:
-                handler.onSelectableFinal(this);
-                break;
-            case SELECTABLE_INIT:
-                handler.onSelectableInit(this);
-                break;
-            case SELECTABLE_READABLE:
-                handler.onSelectableReadable(this);
-                break;
-            case SELECTABLE_UPDATED:
-                handler.onSelectableWritable(this);
-                break;
-            case SELECTABLE_WRITABLE:
-                handler.onSelectableWritable(this);
-                break;
-            case TIMER_TASK:
-                handler.onTimerTask(this);
-                break;
-            default:
-                handler.onUnhandled(this);
-                break;
-            }
+            handler.handle(this);
         } catch(RuntimeException runtimeException) {
             throw new HandlerException(handler, runtimeException);
         }
@@ -217,6 +102,22 @@ class EventImpl implements Event
             dispatch(children.next());
         }
     }
+    
+    @Override
+    public void redispatch(EventType as_type, Handler handler) throws HandlerException 
+    {
+        if (!as_type.isValid()) {
+            throw new IllegalArgumentException("Can only redispatch valid event types");
+        }
+        EventType old = type;
+        try {
+            type = as_type;
+            dispatch(handler);
+        }
+        finally {
+            type = old;
+        }
+    }
 
     @Override
     public Connection getConnection()
@@ -346,4 +247,5 @@ class EventImpl implements Event
         return "EventImpl{" + "type=" + type + ", context=" + context + '}';
     }
 
+
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/94c571f0/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/ReactorImpl.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/ReactorImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/ReactorImpl.java
index 5fc451d..8335ea7 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/ReactorImpl.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/ReactorImpl.java
@@ -34,6 +34,7 @@ import org.apache.qpid.proton.engine.Collector;
 import org.apache.qpid.proton.engine.Connection;
 import org.apache.qpid.proton.engine.Event;
 import org.apache.qpid.proton.engine.Event.Type;
+import org.apache.qpid.proton.engine.EventType;
 import org.apache.qpid.proton.engine.Extendable;
 import org.apache.qpid.proton.engine.Handler;
 import org.apache.qpid.proton.engine.HandlerException;
@@ -60,7 +61,7 @@ public class ReactorImpl implements Reactor, Extendable {
     private int selectables;
     private boolean yield;
     private Selectable selectable;
-    private Type previous;
+    private EventType previous;
     private Timer timer;
     private final Pipe wakeup;
     private Selector selector;
@@ -251,13 +252,13 @@ public class ReactorImpl implements Reactor, Extendable {
         Event event = collector.peek();
         if (event == null) return true;
         if (collector.more()) return false;
-        return event.getType() == Type.REACTOR_QUIESCED;
+        return event.getEventType() == Type.REACTOR_QUIESCED;
     }
 
     @Override
     public boolean process() throws HandlerException {
         mark();
-        Type previous = null;
+        EventType previous = null;
         while (true) {
             Event event = collector.peek();
             if (event != null) {
@@ -269,10 +270,10 @@ public class ReactorImpl implements Reactor, Extendable {
                 event.dispatch(handler);
                 event.dispatch(global);
 
-                if (event.getType() == Type.CONNECTION_FINAL) {
+                if (event.getEventType() == Type.CONNECTION_FINAL) {
                     children.remove(event.getConnection());
                 }
-                this.previous = event.getType();
+                this.previous = event.getEventType();
                 previous = this.previous;
                 collector.pop();
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/94c571f0/proton-j/src/main/resources/cengine.py
----------------------------------------------------------------------
diff --git a/proton-j/src/main/resources/cengine.py b/proton-j/src/main/resources/cengine.py
index ee2226d..019a9ac 100644
--- a/proton-j/src/main/resources/cengine.py
+++ b/proton-j/src/main/resources/cengine.py
@@ -1099,7 +1099,7 @@ def pn_event_context(event):
   return wrappers[pn_event_class(event)](event.impl.getContext())
 
 def pn_event_type(event):
-  return event.impl.getType()
+  return event.impl.getEventType()
 
 def pn_event_type_name(etype):
   return str(etype)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/94c571f0/proton-j/src/test/java/org/apache/qpid/proton/engine/EventExtensibilityTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/engine/EventExtensibilityTest.java
b/proton-j/src/test/java/org/apache/qpid/proton/engine/EventExtensibilityTest.java
new file mode 100644
index 0000000..2706bab
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/engine/EventExtensibilityTest.java
@@ -0,0 +1,396 @@
+/*
+ *
+ * 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.qpid.proton.engine;
+
+import java.io.IOException;
+import java.nio.file.FileVisitOption;
+
+import org.apache.qpid.proton.engine.Event.Type;
+import org.apache.qpid.proton.engine.EventExtensibilityTest.ExtraEvent.ExtraTypes;
+import org.apache.qpid.proton.reactor.Reactor;
+import org.apache.qpid.proton.reactor.Selectable;
+import org.apache.qpid.proton.reactor.Task;
+import org.junit.Test;
+
+import junit.framework.TestCase;
+
+public class EventExtensibilityTest extends TestCase {
+
+    // //////////////
+    // / Extra package public API classes
+    // //////////////
+
+    /**
+     * Sample additional information that gets generated and passed around with
+     * the extension events. The information is stored inside
+     * {@link Event#attachments()} see {@link ExtraEventImpl#getExtraInfo()}
+     */
+    public static class ExtraInfo {
+        public int foo;
+    }
+
+    /**
+     * Additional events generated by this extension.
+     * 
+     */
+    public interface ExtraEvent extends Event {
+        /**
+         * Enum is a convenient mechanism for defining new event types
+         */
+        public enum ExtraTypes implements EventType {
+            FOO,
+            BAR,
+            NOT_A_EXTRA_EVENT {
+                @Override public boolean isValid() { return false; }
+            };
+
+            @Override
+            public boolean isValid() {
+                return true;
+            }
+        }
+
+        /**
+         * typesafe access to event type generated by this extension useful for
+         * handling in switch statements
+         * 
+         * @return one of enum values. When invoked on an Event that is not an
+         *         ExtraEvent the return value shall be
+         */
+        ExtraTypes getExtraEventType();
+
+        /**
+         * typesafe access to extra information attached to additional events
+         * 
+         * @return ExtraInfo stored in the event attachment
+         */
+        ExtraInfo getExtraInfo();
+    }
+
+    /**
+     * New handler methods for handling the extended event types. These methods
+     * can take {@link ExtraEvent} as a parameter to get typesafe access to
+     * {@link ExtraInfo}
+     *
+     * The interface needs to extend the {@link Handler} interface.
+     */
+    public interface ExtraHandler extends Handler {
+        void onFoo(ExtraEvent e);
+
+        void onBar(ExtraEvent e);
+    }
+
+    /**
+     * Implementation of the default base class for ExtraHandler. All events
+     * should be forwarded to the {@link Handler#onUnhandled(Event)} method
+     */
+    public static class ExtraBaseHandler extends BaseHandler implements ExtraHandler {
+
+        @Override
+        public void onFoo(ExtraEvent e) {
+            this.onUnhandled(e);
+        }
+
+        @Override
+        public void onBar(ExtraEvent e) {
+            this.onUnhandled(e);
+        }
+
+        @Override
+        public void handle(Event e) {
+            EventType type = e.getEventType();
+            if (type instanceof ExtraEvent.ExtraTypes) {
+                final ExtraEvent event;
+                if (e instanceof ExtraEvent) {
+                    event = (ExtraEvent)e;
+                } else {
+                    event = new ExtraEventImpl(e);
+                }
+                switch((ExtraEvent.ExtraTypes)type) {
+                case BAR:
+                    onBar(event);
+                    break;
+                case FOO:
+                    onFoo(event);
+                    break;
+                case NOT_A_EXTRA_EVENT:
+                    super.handle(e);
+                    break;
+                }
+            } else {
+                super.handle(e);
+            }
+        }
+
+    }
+
+    // //////////////
+    // / Extra package implementation classes
+    // //////////////
+
+
+    /**
+     * Typesafe access to ExtraInfo attached to event
+     *
+     */
+    public static class ExtraEventImpl implements ExtraEvent {
+        /**
+         * making this accessor public allows for easy binding to the scripting language
+         */
+        public static final RecordAccessor<ExtraInfo> extraInfoAccessor = new RecordAccessor<ExtraInfo>()
{
+
+            @Override
+            public ExtraInfo get(Record r) {
+                return r.get(this, ExtraInfo.class);
+            }
+
+            @Override
+            public void set(Record r, ExtraInfo value) {
+                r.set(this, ExtraInfo.class, value);
+            }
+
+        };
+        private Event impl;
+
+        public ExtraEventImpl(Event impl) {
+            this.impl = impl;
+        }
+
+        @Override
+        public ExtraTypes getExtraEventType() {
+            EventType type = impl.getEventType();
+            if (type instanceof ExtraTypes)
+                return (ExtraTypes) type;
+            else
+                return ExtraTypes.NOT_A_EXTRA_EVENT;
+        }
+
+        @Override
+        public ExtraInfo getExtraInfo() {
+            return extraInfoAccessor.get(impl.attachments());
+        }
+
+        // ---- delegate methods for the Event
+
+        public Record attachments() {
+            return impl.attachments();
+        }
+
+        public EventType getEventType() {
+            return impl.getEventType();
+        }
+
+        public Type getType() {
+            return impl.getType();
+        }
+
+        public Object getContext() {
+            return impl.getContext();
+        }
+
+        public void dispatch(Handler handler) throws HandlerException {
+            impl.dispatch(handler);
+        }
+
+        public void redispatch(EventType as_type, Handler handler) throws HandlerException
{
+            impl.redispatch(as_type, handler);
+        }
+        public Connection getConnection() {
+            return impl.getConnection();
+        }
+
+        public Session getSession() {
+            return impl.getSession();
+        }
+
+        public Link getLink() {
+            return impl.getLink();
+        }
+
+        public Delivery getDelivery() {
+            return impl.getDelivery();
+        }
+
+        public Transport getTransport() {
+            return impl.getTransport();
+        }
+
+        public Reactor getReactor() {
+            return impl.getReactor();
+        }
+
+        public Selectable getSelectable() {
+            return impl.getSelectable();
+        }
+
+        public Task getTask() {
+            return impl.getTask();
+        }
+
+        public Event copy() {
+            return new ExtraEventImpl(impl.copy());
+        }
+    }
+
+    public class ExtendedTestEventGenerator extends BaseHandler {
+        @Override
+        public void onReactorInit(Event e) {
+            ExtraInfo extra = new ExtraInfo();
+            extra.foo = 1234;
+            ExtraEventImpl.extraInfoAccessor.set(e.attachments(), extra);
+            e.redispatch(ExtraEvent.ExtraTypes.FOO, this);
+        }
+    }
+
+    public class ExtendedTestHandler extends ExtraBaseHandler {
+        public boolean didFoo = false;
+        @Override
+        public void onFoo(ExtraEvent e) {
+            assertEquals(ExtraEvent.ExtraTypes.FOO, e.getEventType());
+            assertEquals(ExtraEvent.ExtraTypes.FOO, e.getExtraEventType());
+            assertEquals(Event.Type.NON_CORE_EVENT, e.getType());
+            assertNotNull(e.getExtraInfo());
+            assertEquals(1234, e.getExtraInfo().foo);
+            didFoo = true;
+        }
+    }
+
+    public class FooUnawareTestHandler extends BaseHandler {
+        public boolean seenFoo = false;
+        @Override
+        public void onUnhandled(Event e) {
+            if (e.getEventType() == ExtraTypes.FOO) {
+                seenFoo = true;
+            }
+            FileVisitOption o;
+        }
+    }
+
+    @Test
+    public void testExtendedType() throws IOException {
+        Reactor r = Reactor.Factory.create();
+        ExtendedTestEventGenerator gen = new ExtendedTestEventGenerator();
+        BaseHandler empty = new BaseHandler();
+        ExtendedTestHandler extra = new ExtendedTestHandler();
+        FooUnawareTestHandler unaware = new FooUnawareTestHandler();
+        gen.add(empty);
+        empty.add(extra);
+        extra.add(unaware);
+        r.setGlobalHandler(gen);
+        r.run();
+        assertTrue(extra.didFoo);
+        assertTrue(unaware.seenFoo);
+    }
+
+    @Test
+    public void test() {
+        Event.Type t = Type.NON_CORE_EVENT;
+        switch (extracted(t)) {
+        case CONNECTION_BOUND:
+            fail();
+        case CONNECTION_FINAL:
+            fail();
+        case CONNECTION_INIT:
+            fail();
+        case CONNECTION_LOCAL_CLOSE:
+            fail();
+        case CONNECTION_LOCAL_OPEN:
+            fail();
+        case CONNECTION_REMOTE_CLOSE:
+            fail();
+        case CONNECTION_REMOTE_OPEN:
+            fail();
+        case CONNECTION_UNBOUND:
+            fail();
+        case DELIVERY:
+            fail();
+        case LINK_FINAL:
+            fail();
+        case LINK_FLOW:
+            fail();
+        case LINK_INIT:
+            fail();
+        case LINK_LOCAL_CLOSE:
+            fail();
+        case LINK_LOCAL_DETACH:
+            fail();
+        case LINK_LOCAL_OPEN:
+            fail();
+        case LINK_REMOTE_CLOSE:
+            fail();
+        case LINK_REMOTE_DETACH:
+            fail();
+        case LINK_REMOTE_OPEN:
+            fail();
+        case REACTOR_FINAL:
+            fail();
+        case REACTOR_INIT:
+            fail();
+        case REACTOR_QUIESCED:
+            fail();
+        case SELECTABLE_ERROR:
+            fail();
+        case SELECTABLE_EXPIRED:
+            fail();
+        case SELECTABLE_FINAL:
+            fail();
+        case SELECTABLE_INIT:
+            fail();
+        case SELECTABLE_READABLE:
+            fail();
+        case SELECTABLE_UPDATED:
+            fail();
+        case SELECTABLE_WRITABLE:
+            fail();
+        case SESSION_FINAL:
+            fail();
+        case SESSION_INIT:
+            fail();
+        case SESSION_LOCAL_CLOSE:
+            fail();
+        case SESSION_LOCAL_OPEN:
+            fail();
+        case SESSION_REMOTE_CLOSE:
+            fail();
+        case SESSION_REMOTE_OPEN:
+            fail();
+        case TIMER_TASK:
+            fail();
+        case TRANSPORT:
+            fail();
+        case TRANSPORT_CLOSED:
+            fail();
+        case TRANSPORT_ERROR:
+            fail();
+        case TRANSPORT_HEAD_CLOSED:
+            fail();
+        case TRANSPORT_TAIL_CLOSED:
+            fail();
+        case NON_CORE_EVENT:
+            break;
+        }
+    }
+
+    private Type extracted(Event.Type t) {
+        return t;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/94c571f0/proton-j/src/test/java/org/apache/qpid/proton/reactor/ReactorTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/reactor/ReactorTest.java b/proton-j/src/test/java/org/apache/qpid/proton/reactor/ReactorTest.java
index 2d81666..10c591a 100644
--- a/proton-j/src/test/java/org/apache/qpid/proton/reactor/ReactorTest.java
+++ b/proton-j/src/test/java/org/apache/qpid/proton/reactor/ReactorTest.java
@@ -122,6 +122,7 @@ public class ReactorTest {
 
         @Override
         public void onUnhandled(Event event) {
+            assertNotNull(event.getReactor());
             actual.add(event.getType());
         }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


Mime
View raw message