Return-Path: X-Original-To: apmail-qpid-commits-archive@www.apache.org Delivered-To: apmail-qpid-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A336518942 for ; Tue, 18 Aug 2015 11:55:11 +0000 (UTC) Received: (qmail 80451 invoked by uid 500); 18 Aug 2015 11:55:02 -0000 Delivered-To: apmail-qpid-commits-archive@qpid.apache.org Received: (qmail 80416 invoked by uid 500); 18 Aug 2015 11:55:02 -0000 Mailing-List: contact commits-help@qpid.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@qpid.apache.org Delivered-To: mailing list commits@qpid.apache.org Received: (qmail 80403 invoked by uid 99); 18 Aug 2015 11:55:02 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 18 Aug 2015 11:55:02 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id EC712DFDD7; Tue, 18 Aug 2015 11:55:01 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: bozzo@apache.org To: commits@qpid.apache.org Date: Tue, 18 Aug 2015 11:55:01 -0000 Message-Id: <539a54805da344ba87b5f5a7902a7fad@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/2] qpid-proton git commit: PROTON-964: Proton-J extensible event types 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 Authored: Mon Jul 13 12:57:13 2015 +0200 Committer: Bozo Dragojevic 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. + *

+ * 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 handler + */ + 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 + * final static fields. EventType instances are compared by + * reference. + *

+ * Event types are best described by an enum 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. + *

+ * Note: 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 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 { + 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 extraInfoAccessor = new RecordAccessor() { + + @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