1.9.30 sync.
[gae.git] / java / src / main / com / google / appengine / api / memcache / MemcacheServiceApiHelper.java
blob2813c6239f5787e98d6d5cd176b4cec6d31172d6
1 // Copyright 2011 Google Inc. All Rights Reserved.
2 package com.google.appengine.api.memcache;
4 import com.google.appengine.api.utils.FutureWrapper;
5 import com.google.apphosting.api.ApiProxy;
6 import com.google.common.base.Throwables;
7 import com.google.protobuf.InvalidProtocolBufferException;
8 import com.google.protobuf.Message;
10 import java.util.concurrent.Future;
11 import java.util.logging.Logger;
13 /**
14 * Helper methods and constants shared by classes that implement the java api
15 * of MemcacheService.
18 class MemcacheServiceApiHelper {
20 static final String PACKAGE = "memcache";
21 private static final Logger logger = Logger.getLogger(MemcacheServiceApiHelper.class.getName());
23 private MemcacheServiceApiHelper() {
26 public interface Provider<T> {
27 T get();
30 interface Transformer<F, T> {
31 T transform(F from);
34 /**
35 * An RPC response handler to convert an ApiProxy rpc response
36 * (byte[] or exceptions) to an API level response.
38 static class RpcResponseHandler<M extends Message, T> {
40 private final String errorText;
41 private final Message.Builder builder;
42 private final Transformer<M, T> responseTransfomer;
43 private final ErrorHandler errorHandler;
45 RpcResponseHandler(M response, String errorText,
46 Transformer<M, T> responseTransfomer, ErrorHandler errorHandler) {
47 this.builder = response.newBuilderForType();
48 this.errorText = errorText;
49 this.responseTransfomer = responseTransfomer;
50 this.errorHandler = errorHandler;
53 T convertResponse(byte[] responseBytes) throws InvalidProtocolBufferException {
54 @SuppressWarnings("unchecked")
55 M response = (M) builder.mergeFrom(responseBytes).build();
56 return responseTransfomer.transform(response);
59 void handleApiProxyException(Throwable cause) throws Exception {
60 try {
61 throw cause;
62 } catch (InvalidProtocolBufferException ex) {
63 errorHandler.handleServiceError(
64 new MemcacheServiceException("Could not decode response:", ex));
65 } catch (ApiProxy.ApplicationException ex) {
66 logger.info(errorText + ": " + ex.getErrorDetail());
67 errorHandler.handleServiceError(new MemcacheServiceException(errorText));
68 } catch (ApiProxy.ApiProxyException ex) {
69 errorHandler.handleServiceError(new MemcacheServiceException(errorText, ex));
70 } catch (MemcacheServiceException ex) {
71 if (errorHandler instanceof ConsistentErrorHandler) {
72 errorHandler.handleServiceError(ex);
73 } else {
74 throw ex;
76 } catch (Throwable ex) {
77 Throwables.propagateIfInstanceOf(ex, Exception.class);
78 Throwables.propagate(ex);
82 Logger getLogger() {
83 return logger;
87 /**
88 * Issue an async rpc against the memcache package with the given request and
89 * response pbs as input and apply standard exception handling. Do not
90 * use this helper function if you need non-standard exception handling.
92 static <M extends Message, T> Future<T> makeAsyncCall(String methodName, Message request,
93 final RpcResponseHandler<M, T> responseHandler, final Provider<T> defaultValue) {
94 Future<byte[]> asyncResp = ApiProxy.makeAsyncCall(PACKAGE, methodName, request.toByteArray());
95 return new FutureWrapper<byte[], T>(asyncResp) {
97 @Override
98 protected T wrap(byte[] bytes) throws Exception {
99 try {
100 return bytes == null ? null : responseHandler.convertResponse(bytes);
101 } catch (Exception ex) {
102 return absorbParentException(ex);
106 @Override
107 protected T absorbParentException(Throwable cause) throws Exception {
108 responseHandler.handleApiProxyException(cause);
109 return defaultValue.get();
112 @Override
113 protected Throwable convertException(Throwable cause) {
114 return cause;