App Engine Java SDK version 1.9.14
[gae.git] / java / src / main / com / google / appengine / tools / remoteapi / HostedRemoteApiDelegate.java
blob07af36117bd8fb5791bb2398465c79cbce8e853e
1 // Copyright 2011 Google. All Rights Reserved.
2 package com.google.appengine.tools.remoteapi;
4 import com.google.apphosting.api.ApiProxy;
5 import com.google.apphosting.api.ApiProxy.ApiConfig;
6 import com.google.apphosting.api.ApiProxy.Delegate;
7 import com.google.apphosting.api.ApiProxy.Environment;
9 import java.util.List;
10 import java.util.concurrent.ExecutionException;
11 import java.util.concurrent.Future;
12 import java.util.concurrent.TimeUnit;
14 /**
15 * {@link RemoteApiDelegate} implementation for use inside an App Engine
16 * container. We let the {@link #containerDelegate} handle calls to the url
17 * fetch service for local fulfillment since there's little to be gained from
18 * asking some other app to make the same outbound call. If a good reason for
19 * doing this pops up we can add a config option that will let people opt-in to
20 * this behavior.
23 class HostedRemoteApiDelegate extends RemoteApiDelegate {
24 private final Delegate<Environment> containerDelegate;
26 public HostedRemoteApiDelegate(RemoteRpc rpc, RemoteApiOptions options,
27 Delegate<Environment> containerDelegate) {
28 super(rpc, options);
29 if (containerDelegate == null) {
30 throw new IllegalArgumentException("Options indicate we are running in an App Engine "
31 + "container but App Engine services are not available.");
33 this.containerDelegate = containerDelegate;
36 @Override
37 public byte[] makeSyncCall(Environment env, String serviceName, String methodName,
38 byte[] request) {
39 if (serviceName.equals("urlfetch")) {
40 return containerDelegate.makeSyncCall(env, serviceName, methodName, request);
42 return makeDefaultSyncCall(serviceName, methodName, request);
45 @Override
46 public Future<byte[]> makeAsyncCall(Environment env, String serviceName,
47 String methodName, byte[] request, ApiConfig apiConfig) {
48 try {
49 return new FakeFuture<byte[]>(makeSyncCall(env, serviceName, methodName, request));
50 } catch (Exception e) {
51 return new FakeFuture<byte[]>(e);
55 @Override
56 public void log(Environment environment, ApiProxy.LogRecord record) {
57 containerDelegate.log(environment, record);
60 @Override
61 public List<Thread> getRequestThreads(Environment environment) {
62 return containerDelegate.getRequestThreads(environment);
65 @Override
66 public void flushLogs(Environment environment) {
67 containerDelegate.flushLogs(environment);
70 @Override
71 public void shutdown() {
74 /**
75 * Wraps an already-resolved result in a {@link Future}.
76 * @param <T> The type of the Future.
78 private static class FakeFuture<T> implements Future<T> {
79 private final T result;
80 private final Exception exception;
82 FakeFuture(T result) {
83 this(result, null);
86 FakeFuture(Exception e) {
87 this(null, e);
90 private FakeFuture(T result, Exception exception) {
91 this.result = result;
92 this.exception = exception;
95 @Override
96 public boolean cancel(boolean mayInterruptIfRunning) {
97 return false;
100 @Override
101 public boolean isCancelled() {
102 return false;
105 @Override
106 public boolean isDone() {
107 return true;
110 @Override
111 public T get() throws ExecutionException {
112 if (exception != null) {
113 throw new ExecutionException(exception);
115 return result;
118 @Override
119 public T get(long timeout, TimeUnit unit) throws ExecutionException {
120 if (exception != null) {
121 throw new ExecutionException(exception);
123 return result;