Revision created by MOE tool push_codebase.
[gae.git] / java / src / main / com / google / appengine / api / datastore / DatastoreApiHelper.java
blob325f4f1f7aa693a17cb539b3b7a0c501afc30566
1 // Copyright 2008 Google Inc. All Rights Reserved.
2 package com.google.appengine.api.datastore;
4 import com.google.appengine.api.NamespaceManager;
5 import com.google.appengine.api.utils.FutureWrapper;
6 import com.google.apphosting.api.ApiProxy;
7 import com.google.apphosting.api.ApiProxy.ApiConfig;
8 import com.google.apphosting.datastore.DatastoreV3Pb.DatastoreService_3;
9 import com.google.apphosting.datastore.DatastoreV3Pb.Error;
10 import com.google.apphosting.datastore.DatastoreV4.DatastoreV4Service;
11 import com.google.io.protocol.ProtocolMessage;
12 import com.google.protobuf.MessageLite;
13 import com.google.protobuf.Parser;
15 import java.util.ConcurrentModificationException;
16 import java.util.concurrent.Future;
18 /**
19 * Helper methods and constants shared by classes that implement the java api
20 * on top of the datastore.
21 * Note: user should not access this class directly.
24 public final class DatastoreApiHelper {
26 static final String PACKAGE = "datastore_v3";
27 static final String V4_PACKAGE = "datastore_v4";
29 /**
30 * Key to put in {@link ApiProxy.Environment#getAttributes()} to override the app id used by the
31 * datastore api. If absent, {@link ApiProxy.Environment#getAppId()} will be used.
33 @SuppressWarnings("javadoc")
34 static final String APP_ID_OVERRIDE_KEY = "com.google.appengine.datastore.AppIdOverride";
36 private DatastoreApiHelper() {}
38 public static RuntimeException translateError(ApiProxy.ApplicationException exception) {
39 Error.ErrorCode errorCode = Error.ErrorCode.valueOf(exception.getApplicationError());
40 if (errorCode == null) {
41 return new DatastoreFailureException(exception.getErrorDetail());
43 switch (errorCode) {
44 case BAD_REQUEST:
45 return new IllegalArgumentException(exception.getErrorDetail());
47 case CONCURRENT_TRANSACTION:
48 return new ConcurrentModificationException(exception.getErrorDetail());
50 case NEED_INDEX:
51 return new DatastoreNeedIndexException(exception.getErrorDetail());
53 case TIMEOUT:
54 case BIGTABLE_ERROR:
55 return new DatastoreTimeoutException(exception.getErrorDetail());
57 case COMMITTED_BUT_STILL_APPLYING:
58 return new CommittedButStillApplyingException(exception.getErrorDetail());
60 case INTERNAL_ERROR:
61 default:
62 return new DatastoreFailureException(exception.getErrorDetail());
66 abstract static class AsyncCallWrapper<S, T> extends FutureWrapper<S, T> {
67 AsyncCallWrapper(Future<S> response) {
68 super(response);
71 @Override
72 protected Throwable convertException(Throwable cause) {
73 if (cause instanceof ApiProxy.ApplicationException) {
74 return translateError((ApiProxy.ApplicationException) cause);
76 return cause;
80 static <T extends ProtocolMessage<T>> Future<T> makeAsyncCall(ApiConfig apiConfig,
81 DatastoreService_3.Method method, ProtocolMessage<?> request, final T responseProto) {
82 Future<byte[]> response =
83 ApiProxy.makeAsyncCall(PACKAGE, method.name(), request.toByteArray(), apiConfig);
84 return new AsyncCallWrapper<byte[], T>(response) {
85 @Override
86 protected T wrap(byte[] responseBytes) {
87 if (responseBytes != null) {
88 responseProto.parseFrom(responseBytes);
90 return responseProto;
95 static <T extends MessageLite> Future<T> makeAsyncCall(ApiProxy.ApiConfig apiConfig,
96 DatastoreV4Service.Method method, MessageLite request, Parser<T> responseParser) {
97 return makeAsyncCall(apiConfig, method, request.toByteArray(), responseParser);
100 static <T extends MessageLite> Future<T> makeAsyncCall(ApiProxy.ApiConfig apiConfig,
101 DatastoreV4Service.Method method, byte[] request, final Parser<T> responseParser) {
102 Future<byte[]> response = ApiProxy.makeAsyncCall(V4_PACKAGE, method.name(), request, apiConfig);
103 return new AsyncCallWrapper<byte[], T>(response) {
104 @Override
105 protected T wrap(byte[] responseBytes) throws Exception {
106 if (responseBytes != null) {
107 return responseParser.parseFrom(responseBytes);
109 return responseParser.parsePartialFrom(new byte[0]);
114 static String getCurrentAppId() {
115 ApiProxy.Environment environment = ApiProxy.getCurrentEnvironment();
116 if (environment == null) {
117 throw new NullPointerException("No API environment is registered for this thread.");
120 Object appIdOverride = environment.getAttributes().get(APP_ID_OVERRIDE_KEY);
121 if (appIdOverride != null) {
122 return (String) appIdOverride;
125 return environment.getAppId();
129 * Returns a new {@link AppIdNamespace} with the current appId and the namespace
130 * registered with the {@link NamespaceManager}
132 static AppIdNamespace getCurrentAppIdNamespace() {
133 return getCurrentAppIdNamespace(getCurrentAppId());
137 * Returns a new {@link AppIdNamespace} with the namespace currently
138 * registered with the {@link NamespaceManager} for a given appid.
140 static AppIdNamespace getCurrentAppIdNamespace(String appId) {
141 String namespace = NamespaceManager.get();
142 namespace = namespace == null ? "" : namespace;
143 return new AppIdNamespace(appId, namespace);