appengine-apis 0.0.8 → 0.0.9

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.
@@ -6,6 +6,7 @@ lib/appengine-apis.rb
6
6
  lib/appengine-apis/apiproxy.rb
7
7
  lib/appengine-apis/datastore.rb
8
8
  lib/appengine-apis/datastore_types.rb
9
+ lib/appengine-apis/labs/taskqueue.rb
9
10
  lib/appengine-apis/local_boot.rb
10
11
  lib/appengine-apis/logger.rb
11
12
  lib/appengine-apis/mail.rb
@@ -15,6 +16,8 @@ lib/appengine-apis/sdk.rb
15
16
  lib/appengine-apis/testing.rb
16
17
  lib/appengine-apis/urlfetch.rb
17
18
  lib/appengine-apis/users.rb
19
+ lib/appengine-apis/xmpp.rb
20
+ lib/appengine-apis/tempfile.rb
18
21
  script/console
19
22
  script/destroy
20
23
  script/generate
@@ -25,6 +28,8 @@ spec/mail_spec.rb
25
28
  spec/memcache_spec.rb
26
29
  spec/spec.opts
27
30
  spec/spec_helper.rb
31
+ spec/taskqueue_spec.rb
28
32
  spec/urlfetch_spec.rb
29
33
  spec/users_spec.rb
34
+ spec/xmpp_spec.rb
30
35
  tasks/rspec.rake
@@ -22,6 +22,8 @@ See these classes for an overview of each API:
22
22
  - AppEngine::Memcache
23
23
  - AppEngine::URLFetch
24
24
  - AppEngine::Datastore
25
+ - AppEngine::XMPP
26
+ - AppEngine::Labs::TaskQueue
25
27
 
26
28
  Unless you're implementing your own ORM, you probably want to use the
27
29
  DataMapper API instead of the lower level AppEngine::Datastore API.
@@ -19,5 +19,5 @@ $:.unshift(File.dirname(__FILE__)) unless
19
19
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
20
20
 
21
21
  module AppEngine
22
- VERSION = '0.0.8'
22
+ VERSION = '0.0.9'
23
23
  end
@@ -236,6 +236,21 @@ module Datastore
236
236
  raise TransactionFailed
237
237
  end
238
238
 
239
+ # call-seq:
240
+ # Datastore.allocate_ids(kind, num)
241
+ # Datastore.allocate_ids(parent, kind, num)
242
+ #
243
+ # Ids are allocated within a namespace defined by a parent key and a kind.
244
+ # This method allocates a contiguous range of unique ids of size num
245
+ # within the namespace defined by the given parent key and the given kind.
246
+ #
247
+ # Returns a KeyRange representing the range of allocated ids.
248
+ def allocate_ids(*args)
249
+ convert_exceptions do
250
+ @@db.allocate_ids(*args)
251
+ end
252
+ end
253
+
239
254
  def extract_tx(args) # :nodoc:
240
255
  tx = :none
241
256
  keys = args[0]
@@ -406,8 +421,8 @@ module Datastore
406
421
  end
407
422
 
408
423
  # Returns the number of entities that currently match this query.
409
- def count
410
- pquery.count
424
+ def count(transaction=:current)
425
+ pquery(transaction).count_entities
411
426
  end
412
427
 
413
428
  # Retrieves the one and only result for the {@code Query}.
@@ -417,9 +432,9 @@ module Datastore
417
432
  #
418
433
  # Returns the single, matching result, or nil if no entities match
419
434
  #
420
- def entity
435
+ def entity(transaction=:current)
421
436
  Datastore.convert_exceptions do
422
- pquery.as_single_entity
437
+ pquery(transaction).as_single_entity
423
438
  end
424
439
  end
425
440
 
@@ -429,9 +444,9 @@ module Datastore
429
444
  #
430
445
  # See #convert_options for supported options
431
446
  def each(options={}, &proc) # :yields: entity
432
- options = convert_options(options)
447
+ transaction, options = convert_options(options)
433
448
  Datastore.convert_exceptions do
434
- pquery.as_iterator(options).each(&proc)
449
+ pquery(transaction).as_iterator(options).each(&proc)
435
450
  end
436
451
  end
437
452
 
@@ -440,9 +455,9 @@ module Datastore
440
455
  # See #convert_options for supported options
441
456
  #
442
457
  def iterator(options={})
443
- options = convert_options(options)
458
+ transaction, options = convert_options(options)
444
459
  Datastore.convert_exceptions do
445
- pquery.as_iterator(options)
460
+ pquery(transaction).as_iterator(options)
446
461
  end
447
462
  end
448
463
 
@@ -451,17 +466,21 @@ module Datastore
451
466
  # datastore.
452
467
  #
453
468
  def fetch(options={})
454
- options = convert_options(options)
469
+ transaction, options = convert_options(options)
455
470
  Datastore.convert_exceptions do
456
- pquery.as_list(options)
471
+ pquery(transaction).as_list(options)
457
472
  end
458
473
  end
459
474
 
460
475
  # Returns a Java.ComGoogleAppengineApiDatastore.PreparedQuery
461
476
  # for this query.
462
477
  #
463
- def pquery
464
- @pquery ||= Datastore.service.prepare(@query)
478
+ def pquery(transaction=:current)
479
+ @pquery ||= if transaction != :current
480
+ Datastore.service.prepare(transaction, @query)
481
+ else
482
+ Datastore.service.prepare(@query)
483
+ end
465
484
  end
466
485
 
467
486
  # Returns a Java.ComGoogleAppengineApiDatastore.Query for this query.
@@ -481,9 +500,17 @@ module Datastore
481
500
  # Determines the internal chunking strategy of the iterator
482
501
  # returned by #iterator. This affects only the performance of
483
502
  # the query, not the actual results returned.
503
+ # [:transaction]
504
+ # Transaction in which the query should run. Only supported
505
+ # for ancestor queries. Uses the current transaction if not
506
+ # specified.
484
507
  #
485
508
  def convert_options(options)
486
- return options if options.java_kind_of? FetchOptions
509
+ transaction = :current
510
+ return [transaction, options] if options.java_kind_of? FetchOptions
511
+ if options.include? :transaction
512
+ transaction = options.delete(:transaction)
513
+ end
487
514
  limit = options.delete(:limit)
488
515
  offset = options.delete(:offset)
489
516
  chunk_size = options.delete(:chunk) || FetchOptions::DEFAULT_CHUNK_SIZE
@@ -493,7 +520,7 @@ module Datastore
493
520
  options = FetchOptions::Builder.with_chunk_size(chunk_size)
494
521
  options.offset(offset) if offset
495
522
  options.limit(limit) if limit
496
- options
523
+ [transaction, options]
497
524
  end
498
525
 
499
526
  def inspect
@@ -23,11 +23,11 @@ require 'java'
23
23
 
24
24
  class Time
25
25
  def to_java
26
- java.util.Date.new(tv_sec * 1000 + tv_usec / 1000)
26
+ java.util.Date.new(tv_sec * 1000 + tv_usec / 1000.0)
27
27
  end
28
28
 
29
29
  def self.new_from_java(date)
30
- at(date.time / 1000)
30
+ at(date.time / 1000.0)
31
31
  end
32
32
  end
33
33
 
@@ -117,6 +117,135 @@ module AppEngine
117
117
  end
118
118
  end
119
119
 
120
+ # An RFC2822 email address. Makes no attempt at validation.
121
+ class Email < String
122
+ def to_java
123
+ JavaDatastore::Email.new(self.to_java_string)
124
+ end
125
+
126
+ def self.new_from_java(email)
127
+ self.new(email.getEmail)
128
+ end
129
+ end
130
+
131
+ # A tag, ie a descriptive word or phrase. Entities may be tagged by users,
132
+ # and later returned by a queries for that tag. Tags can also be used for
133
+ # ranking results (frequency), photo captions, clustering, activity, etc.
134
+ #
135
+ # More details: http://www.zeldman.com/daily/0405d.shtml
136
+ class Category < String
137
+ def to_java
138
+ JavaDatastore::Category.new(self.to_java_string)
139
+ end
140
+
141
+ def self.new_from_java(category)
142
+ self.new(category.getCategory)
143
+ end
144
+ end
145
+
146
+ # A human-readable phone number. No validation is performed because phone
147
+ # numbers have many different formats - local, long distance, domestic,
148
+ # international, internal extension, TTY, VOIP, SMS, and alternative
149
+ # networks like Skype, XFire and Roger Wilco. They all have their own
150
+ # numbering and addressing formats.
151
+ class PhoneNumber < String
152
+ def to_java
153
+ JavaDatastore::PhoneNumber.new(self.to_java_string)
154
+ end
155
+
156
+ def self.new_from_java(phone)
157
+ self.new(phone.getNumber)
158
+ end
159
+ end
160
+
161
+ # A human-readable mailing address. Mailing address formats vary widely so
162
+ # no validation is performed.
163
+ class PostalAddress < String
164
+ def to_java
165
+ JavaDatastore::PostalAddress.new(self.to_java_string)
166
+ end
167
+
168
+ def self.new_from_java(address)
169
+ self.new(address.getAddress)
170
+ end
171
+ end
172
+
173
+ Rating = JavaDatastore::Rating
174
+
175
+ # A user-provided integer rating for a piece of content. Normalized to a
176
+ # 0-100 scale.
177
+ class Rating
178
+ # Raises ArgumentError if rating < 0 or rating > 100.
179
+ def self.new(rating)
180
+ if rating < MIN_VALUE || rating > MAX_VALUE
181
+ raise ArgumentError, "rating must be no smaller than #{MIN_VALUE} " +
182
+ "and no greater than #{MAX_VALUE} (received #{rating})"
183
+ end
184
+ super(rating)
185
+ end
186
+
187
+ alias to_i rating
188
+
189
+ def to_s
190
+ rating.to_s
191
+ end
192
+
193
+ def inspect
194
+ "#<Rating #{rating}>"
195
+ end
196
+
197
+ if false
198
+ MIN_VALUE = 0
199
+ MAX_VALUE = 100
200
+ def rating; end
201
+ end
202
+ end
203
+
204
+ IMHandle = JavaDatastore::IMHandle
205
+
206
+ # An instant messaging handle. Includes both an address and its protocol.
207
+ # The protocol value is either a standard IM scheme (legal scheme values are
208
+ # :sip, :xmpp, :unknown or a URL identifying the IM network for the
209
+ # protocol (eg http://aim.com/).
210
+ class IMHandle
211
+ SCHEMES = {
212
+ :sip => Scheme.sip,
213
+ :xmpp => Scheme.xmpp,
214
+ :unknown => Scheme.unknown
215
+ }.freeze
216
+
217
+ def self.new(protocol, address)
218
+ begin
219
+ protocol = SCHEMES[protocol] || java.net.URL.new(protocol)
220
+ rescue java.net.MalformedURLException => ex
221
+ raise ArgumentError, ex.message
222
+ end
223
+ super
224
+ end
225
+
226
+ if false
227
+ def protocol; end
228
+ def address; end
229
+ end
230
+ end
231
+
232
+ GeoPt = JavaDatastore::GeoPt
233
+
234
+ # A geographical point, specified by float latitude and longitude
235
+ # coordinates. Often used to integrate with mapping sites like Google Maps.
236
+ class GeoPt
237
+ def self.new(latitude, longitude)
238
+ super
239
+ rescue java.lang.IllegalArgumentException => ex
240
+ raise ArgumentError, ex.message
241
+ end
242
+
243
+ if false
244
+ def latitude; end
245
+ def longitude; end
246
+ end
247
+ end
248
+
120
249
  Key = JavaDatastore::Key
121
250
 
122
251
  # The primary key for a datastore entity.
@@ -219,6 +348,39 @@ module AppEngine
219
348
  end
220
349
  end
221
350
 
351
+ KeyRange = JavaDatastore::KeyRange
352
+
353
+ # Represents a range of unique datastore identifiers from
354
+ # start.id to end.id inclusive. The Keys returned by an
355
+ # instance of this class have been consumed in the datastore's
356
+ # id-space and are guaranteed never to be reused.
357
+ #
358
+ # This class can be used to construct Entity Entities with
359
+ # Keys that have specific id values without fear of the datastore
360
+ # creating new records with those same ids at a later date. This can be
361
+ # helpful as part of a data migration or large bulk upload where you may
362
+ # need to preserve existing ids and relationships between entities.
363
+ class KeyRange
364
+ include Enumerable
365
+
366
+ if false
367
+ # The first Key in the range.
368
+ def start; end;
369
+
370
+ # The last Key in the range.
371
+ def end; end;
372
+
373
+ # The size of the range.
374
+ def size; end;
375
+ end
376
+
377
+ def each
378
+ iterator.each do |key|
379
+ yield key
380
+ end
381
+ end
382
+ end
383
+
222
384
  Entity = JavaDatastore::Entity
223
385
 
224
386
  # Entity is the fundamental unit of data storage. It has an
@@ -237,12 +399,36 @@ module AppEngine
237
399
  JavaDatastore::Blob => Blob,
238
400
  JavaDatastore::ShortBlob => ByteString,
239
401
  JavaDatastore::Link => Link,
402
+ JavaDatastore::Email => Email,
403
+ JavaDatastore::Category => Category,
404
+ JavaDatastore::PhoneNumber => PhoneNumber,
405
+ JavaDatastore::PostalAddress => PostalAddress,
240
406
  java.util.Date => Time,
241
407
  }.freeze
242
408
 
243
409
  alias :inspect :to_string
244
410
  alias :== :equals?
245
411
 
412
+ if false
413
+ # Create a new Entity with the specified kind and parent Entity. The
414
+ # instantiated Entity will have anincomplete Key when this constructor
415
+ # returns. The Key will remain incomplete until you put the Entity,
416
+ # after which time the Key will have its id set.
417
+ def initialize(kind, parent=nil); end
418
+
419
+ # Create a new Entity with the specified kind, key name, and parent
420
+ # Entity. The instantiated Entity will have a complete Key when this
421
+ # constructor returns. The Key's name field will be set to the value of
422
+ # key_name.
423
+ def initialize(kind, key_name, parent=nil); end
424
+
425
+ # Create a new Entity uniquely identified by the provided Key.
426
+ # Creating an entity for the purpose of insertion (as opposed
427
+ # to update) with a key that has its id field set is strongly
428
+ # discouraged unless the key was returned by a KeyRange.
429
+ def initialize(key); end
430
+ end
431
+
246
432
  # Returns the property with the specified name.
247
433
  def get_property(name)
248
434
  name = name.to_s if name.kind_of? Symbol
@@ -333,8 +519,9 @@ module AppEngine
333
519
  end
334
520
  end
335
521
 
336
- SPECIAL_RUBY_TYPES = [Time, Text, Blob, ByteString, Link].freeze
337
-
522
+ SPECIAL_RUBY_TYPES = [Time, Text, Blob, ByteString, Link, Email,
523
+ Category, PhoneNumber, PostalAddress].freeze
524
+
338
525
  def Datastore.ruby_to_java(value) # :nodoc:
339
526
  if SPECIAL_RUBY_TYPES.include? value.class
340
527
  value.to_java
@@ -357,6 +544,8 @@ module AppEngine
357
544
  yield
358
545
  rescue java.lang.IllegalArgumentException => ex
359
546
  raise ArgumentError, ex.message
547
+ rescue java.lang.NullPointerException => ex
548
+ raise ArgumentError, ex.message
360
549
  rescue java.util.ConcurrentModificationException => ex
361
550
  raise TransactionFailed, ex.message
362
551
  rescue java.util.NoSuchElementException => ex
@@ -368,7 +557,7 @@ module AppEngine
368
557
  rescue JavaDatastore::DatastoreFailureException => ex
369
558
  raise InternalError, ex.message
370
559
  rescue JavaDatastore::EntityNotFoundException => ex
371
- raise EnityNotFound, ex.message
560
+ raise EntityNotFound, ex.message
372
561
  rescue JavaDatastore::PreparedQuery::TooManyResultsException => ex
373
562
  raise TooManyResults, ex.message
374
563
  end
@@ -0,0 +1,266 @@
1
+ #!/usr/bin/ruby1.8 -w
2
+ #
3
+ # Copyright:: Copyright 2009 Google Inc.
4
+ # Original Author:: Ryan Brown (mailto:ribrdb@google.com)
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # 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, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ # Task Queue API.
19
+ #
20
+ # Enables an application to queue background work for itself. Work is done
21
+ # through webhooks that process tasks pushed from a queue. Tasks will execute in
22
+ # best-effort order of ETA. Webhooks that fail will cause tasks to be retried at
23
+ # a later time. Multiple queues may exist with independent throttling controls.
24
+ #
25
+ # Webhook URLs may be specified directly for Tasks, or the default URL scheme
26
+ # may be used, which will translate Task names into URLs relative to a Queue's
27
+ # base path. A default queue is also provided for simple usage.
28
+
29
+ require 'appengine-apis/datastore_types'
30
+
31
+ module AppEngine
32
+ module Labs
33
+ module TaskQueue
34
+ import com.google.appengine.api.labs.taskqueue.QueueFactory
35
+ import com.google.appengine.api.labs.taskqueue.TaskOptions
36
+
37
+ import com.google.appengine.api.labs.taskqueue.TaskAlreadyExistsException
38
+ import com.google.appengine.api.labs.taskqueue.TransientFailureException
39
+ import com.google.appengine.api.labs.taskqueue.InternalFailureException
40
+ import com.google.appengine.api.labs.taskqueue.TaskAlreadyExistsException
41
+ import com.google.appengine.api.labs.taskqueue.UnsupportedTranslationException
42
+
43
+ class TaskAlreadyExistsError < StandardError; end
44
+ class TransientFailureError < StandardError; end
45
+ class InternalError < StandardError; end
46
+
47
+ Blob = AppEngine::Datastore::Blob
48
+
49
+ # Represents a single Task on a queue.
50
+ class Task
51
+
52
+ # Initializer.
53
+ #
54
+ # All parameters are optional.
55
+ #
56
+ # Options:
57
+ # [:payload] The payload data for this Task that will be delivered to
58
+ # the webhook as the HTTP request body. This is only allowed for
59
+ # POST and PUT methods. Assumed to be UTF-8 unless it is a Blob.
60
+ # [:bytes] Binary payload data for this Task.
61
+ # [:countdown]: Time in seconds into the future that this Task should
62
+ # execute. Defaults to zero.
63
+ # [:eta] Absolute time when the Task should execute. Must be a Time
64
+ # object. May not be specified if 'countdown' is also supplied.
65
+ # [:headers] Hash of headers to pass to the webhook. Values in the
66
+ # hash may be enumerable to indicate repeated header fields.
67
+ # [:method]: HTTP method to use when accessing the webhook. Defaults
68
+ # to 'POST'.
69
+ # [:name] Name to give the Task; if not specified, a name will be
70
+ # auto-generated when added to a queue and assigned to this object.
71
+ # [:params]: Hash of parameters to use for this Task.
72
+ # For POST requests these params will be encoded as
73
+ # 'application/x-www-form-urlencoded' and set to the payload.
74
+ # For all other methods, the parameters will be converted to a
75
+ # query string. May not be specified if the URL already
76
+ # contains a query string.
77
+ # [:url] Relative URL where the webhook that should handle this task is
78
+ # located for this application. May have a query string unless
79
+ # this is a POST method.
80
+ #
81
+ # Raises:
82
+ # InvalidTaskError if any of the parameters are invalid;
83
+ # InvalidTaskNameError if the task name is invalid; InvalidUrlError if
84
+ # the task URL is invalid or too long; TaskTooLargeError if the task with
85
+ # its payload is too large.
86
+ def initialize(payload=nil, options={})
87
+ if payload.kind_of? Hash
88
+ options, payload = payload, nil
89
+ elsif payload.kind_of? TaskOptions
90
+ @task_options = payload
91
+ return
92
+ end
93
+ options = options.dup
94
+ if payload.kind_of? Blob
95
+ options[:bytes] = payload
96
+ elsif payload
97
+ options[:payload] = payload
98
+ end
99
+ @task_options = convert_options(options)
100
+ end
101
+
102
+ # Returns whether this Task has been enqueued.
103
+ #
104
+ # Note: This will not check if this Task already exists in the queue.
105
+ def enqueued?
106
+ !!@handle
107
+ end
108
+
109
+ # Adds this Task to a queue
110
+ #
111
+ # Args:
112
+ # - queue: Name of the queue where this Task should be added. (optional)
113
+ #
114
+ def add(queue=nil)
115
+ queue = Queue.new(queue) unless Queue.kind_of? Queue
116
+ @handle = queue.java_queue.add(_task)
117
+ self
118
+ end
119
+
120
+ # Returns the Time when this Task will execute.
121
+ def eta
122
+ Time.at(@handle.eta_millis / 1000.0) if @handle
123
+ end
124
+
125
+ # Returns the name of this Task.
126
+ #
127
+ # Will be nil if using an auto-assigned Task name and this Task has
128
+ # not yet been added to a Queue.
129
+ def name
130
+ @handle.name if @handle
131
+ end
132
+
133
+ # Returns the name of the Queue where this Task was enqueued.
134
+ def queue
135
+ @handle.queue_name if @handle
136
+ end
137
+
138
+ private
139
+ def convert_options(options)
140
+ TaskQueue.convert_exceptions do
141
+ task = TaskOptions::Builder.with_defaults
142
+ if bytes = options.delete(:bytes)
143
+ task.payload(bytes.to_java_bytes, 'application/octet-stream')
144
+ end
145
+ if payload = options.delete(:payload)
146
+ task.payload(payload)
147
+ end
148
+ if countdown = options.delete(:countdown)
149
+ millis = (countdown * 1000).round
150
+ task.countdown_millis(millis)
151
+ end
152
+ if @eta = options.delete(:eta)
153
+ millis = @eta.tv_sec * 1000 + @eta.tv_usec / 1000.0
154
+ task.eta_millis(millis)
155
+ end
156
+ if headers = options.delete(:headers)
157
+ headers.each do |key, value|
158
+ if value.kind_of? Array
159
+ value = value.join(",")
160
+ end
161
+ task.header(key, value)
162
+ end
163
+ end
164
+ if method = options.delete(:method)
165
+ method = TaskOptions::Method.value_of(method.to_s.upcase)
166
+ task.method(method)
167
+ end
168
+ if name = options.delete(:name)
169
+ task.task_name(name)
170
+ end
171
+ if params = options.delete(:params)
172
+ params.each do |name, param|
173
+ if param.kind_of? Blob
174
+ param = param.to_java_bytes
175
+ end
176
+ task.param(name, param)
177
+ end
178
+ end
179
+ if url = options.delete(:url)
180
+ task.url(url)
181
+ end
182
+ task
183
+ end
184
+ end
185
+
186
+ def _task
187
+ @task_options
188
+ end
189
+
190
+ end
191
+
192
+ # Represents a Queue.
193
+ class Queue
194
+ @queues = {}
195
+
196
+ # Returns the named Queue, or the default queue if name is nil.
197
+ #
198
+ # The returned Queue object may not necessarily refer
199
+ # to an existing queue. Queues must be configured before
200
+ # they may be used. Attempting to use a non-existing queue name
201
+ # may result in errors at the point of use of the Queue object,
202
+ # not when creating it.
203
+ def initialize(name=nil)
204
+ TaskQueue.convert_exceptions do
205
+ if name.nil?
206
+ @queue = QueueFactory.default_queue
207
+ else
208
+ @queue = QueueFactory.get_queue(name)
209
+ end
210
+ end
211
+ end
212
+
213
+ def self.new(name=nil)
214
+ @queues[name] ||= super
215
+ end
216
+
217
+ # Submits a task to this queue.
218
+ def add(task=nil)
219
+ if task.nil?
220
+ Task.new.add(self)
221
+ elsif task.java_kind_of? TaskOptions
222
+ Task.new(task).add(self)
223
+ else
224
+ task.add(self)
225
+ end
226
+ end
227
+
228
+ # Returns the name of this queue.
229
+ def name
230
+ @queue.queue_name
231
+ end
232
+
233
+ def java_queue
234
+ @queue
235
+ end
236
+ end
237
+
238
+ # Convenience method will create a Task and add it to the default queue.
239
+ #
240
+ # Args:
241
+ # - args: Passed to the Task constructor.
242
+ #
243
+ # Returns:
244
+ # - The Task that was added to the queue.
245
+ def self.add(*args)
246
+ Task.new(*args).add
247
+ end
248
+
249
+ def self.convert_exceptions
250
+ begin
251
+ yield
252
+ rescue java.lang.IllegalArgumentException => ex
253
+ raise ArgumentError, ex.message
254
+ rescue UnsupportedTranslationException => ex
255
+ raise ArgumentError, ex.message
256
+ rescue TaskAlreadyExistsException => ex
257
+ raise TaskAlreadExistsError, ex.message
258
+ rescue InternalFailureException => ex
259
+ raise InternalError, ex.message
260
+ rescue TransientFailureException => ex
261
+ raise TransientFailureError, ex.message
262
+ end
263
+ end
264
+ end
265
+ end
266
+ end