Package com.google.appengine.tools.remoteapi

Source Code of com.google.appengine.tools.remoteapi.RemoteRpc

// Copyright 2011 Google Inc. All Rights Reserved.

package com.google.appengine.tools.remoteapi;

import com.google.apphosting.utils.remoteapi.RemoteApiPb;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.ConcurrentModificationException;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* An RPC transport that sends protocol buffers over HTTP.
*/
class RemoteRpc {
  private static final Logger logger = Logger.getLogger(RemoteRpc.class.getName());

  private final RemoteApiClient client;
  private int rpcCount = 0;

  RemoteRpc(AppEngineClient client) {
    this.client = client;
  }

  RemoteRpc(RemoteApiClient client) {
    this.client = client;
  }

  /**
   * Makes an RPC call using the injected RemoteRpc instance. Logs how long it took and
   * any exceptions.
   * @throws RemoteApiException if the RPC fails.
   * @throws RuntimeException if the server threw a Java runtime exception
   */
  byte[] call(String serviceName, String methodName, String logSuffix, byte[] request) {
    logger.log(Level.FINE, "remote API call: {0}.{1}{2}",
        new Object[] {serviceName, methodName, logSuffix});

    long startTime = System.currentTimeMillis();
    try {

      RemoteApiPb.Request requestProto = makeRequest(serviceName, methodName, request);
      RemoteApiPb.Response responseProto = callImpl(requestProto);

      if (responseProto.hasJavaException()) {
        logger.fine("remote API call: failed due to a server-side Java exception");
        Object contents = parseJavaException(responseProto,
            requestProto.getServiceName(), requestProto.getMethod());
        if (contents instanceof ConcurrentModificationException) {
          ConcurrentModificationException serverSide = (ConcurrentModificationException) contents;
          ConcurrentModificationException clientSide =
              new ConcurrentModificationException(serverSide.getMessage());
          clientSide.initCause(serverSide);
          throw clientSide;
        } else if (contents instanceof IllegalArgumentException) {
          IllegalArgumentException serverSide = (IllegalArgumentException) contents;
          throw new IllegalArgumentException(serverSide.getMessage(), serverSide);
        } else if (contents instanceof RuntimeException) {
            throw (RuntimeException) contents;
        } else if (contents instanceof Throwable) {
          throw new RemoteApiException("response was an exception",
              requestProto.getServiceName(), requestProto.getMethod(), (Throwable) contents);
        } else {
          throw new RemoteApiException("unexpected response type: " + contents.getClass(),
              requestProto.getServiceName(), requestProto.getMethod(), null);
        }
      } else if (responseProto.hasException()) {
        String pickle = responseProto.getException();

        logger.log(Level.FINE,
            "remote API call: failed due to a server-side Python exception:\n{0}", pickle);
        throw new RemoteApiException("response was a python exception:\n" + pickle,
            requestProto.getServiceName(), requestProto.getMethod(), null);
      }

      return responseProto.getResponseAsBytes();

    } finally {
      long elapsedTime = System.currentTimeMillis() - startTime;
      logger.log(Level.FINE, "remote API call: took {0} ms", elapsedTime);
    }
  }

  RemoteApiPb.Response callImpl(RemoteApiPb.Request requestProto) {
    rpcCount++;

    byte[] requestBytes = requestProto.toByteArray();

    AppEngineClient.Response httpResponse;
    try {
      String path = client.getRemoteApiPath();
      httpResponse = client.post(path, "application/octet-stream", requestBytes);
    } catch (IOException e) {
      throw makeException("I/O error", e, requestProto);
    }

    if (httpResponse.getStatusCode() != 200) {
      throw makeException("unexpected HTTP response: " + httpResponse.getStatusCode(),
          null, requestProto);
    }

    RemoteApiPb.Response parsedResponse = new RemoteApiPb.Response();
    parsedResponse.parseFrom(httpResponse.getBodyAsBytes());
    return parsedResponse;
  }

  void resetRpcCount() {
    rpcCount = 0;
  }

  int getRpcCount() {
    return rpcCount;
  }

  private static final AtomicLong requestId = new AtomicLong();

  private static RemoteApiPb.Request makeRequest(String packageName, String methodName,
      byte[] payload) {
    RemoteApiPb.Request result = new RemoteApiPb.Request();
    result.setServiceName(packageName);
    result.setMethod(methodName);
    result.setRequestAsBytes(payload);
    result.setRequestId(Long.toString(requestId.incrementAndGet()));

    return result;
  }

  private static Object parseJavaException(RemoteApiPb.Response parsedResponse, String packageName,
      String methodName) {
    try {
      InputStream ins = new ByteArrayInputStream(parsedResponse.getJavaExceptionAsBytes());
      ObjectInputStream in = new ObjectInputStream(ins);
      return in.readObject();
    } catch (IOException e) {
      throw new RemoteApiException(
          "remote API call: " + "can't deserialize server-side exception", packageName, methodName,
          e);
    } catch (ClassNotFoundException e) {
      throw new RemoteApiException(
          "remote API call: " + "can't deserialize server-side exception", packageName, methodName,
          e);
    }
  }

  private static RemoteApiException makeException(String message, Throwable cause,
      RemoteApiPb.Request request) {
    logger.log(Level.FINE, "remote API call: {0}", message);
    return new RemoteApiException("remote API call: " + message,
        request.getServiceName(), request.getMethod(), cause);
  }

  RemoteApiClient getClient() {
    return client;
  }
}
TOP

Related Classes of com.google.appengine.tools.remoteapi.RemoteRpc

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.