PROTON-799: Added the Event classes to the Ruby engine APIs.
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/766a59ec Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/766a59ec Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/766a59ec Branch: refs/heads/ruby-engine-apis Commit: 766a59ecd340d47fdfa6926fc2a449785c7dd86b Parents: 5b9e8ff Author: Darryl L. Pierce <mcpie...@gmail.com> Authored: Tue Feb 3 17:17:18 2015 -0500 Committer: Darryl L. Pierce <mcpie...@gmail.com> Committed: Tue May 19 08:02:48 2015 -0400 ---------------------------------------------------------------------- proton-c/bindings/ruby/lib/event/event.rb | 297 ++++++++++++++++++++ proton-c/bindings/ruby/lib/event/event_base.rb | 91 ++++++ proton-c/bindings/ruby/lib/event/event_type.rb | 71 +++++ proton-c/bindings/ruby/lib/qpid_proton.rb | 3 + 4 files changed, 462 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/766a59ec/proton-c/bindings/ruby/lib/event/event.rb ---------------------------------------------------------------------- diff --git a/proton-c/bindings/ruby/lib/event/event.rb b/proton-c/bindings/ruby/lib/event/event.rb new file mode 100644 index 0000000..cdffba2 --- /dev/null +++ b/proton-c/bindings/ruby/lib/event/event.rb @@ -0,0 +1,297 @@ +#-- +# 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. +#++ + +module Qpid::Proton + + module Event + + # @private + def self.event_type(const_name, method_name = nil) # :nodoc: + unless Cproton.const_defined?(const_name) + raise RuntimeError.new("no such constant: #{const_name}") + end + + const_value = Cproton.const_get(const_name) + method_name = "on_#{const_name.to_s[3..-1]}".downcase if method_name.nil? + + EventType.new(const_value, method_name) + end + + # Defined as a programming convenience. No even of this type will ever + # be generated. + NONE = event_type(:PN_EVENT_NONE) + + # A timer event has occurred. + TIMER_TASK = event_type(:PN_TIMER_TASK) + + # A connection has been created. This is the first even that will ever + # be issued for a connection. + CONNECTION_INIT = event_type(:PN_CONNECTION_INIT) + # A conneciton has been bound toa transport. + CONNECTION_BOUND = event_type(:PN_CONNECTION_BOUND) + # A connection has been unbound from its transport. + CONNECTION_UNBOUND = event_type(:PN_CONNECTION_UNBOUND) + # A local connection endpoint has been opened. + CONNECTION_LOCAL_OPEN = event_type(:PN_CONNECTION_LOCAL_OPEN) + # A local connection endpoint has been closed. + CONNECTION_LOCAL_CLOSE = event_type(:PN_CONNECTION_LOCAL_CLOSE) + # A remote endpoint has opened its connection. + CONNECTION_REMOTE_OPEN = event_type(:PN_CONNECTION_REMOTE_OPEN) + # A remote endpoint has closed its connection. + CONNECTION_REMOTE_CLOSE = event_type(:PN_CONNECTION_REMOTE_CLOSE) + # A connection has been freed and any outstanding processing has been + # completed. This is the final event htat will ever be issued for a + # connection + CONNECTION_FINAL = event_type(:PN_CONNECTION_FINAL) + + # A session has been created. This is the first event that will ever be + # issues for a session. + SESSION_INIT = event_type(:PN_SESSION_INIT) + # A local session endpoint has been opened. + SESSION_LOCAL_OPEN = event_type(:PN_SESSION_LOCAL_OPEN) + # A local session endpoint has been closed. + SESSION_LOCAL_CLOSE = event_type(:PN_SESSION_LOCAL_CLOSE) + # A remote endpoint has opened its session. + SESSION_REMOTE_OPEN = event_type(:PN_SESSION_REMOTE_OPEN) + # A remote endpoint has closed its session. + SESSION_REMOTE_CLOSE = event_type(:PN_SESSION_REMOTE_CLOSE) + # A session has been freed and any outstanding processing has been + # completed. This is the final event that will ever be issued for a + # session + SESSION_FINAL = event_type(:PN_SESSION_FINAL) + + # A link has been created. This is the first event that will ever be + # issued for a link. + LINK_INIT = event_type(:PN_LINK_INIT) + # A local link endpoint has been opened. + LINK_LOCAL_OPEN = event_type(:PN_LINK_LOCAL_OPEN) + # A local link endpoint has been closed. + LINK_LOCAL_CLOSE = event_type(:PN_LINK_LOCAL_CLOSE) + # A local link endpoint has been detached. + LINK_LOCAL_DETACH = event_type(:PN_LINK_LOCAL_DETACH) + # A remote endpoint has opened its link. + LINK_REMOTE_OPEN = event_type(:PN_LINK_REMOTE_OPEN) + # A remote endpoint has closed its link. + LINK_REMOTE_CLOSE = event_type(:PN_LINK_REMOTE_CLOSE) + # A remote endpoint has detached its link. + LINK_REMOTE_DETACH = event_type(:PN_LINK_REMOTE_DETACH) + # The flow control state for a link has changed. + LINK_FLOW = event_type(:PN_LINK_FLOW) + # A link has been freed and any outstanding processing has been completed. + # This is the final event htat will ever be issued for a link. + LINK_FINAL = event_type(:PN_LINK_FINAL) + + # A delivery has been created or updated. + DELIVERY = event_type(:PN_DELIVERY) + + # A transport has new data to read and/or write. + TRANSPORT = event_type(:PN_TRANSPORT) + # Indicates that a transport error has occurred. + # @see Transport#condition To access the details of the error. + TRANSPORT_ERROR = event_type(:PN_TRANSPORT_ERROR) + # Indicates that the head of a transport has been closed. This means the + # transport will never produce more bytes for output to the network. + TRANSPORT_HEAD_CLOSED = event_type(:PN_TRANSPORT_HEAD_CLOSED) + # Indicates that the trail of a transport has been closed. This means the + # transport will never be able to process more bytes from the network. + TRANSPORT_TAIL_CLOSED = event_type(:PN_TRANSPORT_TAIL_CLOSED) + # Indicates that both the head and tail of a transport are closed. + TRANSPORT_CLOSED = event_type(:PN_TRANSPORT_CLOSED) + + SELECTABLE_INIT = event_type(:PN_SELECTABLE_INIT) + SELECTABLE_UPDATED = event_type(:PN_SELECTABLE_UPDATED) + SELECTABLE_READABLE = event_type(:PN_SELECTABLE_READABLE) + SELECTABLE_WRITABLE = event_type(:PN_SELECTABLE_WRITABLE) + SELECTABLE_EXPIRED = event_type(:PN_SELECTABLE_EXPIRED) + SELECTABLE_ERROR = event_type(:PN_SELECTABLE_ERROR) + SELECTABLE_FINAL = event_type(:PN_SELECTABLE_FINAL) + + # An Event provides notification of a state change within the protocol + # engine. + # + # Every event has a type that identifies what sort of state change has + # occurred, along with a pointer to the object whose state has changed, + # and also any associated objects. + # + # For more details on working with Event, please refer to Collector. + # + # @see Qpid::Proton::Event The list of predefined events. + # + class Event < EventBase + + # @private + include Qpid::Proton::Util::ClassWrapper + # @private + include Qpid::Proton::Util::Wrapper + + # Creates a Ruby object for the given pn_event_t. + # + # @private + def self.wrap(impl, number = nil) + return nil if impl.nil? + + result = self.fetch_instance(impl, :pn_event_attachments) + return result unless result.nil? + number = Cproton.pn_event_type(impl) if number.nil? + event = Event.new(impl, number) + return event.context if event.context.is_a? EventBase + return event + end + + # @private + def initialize(impl, number) + @impl = impl + class_name = Cproton.pn_class_name(Cproton.pn_event_class(impl)) + context = class_wrapper(class_name, Cproton.pn_event_context(impl)) + event_type = EventType.by_type(Cproton.pn_event_type(impl)) + super(class_name, context, event_type) + @type = EventType.by_type(number) + self.class.store_instance(self, :pn_event_attachments) + end + + # Notifies the handler(s) of this event. + # + # If a handler responds to the event's method then that method is invoked + # and passed the event. Otherwise, if the handler defines the + # +on_unhandled+ method, then that will be invoked instead. + # + # If the handler defines a +handlers+ method then that will be invoked and + # passed the event afterward. + # + # @example + # + # class FallbackEventHandler + # + # # since it now defines a handlers method, any event will iterate + # # through them and invoke the +dispatch+ method on each + # attr_accessor handlers + # + # def initialize + # @handlers = [] + # end + # + # # invoked for any event not otherwise handled + # def on_unhandled(event) + # puts "Unable to invoke #{event.type.method} on #{event.context}." + # end + # + # end + # + # @param handler [Object] An object which implements either the event's + # handler method or else responds to :handlers with an array of other + # handlers. + # + def dispatch(handler, type = nil) + puts "dispatching #{self} to #{handler}" + type = @type if type.nil? + #notify any and all attached handlers + if handler.respond_to?(:handlers?) && handler.handlers? + handler.handlers.each {|hndlr| self.dispatch(hndlr, type)} + end + if handler.respond_to?(type.method) + handler.__send__(type.method, self) + elsif handler.respond_to?(:on_unhandled) + handler.on_unhandled(self) + end + end + + # Returns the transport for this event. + # + # @return [Transport, nil] The transport. + # + def transport + Qpid::Proton::Transport.wrap(Cproton.pn_event_transport(@impl)) + end + + # Returns the Connection for this event. + # + # @return [Connection, nil] The connection. + # + def connection + Qpid::Proton::Connection.wrap(Cproton.pn_event_connection(@impl)) + end + + # Returns the Session for this event. + # + # @return [Session, nil] The session + # + def session + Qpid::Proton::Session.wrap(Cproton.pn_event_session(@impl)) + end + + # Returns the Link for this event. + # + # @return [Link, nil] The link. + # + def link + Qpid::Proton::Link.wrap(Cproton.pn_event_link(@impl)) + end + + # Returns the Sender, or nil if there is no Link, associated with this + # event if that link is a sender. + # + # @return [Sender, nil] The sender. + # + def sender + return self.link if !self.link.nil? && self.link.sender? + end + + # Returns the Receiver, or nil if there is no Link, associated with this + # event if that link is a receiver. + # + # @return [Receiver, nil] The receiver. + # + def receiver + return self.link if !self.link.nil? && self.link.receiver? + end + + # Returns the Delivery associated with this event. + # + # @return [Delivery, nil] The delivery. + # + def delivery + Qpid::Proton::Delivery.wrap(Cproton.pn_event_delivery(@impl)) + end + + # Sets the message. + # + # @param message [Qpid::Proton::Message] The message + # + def message=(message) + @message = message + end + + # Returns the message. + # + # @return [Qpid::Proton::Message] The message. + # + def message + @message + end + + # @private + def to_s + "#{self.type}(#{self.context})" + end + + end + + end + +end http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/766a59ec/proton-c/bindings/ruby/lib/event/event_base.rb ---------------------------------------------------------------------- diff --git a/proton-c/bindings/ruby/lib/event/event_base.rb b/proton-c/bindings/ruby/lib/event/event_base.rb new file mode 100644 index 0000000..6ae6959 --- /dev/null +++ b/proton-c/bindings/ruby/lib/event/event_base.rb @@ -0,0 +1,91 @@ +#-- +# 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. +#++ + +module Qpid::Proton::Event + + # @private + def self.dispatch(handler, method, *args) + args = args.last unless args.nil? + if handler.respond_to? method.to_sym + return handler.__send__(method, args) + elsif handler.respond_to? :on_unhandled + return handler.__send__(:on_unhandled, method, args) + end + end + + # EventBase is the foundation for creating application-specific events. + # + # @example + # + # # SCENARIO: A continuation of the example in EventType. + # # + # # An Event class is defined to handle receiving encrypted + # # data from a remote endpoint. + # + # class EncryptedDataEvent < EventBase + # def initialize(message) + # super(EncryptedDataEvent, message, + # Qpid::Proton::Event::ENCRYPTED_RECV) + # end + # end + # + # # at another point, when encrypted data is received + # msg = Qpid::Proton::Message.new + # msg.decode(link.receive(link.pending)) + # if encrypted?(msg) + # collector.put(EncryptedDataEvent.new(msg) + # end + # + # @see EventType The EventType class for how ENCRYPTED_RECV was defined. + # + class EventBase + + # Returns the name for the class associated with this event. + attr_reader :class_name + + # Returns the associated context object for the event. + attr_reader :context + + # Returns the type of the event. + attr_reader :type + + # Creates a new event with the specific class_name and context of the + # specified type. + # + # @param class_name [String] The name of the class. + # @param context [Object] The event context. + # @param type [EventType] The event type. + # + def initialize(class_name, context, type) + @class_name = class_name + @context = context + @type = type + end + + # Invokes the type-specific method on the provided handler. + # + # @param handler [Object] The handler to be notified of this event. + # + def dispatch(handler) + Qpid::Proton.dispatch(handler, @type.method, self) + end + + end + +end http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/766a59ec/proton-c/bindings/ruby/lib/event/event_type.rb ---------------------------------------------------------------------- diff --git a/proton-c/bindings/ruby/lib/event/event_type.rb b/proton-c/bindings/ruby/lib/event/event_type.rb new file mode 100644 index 0000000..aa5944d --- /dev/null +++ b/proton-c/bindings/ruby/lib/event/event_type.rb @@ -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. +#++ + +module Qpid::Proton::Event + + # Manages the association between an Event and the method which should + # process on the context object associated with an occurance of the event. + # + # Each type is identified by a unique #type value. + # + # @example + # + # # SCENARIO: A part of an application handles extracting and decrypting + # # data received from a remote endpoint. + # # + # # An EventType is created to notify handlers that such a + # # situation has occurred. + # + # ENCRYPTED_RECV = 10000 # the unique constant value for the event + # + # # create a new event type which, when it occurs, invokes a method + # # named :on_encrypted_data when a handler is notified of its occurrance + # Qpid::Proton::Event::ENCRYPTED_RECV = + # Qpid::Proton::Event::EventType.new(ENCRYPTED_RECV, :on_encrypted_data) + # + # @see EventBase EventBase for the rest of this example. + # @see Qpid::Proton::Event::Event The Event class for more details on events. + # + class EventType + + # The method to invoke on any potential handler. + attr_reader :method + attr_reader :number + + def initialize(number, method) + @number = number + @name = Cproton.pn_event_type_name(@number) + @method = method + @@types ||= {} + @@types[number] = self + end + + # @private + def to_s + @name + end + + # @private + def self.by_type(type) # :nodoc: + @@types[type] + end + + end + +end http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/766a59ec/proton-c/bindings/ruby/lib/qpid_proton.rb ---------------------------------------------------------------------- diff --git a/proton-c/bindings/ruby/lib/qpid_proton.rb b/proton-c/bindings/ruby/lib/qpid_proton.rb index 9060b54..58b95d0 100644 --- a/proton-c/bindings/ruby/lib/qpid_proton.rb +++ b/proton-c/bindings/ruby/lib/qpid_proton.rb @@ -51,6 +51,9 @@ require "codec/mapping" require "codec/data" # Event API classes +require "event/event_type" +require "event/event_base" +require "event/event" require "event/collector" # Main Proton classes --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org