Revision created by MOE tool push_codebase.
[gae.git] / java / src / main / com / google / appengine / api / socket / SocketApiHelper.java
blobb4336ee48db901dc80e1296147db56a28df252c2
1 // Copyright 2012 Google Inc. All Rights Reserved.
3 package com.google.appengine.api.socket;
5 import com.google.appengine.api.socket.SocketServicePb.RemoteSocketServiceError;
6 import com.google.appengine.api.socket.SocketServicePb.RemoteSocketServiceError.ErrorCode;
7 import com.google.apphosting.api.ApiProxy;
8 import com.google.io.protocol.ProtocolMessage;
10 import java.io.Serializable;
11 import java.net.SocketException;
12 import java.util.regex.Matcher;
13 import java.util.regex.Pattern;
15 /**
17 class SocketApiHelper implements Serializable {
18 static final String PACKAGE = "remote_socket";
20 private static final Pattern MESSAGE_PATTERN = Pattern.compile(
21 "system_error:\\s*(-?\\d+)\\s*,?\\s*error_detail:\\s*\"([^\"]*)\"\\s*");
22 static void parseErrorDetail(CharSequence string, RemoteSocketServiceError serviceError) {
23 Matcher matcher = MESSAGE_PATTERN.matcher(string);
24 if (!matcher.matches()) {
25 return;
28 serviceError.setErrorDetail(matcher.group(2));
29 serviceError.setSystemError(Integer.parseInt(matcher.group(1)));
32 /**
33 * Make an appserver call and optionally return transform certain
34 * application errors into the passed in serviceError.
35 * @param <T> The request type.
36 * @param <V> The response type.
37 * @param method The service method to call.
38 * @param request The request proto buffer.
39 * @param response The response proto buffer.
40 * @param serviceError The system error proto buffer. May be null if
41 * not the client is not interested.
42 * @return True if the request was successful, otherwise false only if the
43 * error is represented in the serviceError object. Other errors will
44 * throw an appropriate exception. If serviceError is null it will
45 * always throw on error.
46 * @throws SocketException
48 <T extends ProtocolMessage<T>, V extends ProtocolMessage<V>> boolean makeSyncCall(
49 String method, T request, V response,
50 RemoteSocketServiceError serviceError) throws SocketException {
51 try {
52 byte[] responseBytes = apiProxyMakeSyncCall(method, request.toByteArray());
53 if (responseBytes != null) {
54 response.mergeFrom(responseBytes);
56 return true;
57 } catch (ApiProxy.ApplicationException exception) {
58 if (serviceError != null) {
59 ErrorCode errorCode =
60 RemoteSocketServiceError.ErrorCode.valueOf(exception.getApplicationError());
61 switch (errorCode) {
62 case SYSTEM_ERROR:
63 case GAI_ERROR: {
64 parseErrorDetail(exception.getErrorDetail(), serviceError);
65 if (serviceError.hasErrorDetail() || serviceError.hasSystemError()) {
66 return false;
71 throw translateError(exception);
72 } catch (ApiProxy.ApiDeadlineExceededException e) {
73 throw new SocketException("Socket operation timed out: " + e.getMessage());
77 byte[] apiProxyMakeSyncCall(String method, byte[] request) {
78 return ApiProxy.makeSyncCall(PACKAGE, method, request);
81 static SocketException translateError(int error, String detail) {
82 ErrorCode errorCode = RemoteSocketServiceError.ErrorCode.valueOf(error);
84 switch (errorCode) {
85 case SYSTEM_ERROR:
86 return new SocketException("System error: " + detail);
87 case GAI_ERROR:
88 return new SocketException("Resolver error: " + detail);
89 case SSL_ERROR:
90 return new SocketException("SSL Error: " + detail);
91 case FAILURE:
92 return new SocketException("Operation failure: " + detail);
93 case PERMISSION_DENIED:
94 return new SocketException("Permission denied: " + detail);
95 case INVALID_REQUEST:
96 return new SocketException("Invalid request: " + detail);
97 case SOCKET_CLOSED:
98 return new SocketException("Socket is closed: " + detail);
99 default:
100 return new SocketException("Unspecified error (" + errorCode + ") : " + detail);
104 static SocketException translateError(ApiProxy.ApplicationException exception) {
105 return translateError(exception.getApplicationError(), exception.getErrorDetail());