qpid_proton 0.9.0 → 0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codec/data.rb +912 -0
  3. data/lib/codec/mapping.rb +169 -0
  4. data/lib/{qpid_proton/tracker.rb → core/base_handler.rb} +4 -15
  5. data/lib/core/connection.rb +328 -0
  6. data/lib/core/delivery.rb +271 -0
  7. data/lib/core/disposition.rb +158 -0
  8. data/lib/core/endpoint.rb +140 -0
  9. data/lib/{qpid_proton → core}/exceptions.rb +43 -2
  10. data/lib/core/link.rb +387 -0
  11. data/lib/core/message.rb +633 -0
  12. data/lib/core/receiver.rb +95 -0
  13. data/lib/core/sasl.rb +94 -0
  14. data/lib/core/selectable.rb +130 -0
  15. data/lib/core/sender.rb +76 -0
  16. data/lib/core/session.rb +163 -0
  17. data/lib/core/ssl.rb +164 -0
  18. data/lib/{qpid_proton/version.rb → core/ssl_details.rb} +7 -6
  19. data/lib/core/ssl_domain.rb +156 -0
  20. data/lib/core/terminus.rb +218 -0
  21. data/lib/core/transport.rb +411 -0
  22. data/lib/core/url.rb +77 -0
  23. data/lib/event/collector.rb +148 -0
  24. data/lib/event/event.rb +318 -0
  25. data/lib/event/event_base.rb +91 -0
  26. data/lib/event/event_type.rb +71 -0
  27. data/lib/handler/acking.rb +70 -0
  28. data/lib/handler/c_adaptor.rb +47 -0
  29. data/lib/handler/c_flow_controller.rb +33 -0
  30. data/lib/handler/endpoint_state_handler.rb +217 -0
  31. data/lib/handler/incoming_message_handler.rb +74 -0
  32. data/lib/handler/messaging_handler.rb +218 -0
  33. data/lib/handler/outgoing_message_handler.rb +98 -0
  34. data/lib/handler/wrapped_handler.rb +76 -0
  35. data/lib/messenger/messenger.rb +702 -0
  36. data/lib/messenger/subscription.rb +37 -0
  37. data/lib/messenger/tracker.rb +38 -0
  38. data/lib/messenger/tracker_status.rb +69 -0
  39. data/lib/qpid_proton.rb +106 -16
  40. data/lib/reactor/acceptor.rb +41 -0
  41. data/lib/reactor/backoff.rb +41 -0
  42. data/lib/reactor/connector.rb +98 -0
  43. data/lib/reactor/container.rb +272 -0
  44. data/lib/reactor/global_overrides.rb +44 -0
  45. data/lib/reactor/link_option.rb +90 -0
  46. data/lib/reactor/reactor.rb +198 -0
  47. data/lib/reactor/session_per_connection.rb +45 -0
  48. data/lib/reactor/ssl_config.rb +41 -0
  49. data/lib/reactor/task.rb +39 -0
  50. data/lib/{qpid_proton/subscription.rb → reactor/urls.rb} +12 -13
  51. data/lib/{qpid_proton → types}/array.rb +28 -29
  52. data/lib/types/described.rb +63 -0
  53. data/lib/{qpid_proton → types}/hash.rb +4 -3
  54. data/lib/types/strings.rb +62 -0
  55. data/lib/util/class_wrapper.rb +54 -0
  56. data/lib/util/condition.rb +45 -0
  57. data/lib/util/constants.rb +85 -0
  58. data/lib/util/engine.rb +82 -0
  59. data/lib/util/error_handler.rb +127 -0
  60. data/lib/util/handler.rb +41 -0
  61. data/lib/util/reactor.rb +32 -0
  62. data/lib/util/swig_helper.rb +114 -0
  63. data/lib/util/timeout.rb +50 -0
  64. data/lib/util/uuid.rb +32 -0
  65. data/lib/util/version.rb +30 -0
  66. data/lib/util/wrapper.rb +124 -0
  67. metadata +67 -21
  68. data/ext/cproton/cproton.c +0 -22196
  69. data/lib/qpid_proton/data.rb +0 -788
  70. data/lib/qpid_proton/described.rb +0 -66
  71. data/lib/qpid_proton/exception_handling.rb +0 -127
  72. data/lib/qpid_proton/filters.rb +0 -67
  73. data/lib/qpid_proton/mapping.rb +0 -170
  74. data/lib/qpid_proton/message.rb +0 -621
  75. data/lib/qpid_proton/messenger.rb +0 -702
  76. data/lib/qpid_proton/selectable.rb +0 -126
  77. data/lib/qpid_proton/strings.rb +0 -65
  78. data/lib/qpid_proton/tracker_status.rb +0 -73
@@ -17,9 +17,9 @@
17
17
  # under the License.
18
18
  #++
19
19
 
20
- module Qpid # :nodoc:
20
+ module Qpid
21
21
 
22
- module Proton # :nodoc:
22
+ module Proton
23
23
 
24
24
  module Error
25
25
 
@@ -80,6 +80,47 @@ module Qpid # :nodoc:
80
80
  class InProgressError < ProtonError
81
81
  end
82
82
 
83
+ # Raised by instances of Transport.
84
+ #
85
+ class TransportError < ProtonError
86
+ end
87
+
88
+ # Raised by instances of SASL
89
+ #
90
+ class SASLError < TransportError
91
+ end
92
+
93
+ # Raised by Session.
94
+ #
95
+ class SessionError < ProtonError
96
+ end
97
+
98
+ # Raised when an attempt is made to change an attribute that is read-only.
99
+ #
100
+ class AttributeError < ProtonError
101
+ end
102
+
103
+ # Raised by link components.
104
+ #
105
+ class LinkError < ProtonError
106
+ end
107
+
108
+ class SSLError < TransportError
109
+ end
110
+
111
+ class SSLUnavailableError < SSLError
112
+ end
113
+
114
+ # Raised when a message is rejected.
115
+ #
116
+ class Reject < ProtonError
117
+ end
118
+
119
+ # Raised when a message is released.
120
+ #
121
+ class Release < ProtonError
122
+ end
123
+
83
124
  end
84
125
 
85
126
  end
data/lib/core/link.rb ADDED
@@ -0,0 +1,387 @@
1
+ #--
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #++
19
+
20
+ module Qpid::Proton
21
+
22
+ # The base for both Sender and Receiver, providing common functionality
23
+ # between both ends.
24
+ #
25
+ # A Link has a single parent Qpid::Proton::Session instance.
26
+ #
27
+ class Link < Endpoint
28
+
29
+ # The sender will send all deliveries initially unsettled.
30
+ SND_UNSETTLED = Cproton::PN_SND_UNSETTLED
31
+ # The sender will send all deliveries settled to the receiver.
32
+ SND_SETTLED = Cproton::PN_SND_SETTLED
33
+ # The sender may send a mixture of settled and unsettled deliveries.
34
+ SND_MIXED = Cproton::PN_SND_MIXED
35
+
36
+ # The receiver will settle deliveries regardless of what the sender does.
37
+ RCV_FIRST = Cproton::PN_RCV_FIRST
38
+ # The receiver will only settle deliveries after the sender settles.
39
+ RCV_SECOND = Cproton::PN_RCV_SECOND
40
+
41
+ # @private
42
+ include Util::SwigHelper
43
+
44
+ # @private
45
+ PROTON_METHOD_PREFIX = "pn_link"
46
+
47
+ # @!attribute [r] state
48
+ #
49
+ # Returns the endpoint state flags.
50
+ #
51
+ proton_caller :state
52
+
53
+ # @!method open
54
+ #
55
+ # Opens the link. Once this operation has completed, the state flag will be
56
+ # set.
57
+ #
58
+ # @see Endpoint::LOCAL_ACTIVE
59
+ proton_caller :open
60
+
61
+ # @!method close
62
+ #
63
+ # Closes the link.
64
+ #
65
+ # Once this operation has completed, the state flag will be set.
66
+ # This may be called without first calling #open, which is the equivalent to
67
+ # calling #open and then #close.
68
+ #
69
+ # @see Endpoint::LOCAL_CLOSED
70
+ proton_caller :close
71
+
72
+ # @!method detach
73
+ #
74
+ # Detaches the link.
75
+ proton_caller :detach
76
+
77
+ # Advance the current delivery to the next on the link.
78
+ #
79
+ # For sending links, this operation is used to finish sending message data
80
+ # for the current outgoing delivery and move on to the next outgoing
81
+ # delivery (if any).
82
+ #
83
+ # For receiving links, this operatoin is used to finish accessing message
84
+ # data from the current incoming delivery and move on to the next incoming
85
+ # delivery (if any).
86
+ #
87
+ # @return [Boolean] True if the current delivery was changed.
88
+ #
89
+ # @see #current
90
+ #
91
+ proton_caller :advance
92
+
93
+ proton_caller :unsettled
94
+
95
+ # @!attribute [r] credit
96
+ #
97
+ # Returns the credit balance for a link.
98
+ #
99
+ # Links use a credit based flow control scheme. Every receiver maintains a
100
+ # credit balance that corresponds to the number of deliveries that the
101
+ # receiver can accept at any given moment.
102
+ #
103
+ # As more capacity becomes available at the receiver, it adds credit to this
104
+ # balance and communicates the new balance to the sender. Whenever a
105
+ # delivery is sent/received, the credit balance maintained by the link is
106
+ # decremented by one.
107
+ #
108
+ # Once the credit balance at the sender reaches zero, the sender must pause
109
+ # sending until more credit is obtained from the receiver.
110
+ #
111
+ # NOte that a sending link may still be used to send deliveries eve if
112
+ # credit reaches zero. However those deliveries will end up being buffer by
113
+ # the link until enough credit is obtained from the receiver to send them
114
+ # over the wire. In this case the balance reported will go negative.
115
+ #
116
+ # @return [Fixnum] The credit balance.
117
+ #
118
+ # @see #flow
119
+ #
120
+ proton_caller :credit
121
+
122
+ # @!attribute [r] remote_credit
123
+ #
124
+ # Returns the remote view of the credit.
125
+ #
126
+ # The remote view of the credit for a link differs from the local view of
127
+ # credit for a link by the number of queued deliveries. In other words,
128
+ # remote credit is defined as credit - queued.
129
+ #
130
+ # @see #queued
131
+ # @see #credit
132
+ #
133
+ # @return [Fixnum] The remove view of the credit.
134
+ #
135
+ proton_caller :remote_credit
136
+
137
+ # @!attribute [r] available
138
+ #
139
+ # Returns the available deliveries hint for a link.
140
+ #
141
+ # The available count for a link provides a hint as to the number of
142
+ # deliveries that might be able to be sent if sufficient credit were issued
143
+ # by the receiving link endpoint.
144
+ #
145
+ # @return [Fixnum] The available deliveries hint.
146
+ #
147
+ # @see Sender#offered
148
+ #
149
+ proton_caller :available
150
+
151
+ # @!attribute [r] queued
152
+ #
153
+ # Returns the number of queued deliveries for a link.
154
+ #
155
+ # Links may queue deliveries for a number of reasons. For example, there may
156
+ # be insufficient credit to send them to the receiver, or they simply may
157
+ # not have yet had a chance to be written to the wire.
158
+ #
159
+ # @return [Fixnum] The number of queued deliveries.
160
+ #
161
+ # @see #credit
162
+ #
163
+ proton_caller :queued
164
+
165
+ # @!attribute [r] name
166
+ #
167
+ # Returns the name of the link.
168
+ #
169
+ # @return [String] The name.
170
+ #
171
+ proton_caller :name
172
+
173
+ # @!attribute [r] sender?
174
+ #
175
+ # Returns if the link is a sender.
176
+ #
177
+ # @return [Boolean] True if the link is a sender.
178
+ #
179
+ proton_reader :sender, :is_or_get => :is
180
+
181
+ # @!attribute [r] receiver?
182
+ #
183
+ # Returns if the link is a receiver.
184
+ #
185
+ # @return [Boolean] True if the link is a receiver.
186
+ #
187
+ proton_reader :receiver, :is_or_get => :is
188
+
189
+ # @private
190
+ proton_reader :attachments
191
+
192
+ # Drains excess credit.
193
+ #
194
+ # When a link is in drain mode, the sender must use all excess credit
195
+ # immediately and release any excess credit back to the receiver if there
196
+ # are no deliveries available to send.
197
+ #
198
+ # When invoked on a Sender that is in drain mode, this operation will
199
+ # release all excess credit back to the receiver and return the number of
200
+ # credits released back to the sender. If the link is not in drain mode,
201
+ # this operation is a noop.
202
+ #
203
+ # When invoked on a Receiver, this operation will return and reset the
204
+ # number of credits the sender has released back to it.
205
+ #
206
+ # @return [Fixnum] The number of credits drained.
207
+ #
208
+ proton_caller :drained
209
+
210
+ # @private
211
+ include Util::Wrapper
212
+
213
+ # @private
214
+ def self.wrap(impl)
215
+ return nil if impl.nil?
216
+
217
+ result = self.fetch_instance(impl, :pn_link_attachments)
218
+ return result unless result.nil?
219
+ if Cproton.pn_link_is_sender(impl)
220
+ return Sender.new(impl)
221
+ elsif Cproton.pn_link_is_receiver(impl)
222
+ return Receiver.new(impl)
223
+ end
224
+ end
225
+
226
+ # @private
227
+ def initialize(impl)
228
+ @impl = impl
229
+ self.class.store_instance(self, :pn_link_attachments)
230
+ end
231
+
232
+ # Returns additional error information.
233
+ #
234
+ # Whenever a link operation fails (i.e., returns an error code) additional
235
+ # error details can be obtained from this method. Ther error object that is
236
+ # returned may also be used to clear the error condition.
237
+ #
238
+ # @return [Error] The error.
239
+ #
240
+ def error
241
+ Cproton.pn_link_error(@impl)
242
+ end
243
+
244
+ # Returns the next link that matches the given state mask.
245
+ #
246
+ # @param state_mask [Fixnum] The state mask.
247
+ #
248
+ # @return [Sender, Receiver] The next link.
249
+ #
250
+ def next(state_mask)
251
+ return Link.wrap(Cproton.pn_link_next(@impl, state_mask))
252
+ end
253
+
254
+ # Returns the locally defined source terminus.
255
+ #
256
+ # @return [Terminus] The terminus
257
+ def source
258
+ Terminus.new(Cproton.pn_link_source(@impl))
259
+ end
260
+
261
+ # Returns the locally defined target terminus.
262
+ #
263
+ # @return [Terminus] The terminus.
264
+ #
265
+ def target
266
+ Terminus.new(Cproton.pn_link_target(@impl))
267
+ end
268
+
269
+ # Returns a representation of the remotely defined source terminus.
270
+ #
271
+ # @return [Terminus] The terminus.
272
+ #
273
+ def remote_source
274
+ Terminus.new(Cproton.pn_link_remote_source(@impl))
275
+ end
276
+
277
+ # Returns a representation of the remotely defined target terminus.
278
+ #
279
+ # @return [Terminus] The terminus.
280
+ #
281
+ def remote_target
282
+ Terminus.new(Cproton.pn_link_remote_target(@impl))
283
+ end
284
+
285
+ # Returns the parent session.
286
+ #
287
+ # @return [Session] The session.
288
+ #
289
+ def session
290
+ Session.wrap(Cproton.pn_link_session(@impl))
291
+ end
292
+
293
+ # Returns the parent connection.
294
+ #
295
+ # @return [Connection] The connection.
296
+ #
297
+ def connection
298
+ self.session.connection
299
+ end
300
+
301
+ # Returns the parent delivery.
302
+ #
303
+ # @return [Delivery] The delivery.
304
+ #
305
+ def delivery(tag)
306
+ Delivery.new(Cproton.pn_delivery(@impl, tag))
307
+ end
308
+
309
+ # Returns the current delivery.
310
+ #
311
+ # Each link maintains a sequence of deliveries in the order they were
312
+ # created, along with a reference to the *current* delivery. All send and
313
+ # receive operations on a link take place on the *current* delivery. If a
314
+ # link has no current delivery, the current delivery is automatically
315
+ # pointed to the *next* delivery created on the link.
316
+ #
317
+ # Once initialized, the current delivery remains the same until it is
318
+ # changed by advancing, or until it is settled.
319
+ #
320
+ # @see #next
321
+ # @see Delivery#settle
322
+ #
323
+ # @return [Delivery] The current delivery.
324
+ #
325
+ def current
326
+ Delivery.wrap(Cproton.pn_link_current(@impl))
327
+ end
328
+
329
+ # Sets the local sender settle mode.
330
+ #
331
+ # @param mode [Fixnum] The settle mode.
332
+ #
333
+ # @see #SND_UNSETTLED
334
+ # @see #SND_SETTLED
335
+ # @see #SND_MIXED
336
+ #
337
+ def snd_settle_mode=(mode)
338
+ Cproton.pn_link_set_snd_settle_mode(@impl, mode)
339
+ end
340
+
341
+ # Returns the local sender settle mode.
342
+ #
343
+ # @return [Fixnum] The local sender settle mode.
344
+ #
345
+ # @see #snd_settle_mode
346
+ #
347
+ def snd_settle_mode
348
+ Cproton.pn_link_snd_settle_mode(@impl)
349
+ end
350
+
351
+ # Sets the local receiver settle mode.
352
+ #
353
+ # @param mode [Fixnum] The settle mode.
354
+ #
355
+ # @see #RCV_FIRST
356
+ # @see #RCV_SECOND
357
+ #
358
+ def rcv_settle_mode=(mode)
359
+ Cproton.pn_link_set_rcv_settle_mode(@impl, mode)
360
+ end
361
+
362
+ # Returns the local receiver settle mode.
363
+ #
364
+ # @return [Fixnum] The local receiver settle mode.
365
+ #
366
+ def rcv_settle_mode
367
+ Cproton.pn_link_rcv_settle_mode(@impl)
368
+ end
369
+
370
+ # @private
371
+ def _local_condition
372
+ Cproton.pn_link_condition(@impl)
373
+ end
374
+
375
+ # @private
376
+ def _remote_condition
377
+ Cproton.pn_link_remote_condition(@impl)
378
+ end
379
+
380
+ def ==(other)
381
+ other.respond_to?(:impl) &&
382
+ (Cproton.pni_address_of(other.impl) == Cproton.pni_address_of(@impl))
383
+ end
384
+
385
+ end
386
+
387
+ end
@@ -0,0 +1,633 @@
1
+ #--
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #++
19
+
20
+ module Qpid::Proton
21
+
22
+ # A Message represents an addressable quantity of data.
23
+ #
24
+ # ==== Message Body
25
+ #
26
+ # The message body can be set using the #body= method. The message will
27
+ # then attempt to determine how exactly to encode the content.
28
+ #
29
+ # ==== Examples
30
+ #
31
+ # To create a message for sending:
32
+ #
33
+ # # send a simple text message
34
+ # msg = Qpid::Proton::Message.new
35
+ # msg.body = "STATE: update"
36
+ #
37
+ # # send a binary chunk of data
38
+ # data = File.binread("/home/qpid/binfile.tar.gz")
39
+ # msg = Qpid::Proton::Message.new
40
+ # msg.body = Qpid::Proton::BinaryString.new(data)
41
+ #
42
+ class Message
43
+
44
+ # @private
45
+ def proton_send(sender, tag = nil)
46
+ dlv = sender.delivery(tag || sender.delivery_tag)
47
+ encoded = self.encode
48
+ sender.stream(encoded)
49
+ sender.advance
50
+ dlv.settle if sender.snd_settle_mode == Link::SND_SETTLED
51
+ return dlv
52
+ end
53
+
54
+ # Decodes a message from supplied AMQP data and returns the number
55
+ # of bytes consumed.
56
+ #
57
+ # ==== Options
58
+ #
59
+ # * encoded - the encoded data
60
+ #
61
+ def decode(encoded)
62
+ check(Cproton.pn_message_decode(@impl, encoded, encoded.length))
63
+
64
+ post_decode
65
+ end
66
+
67
+ def post_decode # :nodoc:
68
+ # decode elements from the message
69
+ @properties = {}
70
+ props = Codec::Data.new(Cproton::pn_message_properties(@impl))
71
+ if props.next
72
+ @properties = props.type.get(props)
73
+ end
74
+ @instructions = nil
75
+ insts = Codec::Data.new(Cproton::pn_message_instructions(@impl))
76
+ if insts.next
77
+ @instructions = insts.type.get(insts)
78
+ end
79
+ @annotations = nil
80
+ annts = Codec::Data.new(Cproton::pn_message_annotations(@impl))
81
+ if annts.next
82
+ @annotations = annts.type.get(annts)
83
+ end
84
+ @body = nil
85
+ body = Codec::Data.new(Cproton::pn_message_body(@impl))
86
+ if body.next
87
+ @body = body.type.get(body)
88
+ end
89
+ end
90
+
91
+ # Encodes the message.
92
+ def encode
93
+ pre_encode
94
+ size = 16
95
+ loop do
96
+ error, data = Cproton::pn_message_encode(@impl, size)
97
+ if error == Qpid::Proton::Error::OVERFLOW
98
+ size *= 2
99
+ else
100
+ check(error)
101
+ return data
102
+ end
103
+ end
104
+ end
105
+
106
+ def pre_encode # :nodoc:
107
+ # encode elements from the message
108
+ props = Codec::Data.new(Cproton::pn_message_properties(@impl))
109
+ props.clear
110
+ Codec::Mapping.for_class(@properties.class).put(props, @properties) unless @properties.empty?
111
+ insts = Codec::Data.new(Cproton::pn_message_instructions(@impl))
112
+ insts.clear
113
+ if !@instructions.nil?
114
+ mapping = Codec::Mapping.for_class(@instructions.class)
115
+ mapping.put(insts, @instructions)
116
+ end
117
+ annts = Codec::Data.new(Cproton::pn_message_annotations(@impl))
118
+ annts.clear
119
+ if !@annotations.nil?
120
+ mapping = Codec::Mapping.for_class(@annotations.class)
121
+ mapping.put(annts, @annotations, :keys => :SYMBOL)
122
+ end
123
+ body = Codec::Data.new(Cproton::pn_message_body(@impl))
124
+ body.clear
125
+ if !@body.nil?
126
+ mapping = Codec::Mapping.for_class(@body.class)
127
+ mapping.put(body, @body)
128
+ end
129
+ end
130
+
131
+ # Creates a new +Message+ instance.
132
+ def initialize
133
+ @impl = Cproton.pn_message
134
+ ObjectSpace.define_finalizer(self, self.class.finalize!(@impl))
135
+ @properties = {}
136
+ @instructions = {}
137
+ @annotations = {}
138
+ @body = nil
139
+ end
140
+
141
+ def to_s
142
+ tmp = Cproton.pn_string("")
143
+ Cproton.pn_inspect(@impl, tmp)
144
+ result = Cproton.pn_string_get(tmp)
145
+ Cproton.pn_free(tmp)
146
+ return result
147
+ end
148
+
149
+ # Invoked by garbage collection to clean up resources used
150
+ # by the underlying message implementation.
151
+ def self.finalize!(impl) # :nodoc:
152
+ proc {
153
+ Cproton.pn_message_free(impl)
154
+ }
155
+ end
156
+
157
+ # Returns the underlying message implementation.
158
+ def impl # :nodoc:
159
+ @impl
160
+ end
161
+
162
+ # Clears the state of the +Message+. This allows a single instance of
163
+ # +Message+ to be reused.
164
+ #
165
+ def clear
166
+ Cproton.pn_message_clear(@impl)
167
+ @properties.clear unless @properties.nil?
168
+ @instructions.clear unless @instructions.nil?
169
+ @annotations.clear unless @annotations.nil?
170
+ @body = nil
171
+ end
172
+
173
+ # Returns the most recent error number.
174
+ #
175
+ def errno
176
+ Cproton.pn_message_errno(@impl)
177
+ end
178
+
179
+ # Returns the most recent error message.
180
+ #
181
+ def error
182
+ Cproton.pn_error_text(Cproton.pn_message_error(@impl))
183
+ end
184
+
185
+ # Returns whether there is currently an error reported.
186
+ #
187
+ def error?
188
+ !Cproton.pn_message_errno(@impl).zero?
189
+ end
190
+
191
+ # Sets the durable flag.
192
+ #
193
+ # See ::durable for more details on message durability.
194
+ #
195
+ # ==== Options
196
+ #
197
+ # * state - the durable state
198
+ #
199
+ def durable=(state)
200
+ raise TypeError.new("state cannot be nil") if state.nil?
201
+ Cproton.pn_message_set_durable(@impl, state)
202
+ end
203
+
204
+ # Returns the durable property.
205
+ #
206
+ # The durable property indicates that the emessage should be held durably
207
+ # by any intermediaries taking responsibility for the message.
208
+ #
209
+ # ==== Examples
210
+ #
211
+ # msg = Qpid::Proton::Message.new
212
+ # msg.durable = true
213
+ #
214
+ def durable
215
+ Cproton.pn_message_is_durable(@impl)
216
+ end
217
+
218
+ # Sets the priority.
219
+ #
220
+ # +NOTE:+ Priority values are limited to the range [0,255].
221
+ #
222
+ # ==== Options
223
+ #
224
+ # * priority - the priority value
225
+ #
226
+ def priority=(priority)
227
+ raise TypeError.new("invalid priority: #{priority}") if priority.nil? || !([Float, Fixnum].include?(priority.class))
228
+ raise RangeError.new("priority out of range: #{priority}") if ((priority > 255) || (priority < 0))
229
+ Cproton.pn_message_set_priority(@impl, priority.floor)
230
+ end
231
+
232
+ # Returns the priority.
233
+ #
234
+ def priority
235
+ Cproton.pn_message_get_priority(@impl)
236
+ end
237
+
238
+ # Sets the time-to-live for the message.
239
+ #
240
+ # ==== Options
241
+ #
242
+ # * time - the time in milliseconds
243
+ #
244
+ def ttl=(time)
245
+ raise TypeError.new("invalid ttl: #{time}") if time.nil? || !([Float, Fixnum].include?(time.class))
246
+ raise RangeError.new("time out of range: #{time}") if ((time < 0))
247
+ Cproton.pn_message_set_ttl(@impl, time.floor)
248
+ end
249
+
250
+ # Returns the time-to-live, in milliseconds.
251
+ #
252
+ def ttl
253
+ Cproton.pn_message_get_ttl(@impl)
254
+ end
255
+
256
+ # Sets whether this is the first time the message was acquired.
257
+ #
258
+ # See ::first_acquirer? for more details.
259
+ #
260
+ # ==== Options
261
+ #
262
+ # * state - true if claiming the message
263
+ #
264
+ def first_acquirer=(state)
265
+ raise TypeError.new("invalid state: #{state}") if state.nil? || !([TrueClass, FalseClass].include?(state.class))
266
+ Cproton.pn_message_set_first_acquirer(@impl, state)
267
+ end
268
+
269
+ # Sets the delivery count for the message.
270
+ #
271
+ # See ::delivery_count for more details.
272
+ #
273
+ # ==== Options
274
+ #
275
+ # * count - the delivery count
276
+ #
277
+ def delivery_count=(count)
278
+ raise ::ArgumentError.new("invalid count: #{count}") if count.nil? || !([Float, Fixnum].include?(count.class))
279
+ raise RangeError.new("count out of range: #{count}") if count < 0
280
+
281
+ Cproton.pn_message_set_delivery_count(@impl, count.floor)
282
+ end
283
+
284
+ # Returns the delivery count for the message.
285
+ #
286
+ # This is the number of delivery attempts for the given message.
287
+ #
288
+ def delivery_count
289
+ Cproton.pn_message_get_delivery_count(@impl)
290
+ end
291
+
292
+ # Returns whether this is the first acquirer.
293
+ #
294
+ #
295
+ def first_acquirer?
296
+ Cproton.pn_message_is_first_acquirer(@impl)
297
+ end
298
+
299
+ # Sets the message id.
300
+ #
301
+ # ==== Options
302
+ #
303
+ # * id = the id
304
+ #
305
+ def id=(id)
306
+ Cproton.pn_message_set_id(@impl, id)
307
+ end
308
+
309
+ # Returns the message id.
310
+ #
311
+ def id
312
+ Cproton.pn_message_get_id(@impl)
313
+ end
314
+
315
+ # Sets the user id.
316
+ #
317
+ # ==== Options
318
+ #
319
+ # * id - the user id
320
+ #
321
+ def user_id=(id)
322
+ Cproton.pn_message_set_user_id(@impl, id)
323
+ end
324
+
325
+ # Returns the user id.
326
+ #
327
+ def user_id
328
+ Cproton.pn_message_get_user_id(@impl)
329
+ end
330
+
331
+ # Sets the destination address.
332
+ #
333
+ # ==== Options
334
+ #
335
+ # * address - the address
336
+ #
337
+ def address=(address)
338
+ Cproton.pn_message_set_address(@impl, address)
339
+ end
340
+
341
+ # Returns the destination address.
342
+ #
343
+ def address
344
+ Cproton.pn_message_get_address(@impl)
345
+ end
346
+
347
+ # Sets the subject.
348
+ #
349
+ # ==== Options
350
+ #
351
+ # * subject - the subject
352
+ #
353
+ def subject=(subject)
354
+ Cproton.pn_message_set_subject(@impl, subject)
355
+ end
356
+
357
+ # Returns the subject
358
+ #
359
+ def subject
360
+ Cproton.pn_message_get_subject(@impl)
361
+ end
362
+
363
+ # Sets the reply-to address.
364
+ #
365
+ # ==== Options
366
+ #
367
+ # * address - the reply-to address
368
+ #
369
+ def reply_to=(address)
370
+ Cproton.pn_message_set_reply_to(@impl, address)
371
+ end
372
+
373
+ # Returns the reply-to address
374
+ #
375
+ def reply_to
376
+ Cproton.pn_message_get_reply_to(@impl)
377
+ end
378
+
379
+ # Sets the correlation id.
380
+ #
381
+ # ==== Options
382
+ #
383
+ # * id - the correlation id
384
+ #
385
+ def correlation_id=(id)
386
+ Cproton.pn_message_set_correlation_id(@impl, id)
387
+ end
388
+
389
+ # Returns the correlation id.
390
+ #
391
+ def correlation_id
392
+ Cproton.pn_message_get_correlation_id(@impl)
393
+ end
394
+
395
+ # Sets the content type.
396
+ #
397
+ # ==== Options
398
+ #
399
+ # * content_type - the content type
400
+ #
401
+ def content_type=(content_type)
402
+ Cproton.pn_message_set_content_type(@impl, content_type)
403
+ end
404
+
405
+ # Returns the content type
406
+ #
407
+ def content_type
408
+ Cproton.pn_message_get_content_type(@impl)
409
+ end
410
+
411
+ # Sets the message content.
412
+ #
413
+ # *WARNING:* This method has been deprecated. Please use #body= instead to
414
+ # set the content of a message.
415
+ #
416
+ # ==== Options
417
+ #
418
+ # * content - the content
419
+ #
420
+ def content=(content)
421
+ Cproton.pn_message_load(@impl, content)
422
+ end
423
+
424
+ # Returns the message content.
425
+ #
426
+ # *WARNING:* This method has been deprecated. Please use #body instead to
427
+ # retrieve the content of a message.
428
+ #
429
+ def content
430
+ size = 16
431
+ loop do
432
+ result = Cproton.pn_message_save(@impl, size)
433
+ error = result[0]
434
+ data = result[1]
435
+ if error == Qpid::Proton::Error::OVERFLOW
436
+ size = size * 2
437
+ else
438
+ check(error)
439
+ return data
440
+ end
441
+ end
442
+ end
443
+
444
+ # Sets the content encoding type.
445
+ #
446
+ # ==== Options
447
+ #
448
+ # * encoding - the content encoding
449
+ #
450
+ def content_encoding=(encoding)
451
+ Cproton.pn_message_set_content_encoding(@impl, encoding)
452
+ end
453
+
454
+ # Returns the content encoding type.
455
+ #
456
+ def content_encoding
457
+ Cproton.pn_message_get_content_encoding(@impl)
458
+ end
459
+
460
+ # Sets the expiration time.
461
+ #
462
+ # ==== Options
463
+ #
464
+ # * time - the expiry time
465
+ #
466
+ def expires=(time)
467
+ raise TypeError.new("invalid expiry time: #{time}") if time.nil?
468
+ raise ::ArgumentError.new("expiry time cannot be negative: #{time}") if time < 0
469
+ Cproton.pn_message_set_expiry_time(@impl, time)
470
+ end
471
+
472
+ # Returns the expiration time.
473
+ #
474
+ def expires
475
+ Cproton.pn_message_get_expiry_time(@impl)
476
+ end
477
+
478
+ # Sets the creation time.
479
+ #
480
+ # ==== Options
481
+ #
482
+ # * time - the creation time
483
+ #
484
+ def creation_time=(time)
485
+ raise TypeError.new("invalid time: #{time}") if time.nil?
486
+ raise ::ArgumentError.new("time cannot be negative") if time < 0
487
+ Cproton.pn_message_set_creation_time(@impl, time)
488
+ end
489
+
490
+ # Returns the creation time.
491
+ #
492
+ def creation_time
493
+ Cproton.pn_message_get_creation_time(@impl)
494
+ end
495
+
496
+ # Sets the group id.
497
+ #
498
+ # ==== Options
499
+ #
500
+ # * id - the group id
501
+ #
502
+ def group_id=(id)
503
+ Cproton.pn_message_set_group_id(@impl, id)
504
+ end
505
+
506
+ # Returns the group id.
507
+ #
508
+ def group_id
509
+ Cproton.pn_message_get_group_id(@impl)
510
+ end
511
+
512
+ # Sets the group sequence number.
513
+ #
514
+ # ==== Options
515
+ #
516
+ # * seq - the sequence number
517
+ #
518
+ def group_sequence=(seq)
519
+ raise TypeError.new("invalid seq: #{seq}") if seq.nil?
520
+ Cproton.pn_message_set_group_sequence(@impl, seq)
521
+ end
522
+
523
+ # Returns the group sequence number.
524
+ #
525
+ def group_sequence
526
+ Cproton.pn_message_get_group_sequence(@impl)
527
+ end
528
+
529
+ # Sets the reply-to group id.
530
+ #
531
+ # ==== Options
532
+ #
533
+ # * id - the id
534
+ #
535
+ def reply_to_group_id=(id)
536
+ Cproton.pn_message_set_reply_to_group_id(@impl, id)
537
+ end
538
+
539
+ # Returns the reply-to group id.
540
+ #
541
+ def reply_to_group_id
542
+ Cproton.pn_message_get_reply_to_group_id(@impl)
543
+ end
544
+
545
+ # Returns the list of property names for associated with this message.
546
+ #
547
+ # ==== Examples
548
+ #
549
+ # msg.properties.each do |name|
550
+ # end
551
+ #
552
+ def properties
553
+ @properties
554
+ end
555
+
556
+ # Replaces the entire set of properties with the specified hash.
557
+ #
558
+ def properties=(properties)
559
+ @properties = properties
560
+ end
561
+
562
+ # Assigns the value given to the named property.
563
+ #
564
+ # ==== Arguments
565
+ #
566
+ # * name - the property name
567
+ # * value - the property value
568
+ #
569
+ def []=(name, value)
570
+ @properties[name] = value
571
+ end
572
+
573
+ # Retrieves the value for the specified property name. If not found, then
574
+ # it returns nil.
575
+ #
576
+ def [](name)
577
+ @properties[name]
578
+ end
579
+
580
+ # Deletes the named property.
581
+ #
582
+ def delete_property(name)
583
+ @properties.delete(name)
584
+ end
585
+
586
+ # Returns the instructions for this message.
587
+ #
588
+ def instructions
589
+ @instructions
590
+ end
591
+
592
+ # Assigns instructions to this message.
593
+ #
594
+ def instructions=(instr)
595
+ @instructions = instr
596
+ end
597
+
598
+ # Returns the annotations for this message.
599
+ #
600
+ def annotations
601
+ @annotations
602
+ end
603
+
604
+ # Assigns annotations to this message.
605
+ #
606
+ def annotations=(annotations)
607
+ @annotations = annotations
608
+ end
609
+
610
+ # Returns the body property of the message.
611
+ #
612
+ def body
613
+ @body
614
+ end
615
+
616
+ # Assigns a new value to the body of the message.
617
+ #
618
+ def body=(body)
619
+ @body = body
620
+ end
621
+
622
+ private
623
+
624
+ def check(err) # :nodoc:
625
+ if err < 0
626
+ raise DataError, "[#{err}]: #{Cproton.pn_message_error(@data)}"
627
+ else
628
+ return err
629
+ end
630
+ end
631
+ end
632
+
633
+ end