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
;
14 * Helper methods and constants shared by classes that implement the java api
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
> {
30 interface Transformer
<F
, T
> {
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
{
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
);
76 } catch (Throwable ex
) {
77 Throwables
.propagateIfInstanceOf(ex
, Exception
.class);
78 Throwables
.propagate(ex
);
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
) {
98 protected T
wrap(byte[] bytes
) throws Exception
{
100 return bytes
== null ?
null : responseHandler
.convertResponse(bytes
);
101 } catch (Exception ex
) {
102 return absorbParentException(ex
);
107 protected T
absorbParentException(Throwable cause
) throws Exception
{
108 responseHandler
.handleApiProxyException(cause
);
109 return defaultValue
.get();
113 protected Throwable
convertException(Throwable cause
) {