Revision created by MOE tool push_codebase.
[gae.git] / java / src / main / com / google / appengine / api / taskqueue / QueueApiHelper.java
blob6ab8c5b227fcd1071887cec681e9fa97b40a5ab8
1 // Copyright 2010 Google Inc. All rights reserved.
2 package com.google.appengine.api.taskqueue;
4 import com.google.appengine.api.datastore.DatastoreApiHelper;
5 import com.google.appengine.api.taskqueue.TaskQueuePb.TaskQueueServiceError.ErrorCode;
6 import com.google.appengine.api.utils.FutureWrapper;
7 import com.google.apphosting.api.ApiProxy;
8 import com.google.apphosting.api.ApiProxy.ApiConfig;
9 import com.google.io.protocol.ProtocolMessage;
11 import java.util.concurrent.ExecutionException;
12 import java.util.concurrent.Future;
14 /**
15 * Provides translation of calls between userland and appserver land.
18 class QueueApiHelper {
19 static final String PACKAGE = "taskqueue";
21 <T extends ProtocolMessage<T>, V extends ProtocolMessage<V>> void makeSyncCall(
22 String method,
23 ProtocolMessage<T> request,
24 ProtocolMessage<V> response) {
25 try {
26 byte[] responseBytes =
27 ApiProxy.makeSyncCall(PACKAGE, method, request.toByteArray());
28 if (responseBytes != null) {
29 response.mergeFrom(responseBytes);
31 } catch (ApiProxy.ApplicationException exception) {
32 throw translateError(exception);
36 /**
37 * Issue an async rpc against the taskqueue package with the given request and
38 * response pbs as input and apply standard exception handling. Do not
39 * use this helper function if you need non-standard exception handling.
41 <T extends ProtocolMessage<T>> Future<T> makeAsyncCall(
42 String method,
43 ProtocolMessage<?> request,
44 final T responseProto,
45 ApiConfig apiConfig) {
46 Future<byte[]> response =
47 ApiProxy.makeAsyncCall(PACKAGE, method, request.toByteArray(), apiConfig);
48 return new FutureWrapper<byte[], T>(response) {
49 @Override
50 protected Throwable convertException(Throwable cause) {
51 if (cause instanceof ApiProxy.ApplicationException) {
52 return translateError((ApiProxy.ApplicationException) cause);
54 return cause;
57 @Override
58 protected T wrap(byte[] responseBytes) {
59 if (responseBytes != null) {
60 responseProto.parseFrom(responseBytes);
62 return responseProto;
67 /***
68 * Extract the future's result.
70 static <T> T getInternal(Future<T> future) {
71 try {
72 return future.get();
73 } catch (InterruptedException e) {
74 Thread.currentThread().interrupt();
75 throw new ApiProxy.ApplicationException(ErrorCode.TRANSIENT_ERROR.getValue(),
76 "Interrupted while waiting for RPC response.");
77 } catch (ExecutionException e) {
78 Throwable cause = e.getCause();
79 if (cause instanceof RuntimeException) {
80 throw (RuntimeException) cause;
81 } else if (cause instanceof Error) {
82 throw (Error) cause;
83 } else {
84 throw new RuntimeException(cause);
89 static RuntimeException translateError(int error, String detail) {
90 ErrorCode errorCode = ErrorCode.valueOf(error);
92 int datastoreErrorCode = ErrorCode.DATASTORE_ERROR.getValue();
93 if (error >= datastoreErrorCode) {
94 ApiProxy.ApplicationException datastoreApplicationException =
95 new ApiProxy.ApplicationException(error - datastoreErrorCode, detail);
96 TransactionalTaskException taskqueueException = new TransactionalTaskException();
97 taskqueueException.initCause(
98 DatastoreApiHelper.translateError(datastoreApplicationException));
99 return taskqueueException;
102 switch (errorCode) {
103 case UNKNOWN_QUEUE:
104 return new IllegalStateException("The specified queue is unknown : " + detail);
105 case TRANSIENT_ERROR:
106 return new TransientFailureException(detail);
107 case INTERNAL_ERROR:
108 return new InternalFailureException(detail);
109 case TASK_TOO_LARGE:
110 return new IllegalArgumentException("Task size is too large : " + detail);
111 case INVALID_TASK_NAME:
112 return new IllegalArgumentException("Invalid task name : " + detail);
113 case INVALID_QUEUE_NAME:
114 return new IllegalArgumentException("Invalid queue name : " + detail);
115 case INVALID_URL:
116 return new IllegalArgumentException("Invalid URL : " + detail);
117 case INVALID_QUEUE_RATE:
118 return new IllegalArgumentException("Invalid queue rate : " + detail);
119 case PERMISSION_DENIED:
120 return new SecurityException("Permission for requested operation is denied : " + detail);
121 case TASK_ALREADY_EXISTS:
122 return new TaskAlreadyExistsException("Task name already exists : " + detail);
123 case TOMBSTONED_TASK:
124 return new TaskAlreadyExistsException("Task name is tombstoned : " + detail);
125 case INVALID_ETA:
126 return new IllegalArgumentException("ETA is invalid : " + detail);
127 case INVALID_REQUEST:
128 return new IllegalArgumentException("Invalid request : " + detail);
129 case UNKNOWN_TASK:
130 return new TaskNotFoundException("Task does not exist : " + detail);
131 case TOMBSTONED_QUEUE:
132 return new IllegalStateException(
133 "The queue has been marked for deletion and is no longer usable : " + detail);
134 case DUPLICATE_TASK_NAME:
135 return new IllegalArgumentException("Identical task names in request : " + detail);
136 case TOO_MANY_TASKS:
137 return new IllegalArgumentException("Request contains too many tasks : " + detail);
138 case INVALID_QUEUE_MODE:
139 return new InvalidQueueModeException(
140 "Target queue mode does not support this operation : " + detail);
141 case TASK_LEASE_EXPIRED:
142 return new IllegalStateException(
143 "The task lease has expired : " + detail);
144 case QUEUE_PAUSED:
145 return new IllegalStateException(
146 "The queue is paused and cannot process the request : " + detail);
147 default:
148 return new QueueFailureException("Unspecified error (" + errorCode + ") : " + detail);
152 static RuntimeException translateError(ApiProxy.ApplicationException exception) {
153 return translateError(exception.getApplicationError(), exception.getErrorDetail());
156 public static void validateQueueName(String queueName) {
157 if (queueName == null || queueName.length() == 0 ||
158 !QueueConstants.QUEUE_NAME_PATTERN.matcher(queueName).matches()) {
159 throw new IllegalArgumentException(
160 "Queue name does not match expression " + QueueConstants.QUEUE_NAME_REGEX +
161 "; found '" + queueName + "'");