App Engine Java SDK version 1.9.14
[gae.git] / java / src / main / com / google / appengine / tools / remoteapi / RemoteApiOptions.java
blob543232abf94d37147dfb199076aa30a5bec73514
1 // Copyright 2010 Google Inc. All Rights Reserved.
3 package com.google.appengine.tools.remoteapi;
5 import com.google.api.client.auth.oauth2.Credential;
6 import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
7 import com.google.api.client.googleapis.compute.ComputeCredential;
8 import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
9 import com.google.api.client.http.HttpTransport;
10 import com.google.api.client.json.jackson.JacksonFactory;
11 import com.google.apphosting.api.ApiProxy;
12 import com.google.common.collect.ImmutableList;
14 import java.io.File;
15 import java.io.IOException;
16 import java.security.GeneralSecurityException;
17 import java.security.PrivateKey;
18 import java.util.List;
20 /**
21 * A mutable object containing settings for installing the remote API.
23 * <p>Example for connecting to a development app server:</p>
25 * <pre>
26 * RemoteApiOptions options = new RemoteApiOptions()
27 * .server("localhost", 8888),
28 * .credentials("username", "password does not matter");
29 * </pre>
31 * <p>Example for connecting to a deployed app:</p>
33 * <pre>
34 * RemoteApiOptions options = new RemoteApiOptions()
35 * .server("myappid.appspot.com", 443),
36 * .credentials(adminUsername, adminPassword);
37 * </pre>
39 * <p>
40 * The options should be passed to {@link RemoteApiInstaller#install}.
41 * </p>
44 public class RemoteApiOptions {
46 private static final List<String> OAUTH_SCOPES = ImmutableList.of(
47 "https://www.googleapis.com/auth/appengine.apis",
48 "https://www.googleapis.com/auth/userinfo.email");
50 private static final String LOCAL_USER = "test@example.com";
51 private static final String LOCAL_PASSWORD = "";
53 private String hostname;
54 private int port;
55 private String userEmail;
56 private String password;
57 private String credentialsToReuse;
58 private String remoteApiPath = "/remote_api";
59 private int maxConcurrentRequests = 5;
60 private int datastoreQueryFetchSize = 500;
61 private int maxHttpResponseSize = 33 * 1024 * 1024;
63 private Credential oauthCredential;
64 private HttpTransport httpTransport;
66 public RemoteApiOptions() {}
68 RemoteApiOptions(RemoteApiOptions original) {
69 this.hostname = original.hostname;
70 this.port = original.port;
71 this.userEmail = original.userEmail;
72 this.password = original.password;
73 this.credentialsToReuse = original.credentialsToReuse;
74 this.remoteApiPath = original.remoteApiPath;
75 this.maxConcurrentRequests = original.maxConcurrentRequests;
76 this.datastoreQueryFetchSize = original.datastoreQueryFetchSize;
77 this.maxHttpResponseSize = original.maxHttpResponseSize;
78 this.oauthCredential = original.oauthCredential;
79 this.httpTransport = original.httpTransport;
82 /**
83 * Sets the host and port port where we will connect.
85 public RemoteApiOptions server(String newHostname, int newPort) {
86 hostname = newHostname;
87 port = newPort;
88 return this;
91 /**
92 * Sets a username and password to be used for logging in via the
93 * ClientLogin API. Overrides any previously-provided credentials.
95 public RemoteApiOptions credentials(String newUserEMail, String newPassword) {
96 userEmail = newUserEMail;
97 password = newPassword;
98 credentialsToReuse = null;
99 oauthCredential = null;
100 return this;
104 * Reuses credentials from another AppEngineClient. Credentials can only
105 * be reused from a client with the same hostname and user. Overrides any
106 * previously-provided credentials.
107 * @param newUserEmail the email address of the user we want to log in as.
108 * @param serializedCredentials a string returned by calling
109 * {@link AppEngineClient#serializeCredentials} on the previous client
111 public RemoteApiOptions reuseCredentials(String newUserEmail, String serializedCredentials) {
112 userEmail = newUserEmail;
113 password = null;
114 credentialsToReuse = serializedCredentials;
115 oauthCredential = null;
116 return this;
120 * Use a Compute Engine credential for authentication. Overrides any
121 * previously-provided credentials.
123 RemoteApiOptions useComputeEngineCredential() {
124 try {
125 HttpTransport transport = getOrCreateHttpTransportForOAuth();
126 ComputeCredential credential = new ComputeCredential(transport, new JacksonFactory());
127 credential.refreshToken();
128 setOAuthCredential(credential);
129 } catch (IOException|GeneralSecurityException e) {
130 throw new RuntimeException("Failed to acquire Google Compute Engine credential.", e);
132 return this;
136 * Use a service account credential. Overrides any previously-provided
137 * credentials.
139 RemoteApiOptions useServiceAccountCredential(String serviceAccount,
140 String p12PrivateKeyFile) {
141 try {
142 Credential credential = getCredentialBuilder(serviceAccount)
143 .setServiceAccountPrivateKeyFromP12File(new File(p12PrivateKeyFile))
144 .build();
145 setOAuthCredential(credential);
146 } catch (IOException|GeneralSecurityException e) {
147 throw new RuntimeException("Failed to build service account credential.", e);
149 return this;
153 * Use a service account credential. Overrides any previously-provided
154 * credentials.
156 RemoteApiOptions useServiceAccountCredential(String serviceAccount,
157 PrivateKey privateKey) {
158 try {
159 Credential credential = getCredentialBuilder(serviceAccount)
160 .setServiceAccountPrivateKey(privateKey)
161 .build();
162 setOAuthCredential(credential);
163 } catch (IOException|GeneralSecurityException e) {
164 throw new RuntimeException("Failed to build service account credential.", e);
166 return this;
170 * Use credentials appropriate for talking to the Development Server.
171 * Overrides any previously-provided credentials.
173 RemoteApiOptions useDevelopmentServerCredential() {
174 credentials(LOCAL_USER, LOCAL_PASSWORD);
175 return this;
178 private GoogleCredential.Builder getCredentialBuilder(
179 String serviceAccount) throws GeneralSecurityException, IOException {
180 HttpTransport transport = getOrCreateHttpTransportForOAuth();
181 JacksonFactory jsonFactory = new JacksonFactory();
182 return new GoogleCredential.Builder()
183 .setTransport(transport)
184 .setJsonFactory(jsonFactory)
185 .setServiceAccountId(serviceAccount)
186 .setServiceAccountScopes(OAUTH_SCOPES);
189 RemoteApiOptions oauthCredential(Credential oauthCredential) {
190 setOAuthCredential(oauthCredential);
191 return this;
194 private void setOAuthCredential(Credential oauthCredential) {
195 userEmail = null;
196 password = null;
197 credentialsToReuse = null;
198 this.oauthCredential = oauthCredential;
201 RemoteApiOptions httpTransport(HttpTransport httpTransport) {
202 this.httpTransport = httpTransport;
203 return this;
207 * Sets the path used to access the remote API. If not set, the default
208 * is /remote_api.
210 public RemoteApiOptions remoteApiPath(String newPath) {
211 remoteApiPath = newPath;
212 return this;
216 * This parameter controls the maximum number of async API requests that will be
217 * in flight at once. Each concurrent request will likely be handled by a separate
218 * <a href="http://code.google.com/appengine/docs/adminconsole/instances.html"
219 * >instance</a> of your App. Having more instances increases throughput but may
220 * result in errors due to exceeding quota. Defaults to 5.
222 public RemoteApiOptions maxConcurrentRequests(int newValue) {
223 maxConcurrentRequests = newValue;
224 return this;
228 * When executing a datastore query, this is the number of results to fetch
229 * per HTTP request. Increasing this value will reduce the number of round trips
230 * when running large queries, but too high a value can be wasteful when not
231 * all results are needed. Defaults to 500.
233 * <p>(This value can be overridden by the code using the datastore API.)</p>
235 public RemoteApiOptions datastoreQueryFetchSize(int newValue) {
236 datastoreQueryFetchSize = newValue;
237 return this;
241 * When making a remote call, this is the maximum size of the HTTP response.
242 * The default is 33M. Normally there's no reason to change this. This
243 * setting has no effect when running in an App Engine container.
245 public RemoteApiOptions maxHttpResponseSize(int newValue) {
246 maxHttpResponseSize = newValue;
247 return this;
250 public RemoteApiOptions copy() {
251 return new RemoteApiOptions(this);
255 * Create an {@link HttpTransport} appropriate to this environment or return
256 * the one that's already been created. This method ensures that the
257 * determination of whether we're running in App Engine happens early
258 * (specifically, before the Remote API has been installed) and that said
259 * determination is remembered.
261 private HttpTransport getOrCreateHttpTransportForOAuth()
262 throws IOException, GeneralSecurityException {
263 if (httpTransport != null) {
264 return httpTransport;
267 if (ApiProxy.getCurrentEnvironment() != null) {
268 throw new IllegalStateException(
269 "OAuth-based authorization not supported for clients running on App Engine");
272 httpTransport = GoogleNetHttpTransport.newTrustedTransport();
273 return httpTransport;
276 HttpTransport getHttpTransport() {
277 return httpTransport;
280 public String getHostname() {
281 return hostname;
284 public int getPort() {
285 return port;
288 public String getUserEmail() {
289 return userEmail;
292 public String getPassword() {
293 return password;
296 public String getCredentialsToReuse() {
297 return credentialsToReuse;
300 Credential getOAuthCredential() {
301 return oauthCredential;
304 public String getRemoteApiPath() {
305 return remoteApiPath;
308 public int getMaxConcurrentRequests() {
309 return maxConcurrentRequests;
312 public int getDatastoreQueryFetchSize() {
313 return datastoreQueryFetchSize;
316 public int getMaxHttpResponseSize() {
317 return maxHttpResponseSize;