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
;
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()) {
28 serviceError
.setErrorDetail(matcher
.group(2));
29 serviceError
.setSystemError(Integer
.parseInt(matcher
.group(1)));
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
{
52 byte[] responseBytes
= apiProxyMakeSyncCall(method
, request
.toByteArray());
53 if (responseBytes
!= null) {
54 response
.mergeFrom(responseBytes
);
57 } catch (ApiProxy
.ApplicationException exception
) {
58 if (serviceError
!= null) {
60 RemoteSocketServiceError
.ErrorCode
.valueOf(exception
.getApplicationError());
64 parseErrorDetail(exception
.getErrorDetail(), serviceError
);
65 if (serviceError
.hasErrorDetail() || serviceError
.hasSystemError()) {
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
);
86 return new SocketException("System error: " + detail
);
88 return new SocketException("Resolver error: " + detail
);
90 return new SocketException("SSL Error: " + detail
);
92 return new SocketException("Operation failure: " + detail
);
93 case PERMISSION_DENIED
:
94 return new SocketException("Permission denied: " + detail
);
96 return new SocketException("Invalid request: " + detail
);
98 return new SocketException("Socket is closed: " + detail
);
100 return new SocketException("Unspecified error (" + errorCode
+ ") : " + detail
);
104 static SocketException
translateError(ApiProxy
.ApplicationException exception
) {
105 return translateError(exception
.getApplicationError(), exception
.getErrorDetail());