Revision created by MOE tool push_codebase.
[gae.git] / java / src / main / com / google / apphosting / utils / config / AppEngineWebXml.java
blobf662a067797689d7becafca7a679124c556ad1eb
1 // Copyright 2008 Google Inc. All Rights Reserved.
2 package com.google.apphosting.utils.config;
4 import com.google.common.base.StringUtil;
5 import com.google.common.collect.Lists;
6 import com.google.common.collect.Maps;
8 import java.security.Permissions;
9 import java.security.UnresolvedPermission;
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.LinkedHashMap;
13 import java.util.LinkedHashSet;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Objects;
17 import java.util.Set;
18 import java.util.regex.Pattern;
20 /**
21 * Struct describing the config data that lives in WEB-INF/appengine-web.xml.
23 * Any additions to this class should also be made to the YAML
24 * version in AppYaml.java.
27 public class AppEngineWebXml {
28 /**
29 * Enumeration of supported scaling types.
31 public static enum ScalingType {AUTOMATIC, MANUAL, BASIC}
33 private final Map<String, String> systemProperties = Maps.newHashMap();
35 private final Map<String, String> betaSettings = Maps.newLinkedHashMap();
37 private final HealthCheck healthCheck;
39 private final Resources resources;
41 private final Network network;
43 private final Map<String, String> envVariables = Maps.newHashMap();
45 private final List<UserPermission> userPermissions = new ArrayList<UserPermission>();
47 public static final String WARMUP_SERVICE = "warmup";
49 public static final String URL_HANDLER_URLFETCH = "urlfetch";
50 public static final String URL_HANDLER_NATIVE= "native";
52 private String appId;
54 private String majorVersionId;
56 private String module;
57 private String instanceClass;
59 private final AutomaticScaling automaticScaling;
60 private final ManualScaling manualScaling;
61 private final BasicScaling basicScaling;
63 private String sourceLanguage;
64 private boolean sslEnabled = true;
65 private boolean useSessions = false;
66 private boolean asyncSessionPersistence = false;
67 private String asyncSessionPersistenceQueueName;
69 private final List<StaticFileInclude> staticFileIncludes;
70 private final List<String> staticFileExcludes;
71 private final List<String> resourceFileIncludes;
72 private final List<String> resourceFileExcludes;
74 private Pattern staticIncludePattern;
75 private Pattern staticExcludePattern;
76 private Pattern resourceIncludePattern;
77 private Pattern resourceExcludePattern;
79 private String publicRoot = "";
81 private String appRoot;
83 private final Set<String> inboundServices;
84 private boolean precompilationEnabled = true;
86 private final List<AdminConsolePage> adminConsolePages = new ArrayList<AdminConsolePage>();
87 private final List<ErrorHandler> errorHandlers = new ArrayList<ErrorHandler>();
89 private ClassLoaderConfig classLoaderConfig;
91 private String urlStreamHandlerType = null;
93 private boolean threadsafe = false;
94 private boolean threadsafeValueProvided = false;
96 private String autoIdPolicy;
98 private boolean codeLock = false;
99 private boolean useVm = false;
100 private ApiConfig apiConfig;
101 private final List<String> apiEndpointIds;
102 private Pagespeed pagespeed;
105 * Represent user's choice w.r.t the usage of Google's customized connector-j.
107 public static enum UseGoogleConnectorJ {
108 NOT_STATED_BY_USER,
109 TRUE,
110 FALSE,
112 private UseGoogleConnectorJ useGoogleConnectorJ = UseGoogleConnectorJ.NOT_STATED_BY_USER;
114 public AppEngineWebXml() {
115 automaticScaling = new AutomaticScaling();
116 manualScaling = new ManualScaling();
117 basicScaling = new BasicScaling();
118 healthCheck = new HealthCheck();
119 resources = new Resources();
120 network = new Network();
122 staticFileIncludes = new ArrayList<StaticFileInclude>();
123 staticFileExcludes = new ArrayList<String>();
124 staticFileExcludes.add("WEB-INF/**");
125 staticFileExcludes.add("**.jsp");
126 resourceFileIncludes = new ArrayList<String>();
127 resourceFileExcludes = new ArrayList<String>();
128 inboundServices = new LinkedHashSet<String>();
129 apiEndpointIds = new ArrayList<String>();
133 * @return An unmodifiable map whose entries correspond to the
134 * system properties defined in appengine-web.xml.
136 public Map<String, String> getSystemProperties() {
137 return Collections.unmodifiableMap(systemProperties);
140 public void addSystemProperty(String key, String value) {
141 systemProperties.put(key, value);
145 * @return An unmodifiable map whose entires correspond to the
146 * vm settings defined in appengine-web.xml.
148 public Map<String, String> getBetaSettings() {
149 return Collections.unmodifiableMap(betaSettings);
152 public void addBetaSetting(String key, String value) {
153 betaSettings.put(key, value);
156 public HealthCheck getHealthCheck() {
157 return healthCheck;
160 public Resources getResources() {
161 return resources;
164 public Network getNetwork() {
165 return network;
169 * @return An unmodifiable map whose entires correspond to the
170 * environment variables defined in appengine-web.xml.
172 public Map<String, String> getEnvironmentVariables() {
173 return Collections.unmodifiableMap(envVariables);
176 public void addEnvironmentVariable(String key, String value) {
177 envVariables.put(key, value);
180 public String getAppId() {
181 return appId;
184 public void setAppId(String appId) {
185 this.appId = appId;
188 public String getMajorVersionId() {
189 return majorVersionId;
192 public void setMajorVersionId(String majorVersionId) {
193 this.majorVersionId = majorVersionId;
196 public String getSourceLanguage() {
197 return this.sourceLanguage;
200 public void setSourceLanguage(String sourceLanguage) {
201 this.sourceLanguage = sourceLanguage;
204 public String getModule() {
205 return module;
209 * Sets instanceClass (aka class in the xml/yaml files). Normalizes empty and null
210 * inputs to null.
212 public void setInstanceClass(String instanceClass) {
213 this.instanceClass = StringUtil.toNullIfEmptyOrWhitespace(instanceClass);
216 public String getInstanceClass() {
217 return instanceClass;
220 public AutomaticScaling getAutomaticScaling() {
221 return automaticScaling;
224 public ManualScaling getManualScaling() {
225 return manualScaling;
228 public BasicScaling getBasicScaling() {
229 return basicScaling;
232 public ScalingType getScalingType() {
233 if (!getBasicScaling().isEmpty()) {
234 return ScalingType.BASIC;
235 } else if (!getManualScaling().isEmpty()) {
236 return ScalingType.MANUAL;
237 } else {
238 return ScalingType.AUTOMATIC;
242 public void setModule(String module) {
243 this.module = module;
246 public void setSslEnabled(boolean ssl) {
247 sslEnabled = ssl;
250 public boolean getSslEnabled() {
251 return sslEnabled;
254 public void setSessionsEnabled(boolean sessions) {
255 useSessions = sessions;
258 public boolean getSessionsEnabled() {
259 return useSessions;
262 public void setAsyncSessionPersistence(boolean asyncSessionPersistence) {
263 this.asyncSessionPersistence = asyncSessionPersistence;
266 public boolean getAsyncSessionPersistence() {
267 return asyncSessionPersistence;
270 public void setAsyncSessionPersistenceQueueName(String asyncSessionPersistenceQueueName) {
271 this.asyncSessionPersistenceQueueName = asyncSessionPersistenceQueueName;
274 public String getAsyncSessionPersistenceQueueName() {
275 return asyncSessionPersistenceQueueName;
278 public List<StaticFileInclude> getStaticFileIncludes() {
279 return staticFileIncludes;
282 public List<String> getStaticFileExcludes() {
283 return staticFileExcludes;
286 public StaticFileInclude includeStaticPattern(String pattern, String expiration) {
287 staticIncludePattern = null;
288 StaticFileInclude staticFileInclude = new StaticFileInclude(pattern, expiration);
289 staticFileIncludes.add(staticFileInclude);
290 return staticFileInclude;
293 public void excludeStaticPattern(String url) {
294 staticExcludePattern = null;
295 staticFileExcludes.add(url);
298 public List<String> getResourcePatterns() {
299 return resourceFileIncludes;
302 public List<String> getResourceFileExcludes() {
303 return resourceFileExcludes;
306 public void includeResourcePattern(String url) {
307 resourceExcludePattern = null;
308 resourceFileIncludes.add(url);
311 public void excludeResourcePattern(String url) {
312 resourceIncludePattern = null;
313 resourceFileExcludes.add(url);
316 public void addUserPermission(String className, String name, String actions) {
317 if (className.startsWith("java.")) {
318 throw new AppEngineConfigException("Cannot specify user-permissions for " +
319 "classes in java.* packages.");
322 userPermissions.add(new UserPermission(className, name, actions));
325 public Permissions getUserPermissions() {
326 Permissions permissions = new Permissions();
327 for (UserPermission permission : userPermissions) {
328 permissions.add(new UnresolvedPermission(permission.getClassName(),
329 permission.getName(),
330 permission.getActions(),
331 null));
333 permissions.setReadOnly();
334 return permissions;
337 public void setPublicRoot(String root) {
338 if (root.indexOf('*') != -1) {
339 throw new AppEngineConfigException("public-root cannot contain wildcards");
341 if (root.endsWith("/")) {
342 root = root.substring(0, root.length() - 1);
344 if (root.length() > 0 && !root.startsWith("/")) {
345 root = "/" + root;
347 staticIncludePattern = null;
348 publicRoot = root;
351 public String getPublicRoot() {
352 return publicRoot;
355 public void addInboundService(String service) {
356 inboundServices.add(service);
359 public Set<String> getInboundServices() {
360 return inboundServices;
363 public boolean getPrecompilationEnabled() {
364 return precompilationEnabled;
367 public void setPrecompilationEnabled(boolean precompilationEnabled) {
368 this.precompilationEnabled = precompilationEnabled;
371 public boolean getWarmupRequestsEnabled() {
372 return inboundServices.contains(WARMUP_SERVICE);
375 public void setWarmupRequestsEnabled(boolean warmupRequestsEnabled) {
376 if (warmupRequestsEnabled) {
377 inboundServices.add(WARMUP_SERVICE);
378 } else {
379 inboundServices.remove(WARMUP_SERVICE);
383 public List<AdminConsolePage> getAdminConsolePages() {
384 return Collections.unmodifiableList(adminConsolePages);
387 public void addAdminConsolePage(AdminConsolePage page) {
388 adminConsolePages.add(page);
391 public List<ErrorHandler> getErrorHandlers() {
392 return Collections.unmodifiableList(errorHandlers);
395 public void addErrorHandler(ErrorHandler handler) {
396 errorHandlers.add(handler);
399 public boolean getThreadsafe() {
400 return threadsafe;
403 public boolean getThreadsafeValueProvided() {
404 return threadsafeValueProvided;
407 public void setThreadsafe(boolean threadsafe) {
408 this.threadsafe = threadsafe;
409 this.threadsafeValueProvided = true;
412 public void setAutoIdPolicy(String policy) {
413 autoIdPolicy = policy;
416 public String getAutoIdPolicy() {
417 return autoIdPolicy;
420 public boolean getCodeLock() {
421 return codeLock;
424 public void setCodeLock(boolean codeLock) {
425 this.codeLock = codeLock;
428 public void setUseVm(boolean useVm) {
429 this.useVm = useVm;
432 public boolean getUseVm() {
433 return useVm;
436 public ApiConfig getApiConfig() {
437 return apiConfig;
440 public void setApiConfig(ApiConfig config) {
441 apiConfig = config;
444 public ClassLoaderConfig getClassLoaderConfig() {
445 return classLoaderConfig;
448 public void setClassLoaderConfig(ClassLoaderConfig classLoaderConfig) {
449 if (this.classLoaderConfig != null) {
450 throw new AppEngineConfigException("class-loader-config may only be specified once.");
452 this.classLoaderConfig = classLoaderConfig;
455 public String getUrlStreamHandlerType() {
456 return urlStreamHandlerType;
459 public void setUrlStreamHandlerType(String urlStreamHandlerType) {
460 if (this.classLoaderConfig != null) {
461 throw new AppEngineConfigException("url-stream-handler may only be specified once.");
463 if (!URL_HANDLER_URLFETCH.equals(urlStreamHandlerType)
464 && !URL_HANDLER_NATIVE.equals(urlStreamHandlerType)) {
465 throw new AppEngineConfigException(
466 "url-stream-handler must be " + URL_HANDLER_URLFETCH + " or " + URL_HANDLER_NATIVE +
467 " given " + urlStreamHandlerType);
469 this.urlStreamHandlerType = urlStreamHandlerType;
473 * Returns true if {@code url} matches one of the servlets or servlet
474 * filters listed in this web.xml that has api-endpoint set to true.
476 public boolean isApiEndpoint(String id) {
477 return apiEndpointIds.contains(id);
480 public void addApiEndpoint(String id) {
481 apiEndpointIds.add(id);
484 public Pagespeed getPagespeed() {
485 return pagespeed;
488 public void setPagespeed(Pagespeed pagespeed) {
489 this.pagespeed = pagespeed;
492 public void setUseGoogleConnectorJ(boolean useGoogleConnectorJ) {
493 if (useGoogleConnectorJ) {
494 this.useGoogleConnectorJ = UseGoogleConnectorJ.TRUE;
495 } else {
496 this.useGoogleConnectorJ = UseGoogleConnectorJ.FALSE;
500 public UseGoogleConnectorJ getUseGoogleConnectorJ() {
501 return useGoogleConnectorJ;
504 @Override
505 public String toString() {
506 return "AppEngineWebXml{" +
507 "systemProperties=" + systemProperties +
508 ", envVariables=" + envVariables +
509 ", userPermissions=" + userPermissions +
510 ", appId='" + appId + '\'' +
511 ", majorVersionId='" + majorVersionId + '\'' +
512 ", sourceLanguage='" + sourceLanguage + '\'' +
513 ", module='" + module + '\'' +
514 ", instanceClass='" + instanceClass + '\'' +
515 ", automaticScaling=" + automaticScaling +
516 ", manualScaling=" + manualScaling +
517 ", basicScaling=" + basicScaling +
518 ", healthCheck=" + healthCheck +
519 ", resources=" + resources +
520 ", network=" + network +
521 ", sslEnabled=" + sslEnabled +
522 ", useSessions=" + useSessions +
523 ", asyncSessionPersistence=" + asyncSessionPersistence +
524 ", asyncSessionPersistenceQueueName='" + asyncSessionPersistenceQueueName + '\'' +
525 ", staticFileIncludes=" + staticFileIncludes +
526 ", staticFileExcludes=" + staticFileExcludes +
527 ", resourceFileIncludes=" + resourceFileIncludes +
528 ", resourceFileExcludes=" + resourceFileExcludes +
529 ", staticIncludePattern=" + staticIncludePattern +
530 ", staticExcludePattern=" + staticExcludePattern +
531 ", resourceIncludePattern=" + resourceIncludePattern +
532 ", resourceExcludePattern=" + resourceExcludePattern +
533 ", publicRoot='" + publicRoot + '\'' +
534 ", appRoot='" + appRoot + '\'' +
535 ", inboundServices=" + inboundServices +
536 ", precompilationEnabled=" + precompilationEnabled +
537 ", adminConsolePages=" + adminConsolePages +
538 ", errorHandlers=" + errorHandlers +
539 ", threadsafe=" + threadsafe +
540 ", threadsafeValueProvided=" + threadsafeValueProvided +
541 ", autoIdPolicy=" + autoIdPolicy +
542 ", codeLock=" + codeLock +
543 ", apiConfig=" + apiConfig +
544 ", apiEndpointIds=" + apiEndpointIds +
545 ", pagespeed=" + pagespeed +
546 ", classLoaderConfig=" + classLoaderConfig +
547 ", urlStreamHandlerType=" +
548 (urlStreamHandlerType == null ? URL_HANDLER_URLFETCH : urlStreamHandlerType) +
549 ", useGoogleConnectorJ=" + useGoogleConnectorJ +
550 '}';
553 @Override
554 public boolean equals(Object o) {
555 if (this == o) {
556 return true;
558 if (o == null || getClass() != o.getClass()) {
559 return false;
562 AppEngineWebXml that = (AppEngineWebXml) o;
564 if (asyncSessionPersistence != that.asyncSessionPersistence) {
565 return false;
567 if (precompilationEnabled != that.precompilationEnabled) {
568 return false;
570 if (sslEnabled != that.sslEnabled) {
571 return false;
573 if (threadsafe != that.threadsafe) {
574 return false;
576 if (threadsafeValueProvided != that.threadsafeValueProvided) {
577 return false;
579 if (autoIdPolicy != null ? !autoIdPolicy.equals(that.autoIdPolicy)
580 : that.autoIdPolicy != null) {
581 return false;
583 if (codeLock != that.codeLock) {
584 return false;
586 if (useSessions != that.useSessions) {
587 return false;
589 if (adminConsolePages != null ? !adminConsolePages.equals(that.adminConsolePages)
590 : that.adminConsolePages != null) {
591 return false;
593 if (appId != null ? !appId.equals(that.appId) : that.appId != null) {
594 return false;
596 if (majorVersionId != null ? !majorVersionId.equals(that.majorVersionId)
597 : that.majorVersionId != null) {
598 return false;
600 if (module != null ? !module.equals(that.module) : that.module != null) {
601 return false;
603 if (instanceClass != null ? !instanceClass.equals(that.instanceClass)
604 : that.instanceClass != null) {
605 return false;
607 if (!automaticScaling.equals(that.automaticScaling)) {
608 return false;
610 if (!manualScaling.equals(that.manualScaling)) {
611 return false;
613 if (!basicScaling.equals(that.basicScaling)) {
614 return false;
616 if (appRoot != null ? !appRoot.equals(that.appRoot) : that.appRoot != null) {
617 return false;
619 if (asyncSessionPersistenceQueueName != null ? !asyncSessionPersistenceQueueName
620 .equals(that.asyncSessionPersistenceQueueName)
621 : that.asyncSessionPersistenceQueueName != null) {
622 return false;
624 if (envVariables != null ? !envVariables.equals(that.envVariables)
625 : that.envVariables != null) {
626 return false;
628 if (errorHandlers != null ? !errorHandlers.equals(that.errorHandlers)
629 : that.errorHandlers != null) {
630 return false;
632 if (inboundServices != null ? !inboundServices.equals(that.inboundServices)
633 : that.inboundServices != null) {
634 return false;
636 if (majorVersionId != null ? !majorVersionId.equals(that.majorVersionId)
637 : that.majorVersionId != null) {
638 return false;
640 if (sourceLanguage != null ? !sourceLanguage.equals(that.sourceLanguage)
641 : that.sourceLanguage != null) {
642 return false;
644 if (publicRoot != null ? !publicRoot.equals(that.publicRoot) : that.publicRoot != null) {
645 return false;
647 if (resourceExcludePattern != null ? !resourceExcludePattern.equals(that.resourceExcludePattern)
648 : that.resourceExcludePattern != null) {
649 return false;
651 if (resourceFileExcludes != null ? !resourceFileExcludes.equals(that.resourceFileExcludes)
652 : that.resourceFileExcludes != null) {
653 return false;
655 if (resourceFileIncludes != null ? !resourceFileIncludes.equals(that.resourceFileIncludes)
656 : that.resourceFileIncludes != null) {
657 return false;
659 if (resourceIncludePattern != null ? !resourceIncludePattern.equals(that.resourceIncludePattern)
660 : that.resourceIncludePattern != null) {
661 return false;
663 if (staticExcludePattern != null ? !staticExcludePattern.equals(that.staticExcludePattern)
664 : that.staticExcludePattern != null) {
665 return false;
667 if (staticFileExcludes != null ? !staticFileExcludes.equals(that.staticFileExcludes)
668 : that.staticFileExcludes != null) {
669 return false;
671 if (staticFileIncludes != null ? !staticFileIncludes.equals(that.staticFileIncludes)
672 : that.staticFileIncludes != null) {
673 return false;
675 if (staticIncludePattern != null ? !staticIncludePattern.equals(that.staticIncludePattern)
676 : that.staticIncludePattern != null) {
677 return false;
679 if (systemProperties != null ? !systemProperties.equals(that.systemProperties)
680 : that.systemProperties != null) {
681 return false;
683 if (betaSettings != null ? !betaSettings.equals(that.betaSettings) : that.betaSettings != null) {
684 return false;
686 if (healthCheck != null ? !healthCheck.equals(that.healthCheck)
687 : that.healthCheck != null) {
688 return false;
690 if (resources != null ? !resources.equals(that.resources) : that.resources != null) {
691 return false;
693 if (network != null ? !network.equals(that.network) : that.network != null) {
694 return false;
696 if (userPermissions != null ? !userPermissions.equals(that.userPermissions)
697 : that.userPermissions != null) {
698 return false;
700 if (apiConfig != null ? !apiConfig.equals(that.apiConfig)
701 : that.apiConfig != null) {
702 return false;
704 if (apiEndpointIds != null ? !apiEndpointIds.equals(that.apiEndpointIds)
705 : that.apiEndpointIds != null) {
706 return false;
708 if (pagespeed != null ? !pagespeed.equals(that.pagespeed) : that.pagespeed != null) {
709 return false;
711 if (classLoaderConfig != null ? !classLoaderConfig.equals(that.classLoaderConfig) :
712 that.classLoaderConfig != null) {
713 return false;
715 if (urlStreamHandlerType != null ? !urlStreamHandlerType.equals(that.urlStreamHandlerType) :
716 that.urlStreamHandlerType != null) {
717 return false;
719 if (useGoogleConnectorJ != that.useGoogleConnectorJ) {
720 return false;
723 return true;
726 @Override
727 public int hashCode() {
728 int result = systemProperties != null ? systemProperties.hashCode() : 0;
729 result = 31 * result + (envVariables != null ? envVariables.hashCode() : 0);
730 result = 31 * result + (userPermissions != null ? userPermissions.hashCode() : 0);
731 result = 31 * result + (appId != null ? appId.hashCode() : 0);
732 result = 31 * result + (majorVersionId != null ? majorVersionId.hashCode() : 0);
733 result = 31 * result + (sourceLanguage != null ? sourceLanguage.hashCode() : 0);
734 result = 31 * result + (module != null ? module.hashCode() : 0);
735 result = 31 * result + (instanceClass != null ? instanceClass.hashCode() : 0);
736 result = 31 * result + automaticScaling.hashCode();
737 result = 31 * result + manualScaling.hashCode();
738 result = 31 * result + basicScaling.hashCode();
739 result = 31 * result + (sslEnabled ? 1 : 0);
740 result = 31 * result + (useSessions ? 1 : 0);
741 result = 31 * result + (asyncSessionPersistence ? 1 : 0);
742 result =
743 31 * result + (asyncSessionPersistenceQueueName != null ? asyncSessionPersistenceQueueName
744 .hashCode() : 0);
745 result = 31 * result + (staticFileIncludes != null ? staticFileIncludes.hashCode() : 0);
746 result = 31 * result + (staticFileExcludes != null ? staticFileExcludes.hashCode() : 0);
747 result = 31 * result + (resourceFileIncludes != null ? resourceFileIncludes.hashCode() : 0);
748 result = 31 * result + (resourceFileExcludes != null ? resourceFileExcludes.hashCode() : 0);
749 result = 31 * result + (staticIncludePattern != null ? staticIncludePattern.hashCode() : 0);
750 result = 31 * result + (staticExcludePattern != null ? staticExcludePattern.hashCode() : 0);
751 result = 31 * result + (resourceIncludePattern != null ? resourceIncludePattern.hashCode() : 0);
752 result = 31 * result + (resourceExcludePattern != null ? resourceExcludePattern.hashCode() : 0);
753 result = 31 * result + (publicRoot != null ? publicRoot.hashCode() : 0);
754 result = 31 * result + (appRoot != null ? appRoot.hashCode() : 0);
755 result = 31 * result + (inboundServices != null ? inboundServices.hashCode() : 0);
756 result = 31 * result + (precompilationEnabled ? 1 : 0);
757 result = 31 * result + (adminConsolePages != null ? adminConsolePages.hashCode() : 0);
758 result = 31 * result + (errorHandlers != null ? errorHandlers.hashCode() : 0);
759 result = 31 * result + (threadsafe ? 1 : 0);
760 result = 31 * result + (autoIdPolicy != null ? autoIdPolicy.hashCode() : 0);
761 result = 31 * result + (threadsafeValueProvided ? 1 : 0);
762 result = 31 * result + (codeLock ? 1 : 0);
763 result = 31 * result + (apiConfig != null ? apiConfig.hashCode() : 0);
764 result = 31 * result + (apiEndpointIds != null ? apiEndpointIds.hashCode() : 0);
765 result = 31 * result + (pagespeed != null ? pagespeed.hashCode() : 0);
766 result = 31 * result + (classLoaderConfig != null ? classLoaderConfig.hashCode() : 0);
767 result = 31 * result + (urlStreamHandlerType != null ? urlStreamHandlerType.hashCode() : 0);
768 result = 31 * result + (useGoogleConnectorJ.hashCode());
769 result = 31 * result + (betaSettings != null ? betaSettings.hashCode() : 0);
770 result = 31 * result + (healthCheck != null ? healthCheck.hashCode() : 0);
771 result = 31 * result + (resources != null ? resources.hashCode() : 0);
772 result = 31 * result + (network != null ? network.hashCode() : 0);
773 return result;
776 public boolean includesResource(String path) {
777 if (resourceIncludePattern == null) {
778 if (resourceFileIncludes.size() == 0) {
779 resourceIncludePattern = Pattern.compile(".*");
780 } else {
781 resourceIncludePattern = Pattern.compile(makeRegexp(resourceFileIncludes));
784 if (resourceExcludePattern == null && resourceFileExcludes.size() > 0) {
785 resourceExcludePattern = Pattern.compile(makeRegexp(resourceFileExcludes));
786 } else {
788 return includes(path, resourceIncludePattern, resourceExcludePattern);
791 public boolean includesStatic(String path) {
792 if (staticIncludePattern == null) {
793 if (staticFileIncludes.size() == 0) {
794 String staticRoot;
795 if (publicRoot.length() > 0) {
796 staticRoot = publicRoot + "/**";
797 } else {
798 staticRoot = "**";
800 staticIncludePattern = Pattern.compile(
801 makeRegexp(Collections.singletonList(staticRoot)));
802 } else {
803 List<String> patterns = new ArrayList<String>();
804 for (StaticFileInclude include : staticFileIncludes) {
805 patterns.add(include.getPattern());
807 staticIncludePattern = Pattern.compile(makeRegexp(patterns));
810 if (staticExcludePattern == null && staticFileExcludes.size() > 0) {
811 staticExcludePattern = Pattern.compile(makeRegexp(staticFileExcludes));
812 } else {
814 return includes(path, staticIncludePattern, staticExcludePattern);
818 * Tests whether {@code path} is covered by the pattern {@code includes}
819 * while not being blocked by matching {@code excludes}.
821 * @param path a URL to test
822 * @param includes a non-{@code null} pattern for included URLs
823 * @param excludes a pattern for exclusion, or {@code null} to not exclude
824 * anything from the {@code includes} set.
826 public boolean includes(String path, Pattern includes, Pattern excludes) {
827 assert(includes != null);
828 if (!includes.matcher(path).matches()) {
829 return false;
831 if (excludes != null && excludes.matcher(path).matches()) {
832 return false;
834 return true;
837 public String makeRegexp(List<String> patterns) {
838 StringBuilder builder = new StringBuilder();
839 boolean first = true;
840 for (String item : patterns) {
841 if (first) {
842 first = false;
843 } else {
844 builder.append('|');
847 while (item.charAt(0) == '/') {
848 item = item.substring(1);
851 builder.append('(');
852 if (appRoot != null) {
853 builder.append(makeFileRegex(appRoot));
855 builder.append("/");
856 builder.append(makeFileRegex(item));
857 builder.append(')');
859 return builder.toString();
863 * Helper method to translate from appengine-web.xml "file globs" to
864 * proper regular expressions as used in app.yaml.
866 * @param fileGlob the glob to translate
867 * @return the regular expression string matching the input {@code file} pattern.
869 static String makeFileRegex(String fileGlob) {
870 fileGlob = fileGlob.replaceAll("([^A-Za-z0-9\\-_/])", "\\\\$1");
871 fileGlob = fileGlob.replaceAll("\\\\\\*\\\\\\*", ".*");
872 fileGlob = fileGlob.replaceAll("\\\\\\*", "[^/]*");
873 return fileGlob;
876 * Sets the application root directory, as a prefix for the regexps in
877 * {@link #includeResourcePattern(String)} and friends. This is needed
878 * because we want to match complete filenames relative to root.
880 * @param appRoot
882 public void setSourcePrefix(String appRoot) {
883 this.appRoot = appRoot;
884 this.resourceIncludePattern = null;
885 this.resourceExcludePattern = null;
886 this.staticIncludePattern = null;
887 this.staticExcludePattern = null;
890 public String getSourcePrefix() {
891 return this.appRoot;
895 * Represents a {@link java.security.Permission} that needs to be
896 * granted to user code.
898 private static class UserPermission {
899 private final String className;
900 private final String name;
901 private final String actions;
903 private boolean hasHashCode = false;
904 private int hashCode;
906 public UserPermission(String className, String name, String actions) {
907 this.className = className;
908 this.name = name;
909 this.actions = actions;
912 public String getClassName() {
913 return className;
916 public String getName() {
917 return name;
920 public String getActions() {
921 return actions;
924 @Override
925 public int hashCode() {
926 if (hasHashCode) {
927 return hashCode;
930 int hash = className.hashCode();
931 hash = 31 * hash + name.hashCode();
932 if (actions != null) {
933 hash = 31 * hash + actions.hashCode();
936 hashCode = hash;
937 hasHashCode = true;
938 return hashCode;
941 @Override
942 public boolean equals(Object obj) {
943 if (obj instanceof UserPermission) {
944 UserPermission perm = (UserPermission) obj;
945 if (className.equals(perm.className) && name.equals(perm.name)) {
946 if (actions == null ? perm.actions == null : actions.equals(perm.actions)) {
947 return true;
951 return false;
956 * Represents an &lt;include&gt; element within the
957 * &lt;static-files&gt; element. Currently this includes both a
958 * pattern and an optional expiration time specification.
960 public static class StaticFileInclude {
961 private final String pattern;
962 private final String expiration;
963 private final Map<String, String> httpHeaders;
965 public StaticFileInclude(String pattern, String expiration) {
966 this.pattern = pattern;
967 this.expiration = expiration;
968 this.httpHeaders = new LinkedHashMap<>();
971 public String getPattern() {
972 return pattern;
975 public Pattern getRegularExpression() {
976 return Pattern.compile(makeFileRegex(pattern));
979 public String getExpiration() {
980 return expiration;
983 public Map<String, String> getHttpHeaders() {
984 return httpHeaders;
987 @Override
988 public int hashCode() {
989 return Objects.hash(pattern, expiration, httpHeaders);
992 @Override
993 public boolean equals(Object obj) {
994 if (!(obj instanceof StaticFileInclude)) {
995 return false;
998 StaticFileInclude other = (StaticFileInclude) obj;
1000 if (pattern != null) {
1001 if (!pattern.equals(other.pattern)) {
1002 return false;
1004 } else {
1005 if (other.pattern != null) {
1006 return false;
1010 if (expiration != null) {
1011 if (!expiration.equals(other.expiration)) {
1012 return false;
1014 } else {
1015 if (other.expiration != null) {
1016 return false;
1020 if (httpHeaders != null) {
1021 if (!httpHeaders.equals(other.httpHeaders)) {
1022 return false;
1024 } else {
1025 if (other.httpHeaders != null) {
1026 return false;
1030 return true;
1034 public static class AdminConsolePage {
1035 private final String name;
1036 private final String url;
1038 public AdminConsolePage(String name, String url) {
1039 this.name = name;
1040 this.url = url;
1043 public String getName() {
1044 return name;
1047 public String getUrl() {
1048 return url;
1051 @Override
1052 public int hashCode() {
1053 final int prime = 31;
1054 int result = 1;
1055 result = prime * result + ((name == null) ? 0 : name.hashCode());
1056 result = prime * result + ((url == null) ? 0 : url.hashCode());
1057 return result;
1060 @Override
1061 public boolean equals(Object obj) {
1062 if (this == obj) return true;
1063 if (obj == null) return false;
1064 if (getClass() != obj.getClass()) return false;
1065 AdminConsolePage other = (AdminConsolePage) obj;
1066 if (name == null) {
1067 if (other.name != null) return false;
1068 } else if (!name.equals(other.name)) return false;
1069 if (url == null) {
1070 if (other.url != null) return false;
1071 } else if (!url.equals(other.url)) return false;
1072 return true;
1077 * Represents an &lt;error-handler&gt; element. Currently this includes both
1078 * a file name and an optional error code.
1080 public static class ErrorHandler {
1081 private final String file;
1082 private final String errorCode;
1084 public ErrorHandler(String file, String errorCode) {
1085 this.file = file;
1086 this.errorCode = errorCode;
1089 public String getFile() {
1090 return file;
1093 public String getErrorCode() {
1094 return errorCode;
1097 @Override
1098 public int hashCode() {
1099 final int prime = 31;
1100 int result = 1;
1101 result = prime * result + ((file == null) ? 0 : file.hashCode());
1102 result = prime * result +
1103 ((errorCode == null) ? 0 : errorCode.hashCode());
1104 return result;
1107 @Override
1108 public boolean equals(Object obj) {
1109 if (!(obj instanceof ErrorHandler)) {
1110 return false;
1113 ErrorHandler handler = (ErrorHandler) obj;
1114 if (!file.equals(handler.file)) {
1115 return false;
1118 if (errorCode == null) {
1119 if (handler.errorCode != null) {
1120 return false;
1122 } else {
1123 if (!errorCode.equals(handler.errorCode)) {
1124 return false;
1128 return true;
1133 * Represents an &lt;api-config&gt; element. This is a singleton specifying
1134 * url-pattern and servlet-class for the api config server.
1136 public static class ApiConfig {
1137 private final String servletClass;
1138 private final String url;
1140 public ApiConfig(String servletClass, String url) {
1141 this.servletClass = servletClass;
1142 this.url = url;
1145 public String getservletClass() {
1146 return servletClass;
1149 public String getUrl() {
1150 return url;
1153 @Override
1154 public int hashCode() {
1155 final int prime = 31;
1156 int result = 1;
1157 result = prime * result + ((servletClass == null) ? 0 : servletClass.hashCode());
1158 result = prime * result + ((url == null) ? 0 : url.hashCode());
1159 return result;
1162 @Override
1163 public boolean equals(Object obj) {
1164 if (this == obj) { return true; }
1165 if (obj == null) { return false; }
1166 if (getClass() != obj.getClass()) { return false; }
1167 ApiConfig other = (ApiConfig) obj;
1168 if (servletClass == null) {
1169 if (other.servletClass != null) { return false; }
1170 } else if (!servletClass.equals(other.servletClass)) { return false; }
1171 if (url == null) {
1172 if (other.url != null) { return false; }
1173 } else if (!url.equals(other.url)) { return false; }
1174 return true;
1177 @Override
1178 public String toString() {
1179 return "ApiConfig{servletClass=\"" + servletClass + "\", url=\"" + url + "\"}";
1184 * Holder for automatic settings.
1186 public static class AutomaticScaling {
1187 private static final AutomaticScaling EMPTY_SETTINGS = new AutomaticScaling();
1189 public static final String AUTOMATIC = "automatic";
1190 private String minPendingLatency;
1191 private String maxPendingLatency;
1192 private String minIdleInstances;
1193 private String maxIdleInstances;
1194 private String maxConcurrentRequests;
1196 private Integer minNumInstances;
1197 private Integer maxNumInstances;
1198 private Integer coolDownPeriodSec;
1199 private CpuUtilization cpuUtilization;
1201 public String getMinPendingLatency() {
1202 return minPendingLatency;
1206 * Sets minPendingLatency. Normalizes empty and null inputs to null.
1208 public void setMinPendingLatency(String minPendingLatency) {
1209 this.minPendingLatency = StringUtil.toNullIfEmptyOrWhitespace(minPendingLatency);
1212 public String getMaxPendingLatency() {
1213 return maxPendingLatency;
1217 * Sets maxPendingLatency. Normalizes empty and null inputs to null.
1219 public void setMaxPendingLatency(String maxPendingLatency) {
1220 this.maxPendingLatency = StringUtil.toNullIfEmptyOrWhitespace(maxPendingLatency);
1223 public String getMinIdleInstances() {
1224 return minIdleInstances;
1228 * Sets minIdleInstances. Normalizes empty and null inputs to null.
1230 public void setMinIdleInstances(String minIdleInstances) {
1231 this.minIdleInstances = StringUtil.toNullIfEmptyOrWhitespace(minIdleInstances);
1234 public String getMaxIdleInstances() {
1235 return maxIdleInstances;
1239 * Sets maxIdleInstances. Normalizes empty and null inputs to null.
1241 public void setMaxIdleInstances(String maxIdleInstances) {
1242 this.maxIdleInstances = StringUtil.toNullIfEmptyOrWhitespace(maxIdleInstances);
1245 public boolean isEmpty() {
1246 return this.equals(EMPTY_SETTINGS);
1249 public String getMaxConcurrentRequests() {
1250 return maxConcurrentRequests;
1254 * Sets maxConcurrentRequests. Normalizes empty and null inputs to null.
1256 public void setMaxConcurrentRequests(String maxConcurrentRequests) {
1257 this.maxConcurrentRequests = StringUtil.toNullIfEmptyOrWhitespace(maxConcurrentRequests);
1260 public Integer getMinNumInstances() {
1261 return minNumInstances;
1264 public void setMinNumInstances(Integer minNumInstances) {
1265 this.minNumInstances = minNumInstances;
1268 public Integer getMaxNumInstances() {
1269 return maxNumInstances;
1272 public void setMaxNumInstances(Integer maxNumInstances) {
1273 this.maxNumInstances = maxNumInstances;
1276 public Integer getCoolDownPeriodSec() {
1277 return coolDownPeriodSec;
1280 public void setCoolDownPeriodSec(Integer coolDownPeriodSec) {
1281 this.coolDownPeriodSec = coolDownPeriodSec;
1284 public CpuUtilization getCpuUtilization() {
1285 return cpuUtilization;
1288 public void setCpuUtilization(CpuUtilization cpuUtilization) {
1289 this.cpuUtilization = cpuUtilization;
1292 @Override
1293 public int hashCode() {
1294 return Objects.hash(maxPendingLatency, minPendingLatency, maxIdleInstances,
1295 minIdleInstances, maxConcurrentRequests, minNumInstances,
1296 maxNumInstances, coolDownPeriodSec, cpuUtilization);
1299 @Override
1300 public boolean equals(Object obj) {
1301 if (this == obj) {
1302 return true;
1304 if (obj == null) {
1305 return false;
1307 if (getClass() != obj.getClass()) {
1308 return false;
1310 AutomaticScaling other = (AutomaticScaling) obj;
1311 return Objects.equals(maxPendingLatency, other.maxPendingLatency)
1312 && Objects.equals(minPendingLatency, other.minPendingLatency)
1313 && Objects.equals(maxIdleInstances, other.maxIdleInstances)
1314 && Objects.equals(minIdleInstances, other.minIdleInstances)
1315 && Objects.equals(maxConcurrentRequests, other.maxConcurrentRequests)
1316 && Objects.equals(minNumInstances, other.minNumInstances)
1317 && Objects.equals(maxNumInstances, other.maxNumInstances)
1318 && Objects.equals(coolDownPeriodSec, other.coolDownPeriodSec)
1319 && Objects.equals(cpuUtilization, other.cpuUtilization);
1322 @Override
1323 public String toString() {
1324 return "AutomaticScaling [minPendingLatency=" + minPendingLatency
1325 + ", maxPendingLatency=" + maxPendingLatency
1326 + ", minIdleInstances=" + minIdleInstances
1327 + ", maxIdleInstances=" + maxIdleInstances
1328 + ", maxConcurrentRequests=" + maxConcurrentRequests
1329 + ", minNumInstances=" + minNumInstances
1330 + ", maxNumInstances=" + maxNumInstances
1331 + ", coolDownPeriodSec=" + coolDownPeriodSec
1332 + ", cpuUtilization=" + cpuUtilization + "]";
1337 * Holder for CPU utilization.
1339 public static class CpuUtilization {
1340 private static final CpuUtilization EMPTY_SETTINGS = new CpuUtilization();
1341 private Double targetUtilization;
1342 private Integer aggregationWindowLengthSec;
1344 public Double getTargetUtilization() {
1345 return targetUtilization;
1348 public void setTargetUtilization(Double targetUtilization) {
1349 this.targetUtilization = targetUtilization;
1352 public Integer getAggregationWindowLengthSec() {
1353 return aggregationWindowLengthSec;
1356 public void setAggregationWindowLengthSec(Integer aggregationWindowLengthSec) {
1357 this.aggregationWindowLengthSec = aggregationWindowLengthSec;
1360 public boolean isEmpty() {
1361 return this.equals(EMPTY_SETTINGS);
1364 @Override
1365 public int hashCode() {
1366 return Objects.hash(targetUtilization, aggregationWindowLengthSec);
1369 @Override
1370 public boolean equals(Object obj) {
1371 if (this == obj) {
1372 return true;
1374 if (obj == null) {
1375 return false;
1377 if (getClass() != obj.getClass()) {
1378 return false;
1380 CpuUtilization other = (CpuUtilization) obj;
1381 return Objects.equals(targetUtilization, other.targetUtilization)
1382 && Objects.equals(aggregationWindowLengthSec, other.aggregationWindowLengthSec);
1385 @Override
1386 public String toString() {
1387 return "CpuUtilization [targetUtilization=" + targetUtilization
1388 + ", aggregationWindowLengthSec=" + aggregationWindowLengthSec + "]";
1393 * Holder for health check.
1395 public static class HealthCheck {
1396 private static final HealthCheck EMPTY_SETTINGS = new HealthCheck();
1398 private boolean enableHealthCheck = true;
1399 private Integer checkIntervalSec;
1400 private Integer timeoutSec;
1401 private Integer unhealthyThreshold;
1402 private Integer healthyThreshold;
1403 private Integer restartThreshold;
1404 private String host;
1406 public boolean getEnableHealthCheck() {
1407 return enableHealthCheck;
1410 * Sets enableHealthCheck.
1412 public void setEnableHealthCheck(boolean enableHealthCheck) {
1413 this.enableHealthCheck = enableHealthCheck;
1416 public Integer getCheckIntervalSec() {
1417 return checkIntervalSec;
1420 * Sets checkIntervalSec.
1422 public void setCheckIntervalSec(Integer checkIntervalSec) {
1423 this.checkIntervalSec = checkIntervalSec;
1426 public Integer getTimeoutSec() {
1427 return timeoutSec;
1430 * Sets timeoutSec.
1432 public void setTimeoutSec(Integer timeoutSec) {
1433 this.timeoutSec = timeoutSec;
1436 public Integer getUnhealthyThreshold() {
1437 return unhealthyThreshold;
1441 * Sets unhealthyThreshold.
1443 public void setUnhealthyThreshold(Integer unhealthyThreshold) {
1444 this.unhealthyThreshold = unhealthyThreshold;
1447 public Integer getHealthyThreshold() {
1448 return healthyThreshold;
1452 * Sets healthyThreshold.
1455 public void setHealthyThreshold(Integer healthyThreshold) {
1456 this.healthyThreshold = healthyThreshold;
1459 public Integer getRestartThreshold() {
1460 return restartThreshold;
1464 * Sets restartThreshold.
1466 public void setRestartThreshold(Integer restartThreshold) {
1467 this.restartThreshold = restartThreshold;
1470 public String getHost() {
1471 return host;
1475 * Sets host. Normalizes empty and null inputs to null.
1477 public void setHost(String host) {
1478 this.host = StringUtil.toNullIfEmptyOrWhitespace(host);
1481 public boolean isEmpty() {
1482 return this.equals(EMPTY_SETTINGS);
1485 @Override
1486 public int hashCode() {
1487 return Objects.hash(enableHealthCheck, checkIntervalSec, timeoutSec, unhealthyThreshold,
1488 healthyThreshold, restartThreshold, host);
1491 @Override
1492 public boolean equals(Object obj) {
1493 if (this == obj) {
1494 return true;
1496 if (obj == null) {
1497 return false;
1499 if (getClass() != obj.getClass()) {
1500 return false;
1502 HealthCheck other = (HealthCheck) obj;
1503 return Objects.equals(enableHealthCheck, other.enableHealthCheck)
1504 && Objects.equals(checkIntervalSec, other.checkIntervalSec)
1505 && Objects.equals(timeoutSec, other.timeoutSec)
1506 && Objects.equals(unhealthyThreshold, other.unhealthyThreshold)
1507 && Objects.equals(healthyThreshold, other.healthyThreshold)
1508 && Objects.equals(restartThreshold, other.restartThreshold)
1509 && Objects.equals(host, other.host);
1512 @Override
1513 public String toString() {
1514 return "HealthCheck [enableHealthCheck=" + enableHealthCheck
1515 + ", checkIntervalSec=" + checkIntervalSec
1516 + ", timeoutSec=" + timeoutSec
1517 + ", unhealthyThreshold=" + unhealthyThreshold
1518 + ", healthyThreshold=" + healthyThreshold
1519 + ", restartThreshold=" + restartThreshold
1520 + ", host=" + host + "]";
1525 * Holder for Resources
1527 public static class Resources {
1528 private static final Resources EMPTY_SETTINGS = new Resources();
1530 private double cpu;
1532 public double getCpu() {
1533 return cpu;
1536 public void setCpu(double cpu) {
1537 this.cpu = cpu;
1540 private double memory_gb;
1542 public double getMemoryGb() {
1543 return memory_gb;
1546 public void setMemoryGb(double memory_gb) {
1547 this.memory_gb = memory_gb;
1550 private int disk_size_gb;
1552 public int getDiskSizeGb() {
1553 return disk_size_gb;
1556 public void setDiskSizeGb(int disk_size_gb) {
1557 this.disk_size_gb = disk_size_gb;
1560 public boolean isEmpty() {
1561 return this.equals(EMPTY_SETTINGS);
1564 @Override
1565 public int hashCode() {
1566 return Objects.hash(cpu, memory_gb, disk_size_gb);
1569 @Override
1570 public boolean equals(Object obj) {
1571 if (this == obj) {
1572 return true;
1574 if (obj == null) {
1575 return false;
1577 if (getClass() != obj.getClass()) {
1578 return false;
1580 Resources other = (Resources) obj;
1581 return Objects.equals(cpu, other.cpu) &&
1582 Objects.equals(memory_gb, other.memory_gb) &&
1583 Objects.equals(disk_size_gb, other.disk_size_gb);
1586 @Override
1587 public String toString() {
1588 return "Resources [" + "cpu=" + cpu +
1589 ", memory_gb=" + memory_gb +
1590 ", disk_size_gb=" + disk_size_gb + "]";
1595 * Holder for network.
1597 public static class Network {
1598 private static final Network EMPTY_SETTINGS = new Network();
1600 private String instanceTag;
1602 public String getInstanceTag() {
1603 return instanceTag;
1606 public void setInstanceTag(String instanceTag) {
1607 this.instanceTag = instanceTag;
1610 private final List<String> forwardedPorts = Lists.newArrayList();
1612 public List<String> getForwardedPorts() {
1613 return Collections.unmodifiableList(forwardedPorts);
1616 public void addForwardedPort(String forwardedPort) {
1617 forwardedPorts.add(forwardedPort);
1620 private String name;
1622 public String getName() {
1623 return name;
1626 public void setName(String name) {
1627 this.name = name;
1630 public boolean isEmpty() {
1631 return this.equals(EMPTY_SETTINGS);
1634 @Override
1635 public int hashCode() {
1636 return Objects.hash(forwardedPorts, instanceTag);
1639 @Override
1640 public boolean equals(Object obj) {
1641 if (this == obj) {
1642 return true;
1644 if (obj == null) {
1645 return false;
1647 if (getClass() != obj.getClass()) {
1648 return false;
1650 Network other = (Network) obj;
1651 return Objects.equals(forwardedPorts, other.forwardedPorts)
1652 && Objects.equals(instanceTag, other.instanceTag);
1655 @Override
1656 public String toString() {
1657 return "Network [forwardedPorts=" + forwardedPorts + ", instanceTag=" + instanceTag + "]";
1662 * Holder for manual settings.
1664 public static class ManualScaling {
1665 private static final ManualScaling EMPTY_SETTINGS = new ManualScaling();
1667 private String instances;
1669 public String getInstances() {
1670 return instances;
1674 * Sets instances. Normalizes empty and null inputs to null.
1676 public void setInstances(String instances) {
1677 this.instances = StringUtil.toNullIfEmptyOrWhitespace(instances);
1680 public boolean isEmpty() {
1681 return this.equals(EMPTY_SETTINGS);
1684 @Override
1685 public int hashCode() {
1686 return Objects.hash(instances);
1689 @Override
1690 public boolean equals(Object obj) {
1691 if (this == obj) {
1692 return true;
1694 if (obj == null) {
1695 return false;
1697 if (getClass() != obj.getClass()) {
1698 return false;
1700 ManualScaling other = (ManualScaling) obj;
1701 return Objects.equals(instances, other.instances);
1704 @Override
1705 public String toString() {
1706 return "ManualScaling [" + "instances=" + instances + "]";
1711 * Holder for basic settings.
1713 public static class BasicScaling {
1714 private static final BasicScaling EMPTY_SETTINGS = new BasicScaling();
1716 private String maxInstances;
1717 private String idleTimeout;
1719 public String getMaxInstances() {
1720 return maxInstances;
1723 public String getIdleTimeout() {
1724 return idleTimeout;
1728 * Sets maxInstances. Normalizes empty and null inputs to null.
1730 public void setMaxInstances(String maxInstances) {
1731 this.maxInstances = StringUtil.toNullIfEmptyOrWhitespace(maxInstances);
1735 * Sets idleTimeout. Normalizes empty and null inputs to null.
1737 public void setIdleTimeout(String idleTimeout) {
1738 this.idleTimeout = StringUtil.toNullIfEmptyOrWhitespace(idleTimeout);
1741 public boolean isEmpty() {
1742 return this.equals(EMPTY_SETTINGS);
1745 @Override
1746 public int hashCode() {
1747 return Objects.hash(maxInstances, idleTimeout);
1750 @Override
1751 public boolean equals(Object obj) {
1752 if (this == obj) {
1753 return true;
1755 if (obj == null) {
1756 return false;
1758 if (getClass() != obj.getClass()) {
1759 return false;
1761 BasicScaling other = (BasicScaling) obj;
1762 return Objects.equals(maxInstances, other.maxInstances)
1763 && Objects.equals(idleTimeout, other.idleTimeout);
1766 @Override
1767 public String toString() {
1768 return "BasicScaling [" + "maxInstances=" + maxInstances
1769 + ", idleTimeout=" + idleTimeout + "]";
1774 * Represents a &lt;pagespeed&gt; element. This is used to specify configuration for the Page
1775 * Speed Service, which can be used to automatically optimize the loading speed of app engine
1776 * sites.
1778 public static class Pagespeed {
1779 private final List<String> urlBlacklist = Lists.newArrayList();
1780 private final List<String> domainsToRewrite = Lists.newArrayList();
1781 private final List<String> enabledRewriters = Lists.newArrayList();
1782 private final List<String> disabledRewriters = Lists.newArrayList();
1784 public void addUrlBlacklist(String url) {
1785 urlBlacklist.add(url);
1788 public List<String> getUrlBlacklist() {
1789 return Collections.unmodifiableList(urlBlacklist);
1792 public void addDomainToRewrite(String domain) {
1793 domainsToRewrite.add(domain);
1796 public List<String> getDomainsToRewrite() {
1797 return Collections.unmodifiableList(domainsToRewrite);
1800 public void addEnabledRewriter(String rewriter) {
1801 enabledRewriters.add(rewriter);
1804 public List<String> getEnabledRewriters() {
1805 return Collections.unmodifiableList(enabledRewriters);
1808 public void addDisabledRewriter(String rewriter) {
1809 disabledRewriters.add(rewriter);
1812 public List<String> getDisabledRewriters() {
1813 return Collections.unmodifiableList(disabledRewriters);
1816 public boolean isEmpty() {
1817 return urlBlacklist.isEmpty() && domainsToRewrite.isEmpty() && enabledRewriters.isEmpty()
1818 && disabledRewriters.isEmpty();
1821 @Override
1822 public int hashCode() {
1823 return Objects.hash(urlBlacklist, domainsToRewrite, enabledRewriters, disabledRewriters);
1826 @Override
1827 public boolean equals(Object obj) {
1828 if (this == obj) {
1829 return true;
1831 if (obj == null) {
1832 return false;
1834 if (getClass() != obj.getClass()) {
1835 return false;
1837 Pagespeed other = (Pagespeed) obj;
1838 return Objects.equals(urlBlacklist, other.urlBlacklist)
1839 && Objects.equals(domainsToRewrite, other.domainsToRewrite)
1840 && Objects.equals(enabledRewriters, other.enabledRewriters)
1841 && Objects.equals(disabledRewriters, other.disabledRewriters);
1844 @Override
1845 public String toString() {
1846 return "Pagespeed [urlBlacklist=" + urlBlacklist + ", domainsToRewrite=" + domainsToRewrite
1847 + ", enabledRewriters=" + enabledRewriters + ", disabledRewriters=" + disabledRewriters
1848 + "]";
1852 public static class ClassLoaderConfig {
1853 private final List<PrioritySpecifierEntry> entries = Lists.newArrayList();
1855 public void add(PrioritySpecifierEntry entry) {
1856 entries.add(entry);
1859 public List<PrioritySpecifierEntry> getEntries() {
1860 return entries;
1863 @Override
1864 public int hashCode() {
1865 final int prime = 31;
1866 int result = 1;
1867 result = prime * result + ((entries == null) ? 0 : entries.hashCode());
1868 return result;
1871 @Override
1872 public boolean equals(Object obj) {
1873 if (this == obj) return true;
1874 if (obj == null) return false;
1875 if (getClass() != obj.getClass()) return false;
1876 ClassLoaderConfig other = (ClassLoaderConfig) obj;
1877 if (entries == null) {
1878 if (other.entries != null) return false;
1879 } else if (!entries.equals(other.entries)) return false;
1880 return true;
1883 @Override
1884 public String toString() {
1885 return "ClassLoaderConfig{entries=\"" + entries + "\"}";
1889 public static class PrioritySpecifierEntry {
1890 private String filename;
1891 private Double priority;
1893 private void checkNotAlreadySet() {
1894 if (filename != null) {
1895 throw new AppEngineConfigException("Found more that one file name matching tag. "
1896 + "Only one of 'filename' attribute allowed.");
1900 public String getFilename() {
1901 return filename;
1904 public void setFilename(String filename) {
1905 checkNotAlreadySet();
1906 this.filename = filename;
1909 public Double getPriority() {
1910 return priority;
1913 public double getPriorityValue() {
1914 if (priority == null) {
1915 return 1.0d;
1917 return priority;
1920 public void setPriority(String priority) {
1921 if (this.priority != null) {
1922 throw new AppEngineConfigException("The 'priority' tag may only be specified once.");
1925 if (priority == null) {
1926 this.priority = null;
1927 return;
1930 this.priority = Double.parseDouble(priority);
1933 public void checkClassLoaderConfig() {
1934 if (filename == null) {
1935 throw new AppEngineConfigException("Must have a filename attribute.");
1939 @Override
1940 public int hashCode() {
1941 final int prime = 31;
1942 int result = 1;
1943 result = prime * result + ((filename == null) ? 0 : filename.hashCode());
1944 result = prime * result + ((priority == null) ? 0 : priority.hashCode());
1945 return result;
1948 @Override
1949 public boolean equals(Object obj) {
1950 if (this == obj) return true;
1951 if (obj == null) return false;
1952 if (getClass() != obj.getClass()) return false;
1953 PrioritySpecifierEntry other = (PrioritySpecifierEntry) obj;
1954 if (filename == null) {
1955 if (other.filename != null) return false;
1956 } else if (!filename.equals(other.filename)) return false;
1957 if (priority == null) {
1958 if (other.priority != null) return false;
1959 } else if (!priority.equals(other.priority)) return false;
1960 return true;
1963 @Override
1964 public String toString() {
1965 return "PrioritySpecifierEntry{filename=\"" + filename + "\", priority=\"" + priority + "\"}";