Revision created by MOE tool push_codebase.
[gae.git] / java / src / main / com / google / appengine / tools / admin / AppAdminFactory.java
blobd41203ea5f0d7ab452552102cb95d7e45c68409d
1 // Copyright 2008 Google Inc. All Rights Reserved.
3 package com.google.appengine.tools.admin;
5 import com.google.appengine.tools.info.SdkInfo;
6 import com.google.appengine.tools.util.ClientCookieManager;
8 import java.io.File;
9 import java.io.PrintWriter;
10 import java.nio.charset.Charset;
11 import java.util.Collections;
12 import java.util.Set;
14 /**
15 * Creates a new {@link AppAdmin} for a designated App Engine application.
18 public class AppAdminFactory {
20 private static final String JAVA_CMD_PROP = "appengine.java";
21 private static final String JAVAC_CMD_PROP = "appengine.javac";
23 private ApplicationProcessingOptions appOptions = new ApplicationProcessingOptions();
25 private Class<? extends AppVersionUpload> appVersionUploadClass = AppVersionUpload.class;
27 /**
28 * Creates a new {@link AppAdmin} that can be used to administer the
29 * designated App Engine application.
31 * @param options The options used to connect to the remote server. Must not
32 * be {@code null}.
33 * @param app The application to be administered. May be {@code null}.
34 * @param errorWriter A writer to which error logs can be written. The logs
35 * can be used for diagnosis if a failure occurs during operation. May
36 * be {@code null}.
37 * @return a not {@code null} AppAdmin
39 public AppAdmin createAppAdmin(ConnectOptions options, Application app, PrintWriter errorWriter) {
40 return new AppAdminImpl(options, app, errorWriter, appOptions, appVersionUploadClass);
43 /**
44 * Creates a new {@link AppAdmin} that can be used to administer the
45 * designated App Engine application.
47 * @param options The options used to connect to the remote server. Must not
48 * be {@code null}.
49 * @param app The application to be administered. May be {@code null}.
50 * @param errorWriter A writer to which error logs can be written. The logs
51 * can be used for diagnosis if a failure occurs during operation. May
52 * be {@code null}.
53 * @return a not {@code null} AppAdmin
55 public AppAdmin createAppAdmin(ConnectOptions options, GenericApplication app,
56 PrintWriter errorWriter) {
57 return new AppAdminImpl(options, app, errorWriter, appOptions, appVersionUploadClass);
60 public ApplicationProcessingOptions getAppOptions() {
61 return appOptions;
64 public Class<? extends AppVersionUpload> getAppVersionUploadClass() {
65 return appVersionUploadClass;
68 /**
69 * Sets the class used for uploading the application to the server. Should
70 * only be used for advanced customization of the upload process.
72 public void setAppVersionUploadClass(Class<? extends AppVersionUpload> klass) {
73 appVersionUploadClass = klass;
76 /**
77 * Callback that is invoked to prompt the user to enter a password.
79 public interface PasswordPrompt {
80 String getPassword();
83 /**
84 * The options used to connect to the remote App Engine administration server.
87 public static class ConnectOptions {
89 /**
90 * Retrieves the user's email address used to authenticate to the server.
92 * @return user identity
94 public String getUserId() {
95 return userId;
98 /**
99 * The user id for the App Engine account. This should be the same e-mail
100 * address used to register the account owning the App Engine application.
102 * @param userId the not {@code null} e-mail address
104 public void setUserId(String userId) {
105 this.userId = userId;
109 * Retrieves the prompter used to get the user's password.
111 * @return the {@link PasswordPrompt} to be used
113 public PasswordPrompt getPasswordPrompt() {
114 return passwordPrompt;
118 * The password prompt to get the user's password.
120 * @param prompt the {@link PasswordPrompt} that's being used
122 public void setPasswordPrompt(PasswordPrompt prompt) {
123 this.passwordPrompt = prompt;
126 /** Returns the server address to connect to. */
127 public String getServer() {
128 return server;
132 * The remote administration server to connect to. This is an advanced
133 * option that should rarely be set by users.
135 * @param server May be set to {@code null} to use the default server.
137 public void setServer(String server) {
138 this.server = server;
142 * Returns the value used for the Host header sent to the server with RPCs.
144 * @return hostname to insert into request headers
146 public String getHost() {
147 return host;
151 * The host name to supply to the remote server. This is an advanced option
152 * that should rarely be set by users.
154 * @param host May be set to {@code null} to use the default host name.
156 public void setHost(String host) {
157 this.host = host;
161 * Controls whether we clean up our temporary files, or leave it for
162 * debugging.
164 public void setRetainUploadDir(boolean flag) {
165 this.keepUpload = flag;
168 /** Returns {@code true} if the upload directory should not be deleted. */
169 public boolean getRetainUploadDir() {
170 return keepUpload;
173 /** Returns the location of the AppEngine SDK directory. */
174 public String getSdkRoot() {
175 return sdkRoot;
179 * A file path to the top directory of the Google App Engine SDK.
181 * @param sdkRoot the not {@code null} path to the SDK
183 public void setSdkRoot(String sdkRoot) {
184 this.sdkRoot = sdkRoot;
188 * Retrieves the current cookie manager.
190 * @return the cookie manager set with
191 * {@link #setCookies(ClientCookieManager)}.
193 public ClientCookieManager getCookies() {
194 return cookies;
198 * Associates a {@link ClientCookieManager} to store cookies received from
199 * the server, for later reuse in other requests.
201 * @param cookies the cookie manager to use
203 public void setCookies(ClientCookieManager cookies) {
204 this.cookies = cookies;
208 * Returns whether to use HTTPS for communicating with the Admin Console. By
209 * default, this returns true.
211 public boolean getSecure() {
212 return secure;
216 * Sets whether to use HTTPS for communicating with the Admin Console.
218 * @param secure true for HTTPS, false for HTTP
220 public void setSecure(boolean secure) {
221 this.secure = secure;
225 * Sets the OAuth 2.0 token to use for authentication (instead of requiring
226 * a username and password).
228 public void setOauthToken(String oauthToken) {
229 this.oauthToken = oauthToken;
233 * Returns the OAuth 2.0 token being used for authentication, or {@code
234 * null} if none.
236 public String getOauthToken() {
237 return oauthToken;
241 * Sets whether to use persisted credentials (load/save to/from disk).
243 public void setUsePersistedCredentials(boolean usePersistedCredentials) {
244 this.usePersistedCredentials = usePersistedCredentials;
248 * Returns whether to use persisted credentials (load/save to/from disk).
250 public boolean getUsePersistedCredentials() {
251 return usePersistedCredentials;
254 private String userId;
255 private String server = SdkInfo.getDefaultServer();
256 private String host;
257 private String sdkRoot;
258 boolean keepUpload;
259 private ClientCookieManager cookies;
260 private PasswordPrompt passwordPrompt;
261 private boolean secure = true;
262 private String oauthToken;
263 private boolean usePersistedCredentials = true;
265 @Override
266 public boolean equals(Object o) {
267 if (this == o) {
268 return true;
270 if (o == null || getClass() != o.getClass()) {
271 return false;
273 ConnectOptions that = (ConnectOptions) o;
275 if (host != null ? !host.equals(that.host) : that.host != null) {
276 return false;
278 if (server != null ? !server.equals(that.server) : that.server != null) {
279 return false;
281 if (userId != null ? !userId.equals(that.userId) : that.userId != null) {
282 return false;
284 if (sdkRoot != null ? !sdkRoot.equals(that.sdkRoot) : that.sdkRoot != null) {
285 return false;
288 return true;
291 @Override
292 public int hashCode() {
293 int result;
294 result = (userId != null ? userId.hashCode() : 0);
295 result = 31 * result + (server != null ? server.hashCode() : 0);
296 result = 31 * result + (host != null ? host.hashCode() : 0);
297 result = 31 * result + (sdkRoot != null ? sdkRoot.hashCode() : 0);
298 return result;
303 * Options used in preparing an application directory for upload.
305 public static class ApplicationProcessingOptions {
306 private File java;
307 private File javac;
308 private boolean compileJsps = true;
309 private boolean doBatch = true;
310 private String compileEncoding = "UTF-8";
311 private boolean splitJars = false;
312 private boolean jarJSPs = true;
313 private boolean jarClasses = false;
314 private boolean deleteJSPs = false;
315 private Set<String> splitExcludes = Collections.emptySet();
316 private String runtime;
317 private boolean allowAnyRuntime = false;
318 private boolean failOnPrecompilationError = false;
319 private boolean ignoreEndpointsFailures = true;
320 private boolean quickstart = false;
323 * Returns an appropriate "java" executable. If a prior call to
324 * {@link #setJavaExecutable(File)} was made, that value is returned (on
325 * windows, the algorithm is forgiving if ".exe" was omitted, and will add
326 * it). If not, the system property {@code java.home} is used to identify
327 * the currently-running JVM, and if that directory contains a file named
328 * {@code bin/java} (Unix) or {@code bin\\java.exe} (Windows), that is
329 * returned.
331 * @return the Java executable, as a {@link File}.
332 * @throws IllegalStateException if the java cannot be found by the
333 * heuristic above, but {@link #setJavaExecutable(File)} has not
334 * been called, or if it has been called, but the specified file
335 * cannot be found.
337 public File getJavaExecutable() {
338 if (java != null) {
339 return java;
342 String javaProp = System.getProperty(JAVA_CMD_PROP);
343 if (javaProp != null) {
344 java = new File(javaProp);
345 if (!java.exists()) {
346 if (Utility.isOsWindows() && !javaProp.endsWith(".exe")
347 && (new File(javaProp + ".exe")).exists()) {
348 java = new File(javaProp + ".exe");
349 } else {
350 throw new IllegalStateException("cannot find java executable \"" + javaProp + "\"");
353 } else {
354 String javaHome = System.getProperty("java.home");
355 String javaCmd =
356 javaHome + File.separator + "bin" + File.separator + "java"
357 + (Utility.isOsWindows() ? ".exe" : "");
358 java = new File(javaCmd);
359 if (!java.exists()) {
360 java = null;
361 throw new IllegalStateException("cannot find java executable "
362 + "based on java.home, tried \"" + javaCmd + "\"");
365 return java;
369 * Explicitly requests a specific {@code java} program be used for launched
370 * tasks, such as compiling JSP files.
372 * @param java the executable file to run.
374 void setJavaExecutable(File java) {
375 this.java = java;
379 * Returns an appropriate "javac" executable. If a prior call to
380 * {@link #setJavaCompiler(File)} was made, that value is returned (on
381 * windows, the algorithm is forgiving if ".exe" was omitted, and will add
382 * it). If not, the system property {@code java.home} is used to identify
383 * the currently-running JVM. If that pathname ends with "jre", then its
384 * parent is used instead as a hoped-for JDK root. If that directory
385 * contains a file named {@code bin/javac} (Unix) or {@code bin\\javac.exe}
386 * (Windows), that is returned.
388 * @return the Java compiler, as a {@link File}.
389 * @throws IllegalStateException if the javac cannot be found by the
390 * heuristic above, but {@link #setJavaCompiler(File)} has not be
391 * called, or if it has been called but the file does not exist.
393 public File getJavaCompiler() {
394 if (javac != null) {
395 return javac;
398 String javacProp = System.getProperty(JAVAC_CMD_PROP);
399 if (javacProp != null) {
400 javac = new File(javacProp);
401 if (!javac.exists()) {
402 if (Utility.isOsWindows() && !javacProp.endsWith(".exe")
403 && (new File(javacProp + ".exe")).exists()) {
404 javac = new File(javacProp + ".exe");
405 } else {
406 throw new IllegalStateException("cannot find javac executable \"" + javacProp + "\"");
409 } else {
410 String javaHome = System.getProperty("java.home");
411 String javacDir = javaHome;
412 String javacCmd =
413 javacDir + File.separator + "bin" + File.separator + "javac"
414 + (Utility.isOsWindows() ? ".exe" : "");
415 javac = new File(javacCmd);
416 if (!javac.exists()) {
417 javac = null;
418 javacDir = (new File(javaHome)).getParentFile().getPath();
419 String javacCmd2 =
420 javacDir + File.separator + "bin" + File.separator + "javac"
421 + (Utility.isOsWindows() ? ".exe" : "");
422 javac = new File(javacCmd2);
423 if (!javac.exists()) {
424 javac = null;
425 throw new IllegalStateException("cannot find javac executable "
426 + "based on java.home, tried \"" + javacCmd + "\" and \"" + javacCmd2 + "\"");
430 return javac;
434 * Explicitly requests a specific {@code javac} program be used for launched
435 * Java compilations, such as compiling JSP files into classes.
437 * @param javac the executable file to run.
439 void setJavaCompiler(File javac) {
440 this.javac = javac;
443 /** Returns whether we should attempt to compile JSPs */
444 public boolean isCompileJspsSet() {
445 return compileJsps;
449 * Requests that *.jsp files should be compiled into Java byte code, or if
450 * false should be left untouched.
452 * @param doJsps {@code true} to compile .jsp files
454 void setCompileJsps(boolean doJsps) {
455 this.compileJsps = doJsps;
459 * Returns whether we should use batch upload
461 public boolean isBatchModeSet() {
462 return doBatch;
466 * Requests we use the upload batch mode
468 * @param doBatch {@code true} to use batch mode
470 void setBatchMode(boolean doBatch) {
471 this.doBatch = doBatch;
474 public String getCompileEncoding() {
475 return compileEncoding;
478 public void setCompileEncoding(String compileEncoding) {
479 this.compileEncoding = compileEncoding;
482 /** Returns whether we should split large jar files. */
483 public boolean isSplitJarsSet() {
484 return splitJars;
487 /** Sets whether we should split large jar files. */
488 public void splitJars(boolean b) {
489 splitJars = b;
492 /** Sets whether we should jar the classes generated from JSPs. */
493 public void setJarJSPs(boolean b) {
494 jarJSPs = b;
497 /** Returns whether we should jar the classes generated from JSPs. */
498 public boolean isJarJSPsSet() {
499 return jarJSPs;
502 /** Sets whether we should jar the WEB-INF/classes content. */
503 public void setJarClasses(boolean b) {
504 jarClasses = b;
507 /** Returns whether we should jar the WEB-INF/classes content. */
508 public boolean isJarClassesSet() {
509 return jarClasses;
512 /** Sets whether we should delete the JSP source files. */
513 public void setDeleteJSPs(boolean b) {
514 deleteJSPs = b;
517 /** Returns whether we should delete the JSP source files. */
518 public boolean isDeleteJSPs() {
519 return deleteJSPs;
523 * Sets suffixes of filenames to exclude when splitting jars.
525 * @param jarSplittingExcludeSuffixes suffixes of filenames to exclude when
526 * splitting jars.
528 void setJarSplittingExcludes(Set<String> jarSplittingExcludeSuffixes) {
529 splitExcludes = jarSplittingExcludeSuffixes;
533 * Returns the set of suffixes of filenames that should be excluded when
534 * splitting jars.
536 * @return a set of suffixes of filenames to exclude.
538 public Set<String> getJarSplittingExcludes() {
539 return splitExcludes;
542 /** Sets the runtime id. */
543 public void setRuntime(String s) {
544 runtime = s;
547 /** Returns the runtime id. */
548 public String getRuntime() {
549 return runtime;
552 /** Sets whether to skip validation of the runtime id provided by the user. */
553 public void setAllowAnyRuntime(boolean b) {
554 allowAnyRuntime = b;
557 /** Returns whether to skip validation of the runtime id provided by the user. */
558 public boolean isAllowAnyRuntime() {
559 return allowAnyRuntime;
562 /** Sets whether to abort an update in case precompilation fails. */
563 public void setFailOnPrecompilationError(boolean b) {
564 failOnPrecompilationError = b;
567 /** Returns whether to abort an update in case precompilation fails. */
568 public boolean isFailOnPrecompilationError() {
569 return failOnPrecompilationError;
572 /** Sets whether Endpoints config update failures should be ignored. */
573 public void setIgnoreEndpointsFailures(boolean b) {
574 ignoreEndpointsFailures = b;
577 /** Return whether Endpoints config update failures should be ignored. */
578 public boolean isIgnoreEndpointsFailures() {
579 return ignoreEndpointsFailures;
582 /** Sets whether Quickstart should be applied when staging */
583 public void setQuickstart(boolean b) {
584 quickstart = b;
587 /** Return whether Quickstart should be applied when staging */
588 public boolean isQuickstart() {
589 return quickstart;
594 * Specifies the location of a java executable, used when compiling JSPs. By
595 * default, the system property {@code java.home} is used to identify the
596 * currently-running JVM, and if that directory contains a file named {@code
597 * bin/java} (Unix) or {@code bin\\java.exe} (Windows), that is returned.
599 * @param java the Java executable to be used.
601 public void setJavaExecutable(File java) {
602 appOptions.setJavaExecutable(java);
606 * Specifies the location of a javac executable, used when compiling JSPs. By
607 * default, the system property {@code java.home} is used to identify the
608 * currently-running JVM. If that pathname ends with "jre", then its parent is
609 * used instead as a hoped-for JDK root. If that directory contains a file
610 * named {@code bin/javac} (Unix) or {@code bin\\javac.exe} (Windows), that is
611 * returned.
613 * @param javac the Java compiler executable to be used.
615 public void setJavaCompiler(File javac) {
616 appOptions.setJavaCompiler(javac);
620 * Requests that *.jsp files should be compiled into Java byte code, or if
621 * false should be left untouched.
623 * @param flag {@code true} to compile .jsp files
625 public void setCompileJsps(boolean flag) {
626 appOptions.setCompileJsps(flag);
630 * Requests we do upload using batch
632 * @param flag {@code true} to use batch mode for upload
634 public void setBatchMode(boolean flag) {
635 appOptions.setBatchMode(flag);
639 * Enables or disables jar splitting.
641 * @param doSplit {@code false} to leave jars unsplit, and perhaps fail to
642 * upload due to large files, {@code true} to split into chunks of some
643 * uploadable size.
645 public void setJarSplittingEnabled(boolean doSplit) {
646 appOptions.splitJars(doSplit);
650 * Enables or disables jarring classes generated from JSPs.
652 * @param doJarJSPs {@code true} to jar the generated classes from JSPs.
654 public void setJarJSPsEnabled(boolean doJarJSPs) {
655 appOptions.setJarJSPs(doJarJSPs);
659 * Enables or disables jarring WEB-INF/classes content.
661 * @param doJarClasses {@code true} to jar the WEB-INF/classes content.
663 public void setJarClassessEnabled(boolean doJarClasses) {
664 appOptions.setJarClasses(doJarClasses);
668 * Deletes or not the JSPs source files.
670 * @param deleteJSPs {@code true} remove all JSPs source (not needed after compilation).
672 public void setDeleteJSPs(boolean deleteJSPs) {
673 appOptions.setDeleteJSPs(deleteJSPs);
677 * Sets suffixes for files to exclude when performing jar splitting.
679 * @param jarSplittingExcludeSuffixes a set of filename suffixes to exclude
680 * when performing jar splitting.
682 public void setJarSplittingExcludes(Set<String> jarSplittingExcludeSuffixes) {
683 appOptions.setJarSplittingExcludes(jarSplittingExcludeSuffixes);
687 * Sets the character encoding to use when compiling JSP files.
689 * @throws IllegalArgumentException If the specified encoding is illegal or
690 * not supported.
692 public void setCompileEncoding(String compileEncoding) {
693 Charset.forName(compileEncoding);
694 appOptions.setCompileEncoding(compileEncoding);
698 * Sets the runtime id to use in the generated app.yaml descriptor.
700 * @param runtime the runtime id to use.
702 public void setRuntime(String runtime) {
703 appOptions.setRuntime(runtime);
707 * Enables or disables validation of the runtime id provided by the user.
709 * @param allowAnyRuntime {@code true} to allow an arbitrary runtime id value,
710 * {@code false} to validate it against the list of supported runtimes.
712 public void setAllowAnyRuntime(boolean allowAnyRuntime) {
713 appOptions.setAllowAnyRuntime(allowAnyRuntime);
717 * Enables or disables treating (repeated) precompilation errors as fatal when
718 * updating an application.
720 * @param fail {@code true} to abort an update if precompilation fails,
721 * {@code false} to treat it as a warning and continue updating the application.
723 public void setFailOnPrecompilationError(boolean fail) {
724 appOptions.setFailOnPrecompilationError(fail);
728 * Enables or disables ignoring Google Cloud Endpoints failures when updating an app.
730 * @param ignore {@code true} to ignore errors updating the Endpoints configuration,
731 * {@code false} to allow them to abort the update.
733 public void setIgnoreEndpointsFailures(boolean ignore) {
734 appOptions.setIgnoreEndpointsFailures(ignore);
737 public void setQuickstart(boolean enable) {
738 appOptions.setQuickstart(enable);