appengine-apis 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -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