1 // Copyright 2008 Google Inc. All Rights Reserved.
2 package com
.google
.apphosting
.utils
.config
;
4 import com
.google
.common
.base
.Objects
;
5 import com
.google
.common
.base
.StringUtil
;
6 import com
.google
.common
.collect
.Lists
;
7 import com
.google
.common
.collect
.Maps
;
9 import java
.security
.Permissions
;
10 import java
.security
.UnresolvedPermission
;
11 import java
.util
.ArrayList
;
12 import java
.util
.Collections
;
13 import java
.util
.HashMap
;
14 import java
.util
.LinkedHashSet
;
15 import java
.util
.List
;
18 import java
.util
.regex
.Pattern
;
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
{
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
> vmSettings
= Maps
.newLinkedHashMap();
37 private final Map
<String
, String
> envVariables
= Maps
.newHashMap();
39 private final List
<UserPermission
> userPermissions
= new ArrayList
<UserPermission
>();
41 public static final String WARMUP_SERVICE
= "warmup";
43 public static final String URL_HANDLER_URLFETCH
= "urlfetch";
44 public static final String URL_HANDLER_NATIVE
= "native";
48 private String majorVersionId
;
50 private String module
;
51 private String instanceClass
;
53 private final AutomaticScaling automaticScaling
;
54 private final ManualScaling manualScaling
;
55 private final BasicScaling basicScaling
;
57 private String sourceLanguage
;
58 private boolean sslEnabled
= true;
59 private boolean useSessions
= false;
60 private boolean asyncSessionPersistence
= false;
61 private String asyncSessionPersistenceQueueName
;
63 private final List
<StaticFileInclude
> staticFileIncludes
;
64 private final List
<String
> staticFileExcludes
;
65 private final List
<String
> resourceFileIncludes
;
66 private final List
<String
> resourceFileExcludes
;
68 private Pattern staticIncludePattern
;
69 private Pattern staticExcludePattern
;
70 private Pattern resourceIncludePattern
;
71 private Pattern resourceExcludePattern
;
73 private String publicRoot
= "";
75 private String appRoot
;
77 private final Set
<String
> inboundServices
;
78 private boolean precompilationEnabled
= true;
80 private final List
<AdminConsolePage
> adminConsolePages
= new ArrayList
<AdminConsolePage
>();
81 private final List
<ErrorHandler
> errorHandlers
= new ArrayList
<ErrorHandler
>();
83 private ClassLoaderConfig classLoaderConfig
;
85 private String urlStreamHandlerType
= null;
87 private boolean threadsafe
= false;
88 private boolean threadsafeValueProvided
= false;
90 private String autoIdPolicy
;
92 private boolean codeLock
= false;
93 private boolean useVm
= false;
94 private ApiConfig apiConfig
;
95 private final List
<String
> apiEndpointIds
;
96 private Pagespeed pagespeed
;
99 * Represent user's choice w.r.t the usage of Google's customized connector-j.
101 public static enum UseGoogleConnectorJ
{
106 private UseGoogleConnectorJ useGoogleConnectorJ
= UseGoogleConnectorJ
.NOT_STATED_BY_USER
;
108 public AppEngineWebXml() {
109 automaticScaling
= new AutomaticScaling();
110 manualScaling
= new ManualScaling();
111 basicScaling
= new BasicScaling();
113 staticFileIncludes
= new ArrayList
<StaticFileInclude
>();
114 staticFileExcludes
= new ArrayList
<String
>();
115 staticFileExcludes
.add("WEB-INF/**");
116 staticFileExcludes
.add("**.jsp");
117 resourceFileIncludes
= new ArrayList
<String
>();
118 resourceFileExcludes
= new ArrayList
<String
>();
119 inboundServices
= new LinkedHashSet
<String
>();
120 apiEndpointIds
= new ArrayList
<String
>();
124 * @return An unmodifiable map whose entries correspond to the
125 * system properties defined in appengine-web.xml.
127 public Map
<String
, String
> getSystemProperties() {
128 return Collections
.unmodifiableMap(systemProperties
);
131 public void addSystemProperty(String key
, String value
) {
132 systemProperties
.put(key
, value
);
136 * @return An unmodifiable map whose entires correspond to the
137 * vm settings defined in appengine-web.xml.
139 public Map
<String
, String
> getVmSettings() {
140 return Collections
.unmodifiableMap(vmSettings
);
143 public void addVmSetting(String key
, String value
) {
144 vmSettings
.put(key
, value
);
148 * @return An unmodifiable map whose entires correspond to the
149 * environment variables defined in appengine-web.xml.
151 public Map
<String
, String
> getEnvironmentVariables() {
152 return Collections
.unmodifiableMap(envVariables
);
155 public void addEnvironmentVariable(String key
, String value
) {
156 envVariables
.put(key
, value
);
159 public String
getAppId() {
163 public void setAppId(String appId
) {
167 public String
getMajorVersionId() {
168 return majorVersionId
;
171 public void setMajorVersionId(String majorVersionId
) {
172 this.majorVersionId
= majorVersionId
;
175 public String
getSourceLanguage() {
176 return this.sourceLanguage
;
179 public void setSourceLanguage(String sourceLanguage
) {
180 this.sourceLanguage
= sourceLanguage
;
183 public String
getModule() {
188 * Sets instanceClass (aka class in the xml/yaml files). Normalizes empty and null
191 public void setInstanceClass(String instanceClass
) {
192 this.instanceClass
= StringUtil
.toNullIfEmptyOrWhitespace(instanceClass
);
195 public String
getInstanceClass() {
196 return instanceClass
;
199 public AutomaticScaling
getAutomaticScaling() {
200 return automaticScaling
;
203 public ManualScaling
getManualScaling() {
204 return manualScaling
;
207 public BasicScaling
getBasicScaling() {
211 public ScalingType
getScalingType() {
212 if (!getBasicScaling().isEmpty()) {
213 return ScalingType
.BASIC
;
214 } else if (!getManualScaling().isEmpty()) {
215 return ScalingType
.MANUAL
;
217 return ScalingType
.AUTOMATIC
;
221 public void setModule(String module
) {
222 this.module
= module
;
225 public void setSslEnabled(boolean ssl
) {
229 public boolean getSslEnabled() {
233 public void setSessionsEnabled(boolean sessions
) {
234 useSessions
= sessions
;
237 public boolean getSessionsEnabled() {
241 public void setAsyncSessionPersistence(boolean asyncSessionPersistence
) {
242 this.asyncSessionPersistence
= asyncSessionPersistence
;
245 public boolean getAsyncSessionPersistence() {
246 return asyncSessionPersistence
;
249 public void setAsyncSessionPersistenceQueueName(String asyncSessionPersistenceQueueName
) {
250 this.asyncSessionPersistenceQueueName
= asyncSessionPersistenceQueueName
;
253 public String
getAsyncSessionPersistenceQueueName() {
254 return asyncSessionPersistenceQueueName
;
257 public List
<StaticFileInclude
> getStaticFileIncludes() {
258 return staticFileIncludes
;
261 public List
<String
> getStaticFileExcludes() {
262 return staticFileExcludes
;
265 public StaticFileInclude
includeStaticPattern(String pattern
, String expiration
) {
266 staticIncludePattern
= null;
267 StaticFileInclude staticFileInclude
= new StaticFileInclude(pattern
, expiration
);
268 staticFileIncludes
.add(staticFileInclude
);
269 return staticFileInclude
;
272 public void excludeStaticPattern(String url
) {
273 staticExcludePattern
= null;
274 staticFileExcludes
.add(url
);
277 public List
<String
> getResourcePatterns() {
278 return resourceFileIncludes
;
281 public List
<String
> getResourceFileExcludes() {
282 return resourceFileExcludes
;
285 public void includeResourcePattern(String url
) {
286 resourceExcludePattern
= null;
287 resourceFileIncludes
.add(url
);
290 public void excludeResourcePattern(String url
) {
291 resourceIncludePattern
= null;
292 resourceFileExcludes
.add(url
);
295 public void addUserPermission(String className
, String name
, String actions
) {
296 if (className
.startsWith("java.")) {
297 throw new AppEngineConfigException("Cannot specify user-permissions for " +
298 "classes in java.* packages.");
301 userPermissions
.add(new UserPermission(className
, name
, actions
));
304 public Permissions
getUserPermissions() {
305 Permissions permissions
= new Permissions();
306 for (UserPermission permission
: userPermissions
) {
307 permissions
.add(new UnresolvedPermission(permission
.getClassName(),
308 permission
.getName(),
309 permission
.getActions(),
312 permissions
.setReadOnly();
316 public void setPublicRoot(String root
) {
317 if (root
.indexOf('*') != -1) {
318 throw new AppEngineConfigException("public-root cannot contain wildcards");
320 if (root
.endsWith("/")) {
321 root
= root
.substring(0, root
.length() - 1);
323 if (root
.length() > 0 && !root
.startsWith("/")) {
326 staticIncludePattern
= null;
330 public String
getPublicRoot() {
334 public void addInboundService(String service
) {
335 inboundServices
.add(service
);
338 public Set
<String
> getInboundServices() {
339 return inboundServices
;
342 public boolean getPrecompilationEnabled() {
343 return precompilationEnabled
;
346 public void setPrecompilationEnabled(boolean precompilationEnabled
) {
347 this.precompilationEnabled
= precompilationEnabled
;
350 public boolean getWarmupRequestsEnabled() {
351 return inboundServices
.contains(WARMUP_SERVICE
);
354 public void setWarmupRequestsEnabled(boolean warmupRequestsEnabled
) {
355 if (warmupRequestsEnabled
) {
356 inboundServices
.add(WARMUP_SERVICE
);
358 inboundServices
.remove(WARMUP_SERVICE
);
362 public List
<AdminConsolePage
> getAdminConsolePages() {
363 return Collections
.unmodifiableList(adminConsolePages
);
366 public void addAdminConsolePage(AdminConsolePage page
) {
367 adminConsolePages
.add(page
);
370 public List
<ErrorHandler
> getErrorHandlers() {
371 return Collections
.unmodifiableList(errorHandlers
);
374 public void addErrorHandler(ErrorHandler handler
) {
375 errorHandlers
.add(handler
);
378 public boolean getThreadsafe() {
382 public boolean getThreadsafeValueProvided() {
383 return threadsafeValueProvided
;
386 public void setThreadsafe(boolean threadsafe
) {
387 this.threadsafe
= threadsafe
;
388 this.threadsafeValueProvided
= true;
391 public void setAutoIdPolicy(String policy
) {
392 autoIdPolicy
= policy
;
395 public String
getAutoIdPolicy() {
399 public boolean getCodeLock() {
403 public void setCodeLock(boolean codeLock
) {
404 this.codeLock
= codeLock
;
407 public void setUseVm(boolean useVm
) {
411 public boolean getUseVm() {
415 public ApiConfig
getApiConfig() {
419 public void setApiConfig(ApiConfig config
) {
423 public ClassLoaderConfig
getClassLoaderConfig() {
424 return classLoaderConfig
;
427 public void setClassLoaderConfig(ClassLoaderConfig classLoaderConfig
) {
428 if (this.classLoaderConfig
!= null) {
429 throw new AppEngineConfigException("class-loader-config may only be specified once.");
431 this.classLoaderConfig
= classLoaderConfig
;
434 public String
getUrlStreamHandlerType() {
435 return urlStreamHandlerType
;
438 public void setUrlStreamHandlerType(String urlStreamHandlerType
) {
439 if (this.classLoaderConfig
!= null) {
440 throw new AppEngineConfigException("url-stream-handler may only be specified once.");
442 if (!URL_HANDLER_URLFETCH
.equals(urlStreamHandlerType
)
443 && !URL_HANDLER_NATIVE
.equals(urlStreamHandlerType
)) {
444 throw new AppEngineConfigException(
445 "url-stream-handler must be " + URL_HANDLER_URLFETCH
+ " or " + URL_HANDLER_NATIVE
+
446 " given " + urlStreamHandlerType
);
448 this.urlStreamHandlerType
= urlStreamHandlerType
;
452 * Returns true if {@code url} matches one of the servlets or servlet
453 * filters listed in this web.xml that has api-endpoint set to true.
455 public boolean isApiEndpoint(String id
) {
456 return apiEndpointIds
.contains(id
);
459 public void addApiEndpoint(String id
) {
460 apiEndpointIds
.add(id
);
463 public Pagespeed
getPagespeed() {
467 public void setPagespeed(Pagespeed pagespeed
) {
468 this.pagespeed
= pagespeed
;
471 public void setUseGoogleConnectorJ(boolean useGoogleConnectorJ
) {
472 if (useGoogleConnectorJ
) {
473 this.useGoogleConnectorJ
= UseGoogleConnectorJ
.TRUE
;
475 this.useGoogleConnectorJ
= UseGoogleConnectorJ
.FALSE
;
479 public UseGoogleConnectorJ
getUseGoogleConnectorJ() {
480 return useGoogleConnectorJ
;
484 public String
toString() {
485 return "AppEngineWebXml{" +
486 "systemProperties=" + systemProperties
+
487 ", envVariables=" + envVariables
+
488 ", userPermissions=" + userPermissions
+
489 ", appId='" + appId
+ '\'' +
490 ", majorVersionId='" + majorVersionId
+ '\'' +
491 ", sourceLanguage='" + sourceLanguage
+ '\'' +
492 ", module='" + module
+ '\'' +
493 ", instanceClass='" + instanceClass
+ '\'' +
494 ", automaticScaling=" + automaticScaling
+
495 ", manualScaling=" + manualScaling
+
496 ", basicScaling=" + basicScaling
+
497 ", sslEnabled=" + sslEnabled
+
498 ", useSessions=" + useSessions
+
499 ", asyncSessionPersistence=" + asyncSessionPersistence
+
500 ", asyncSessionPersistenceQueueName='" + asyncSessionPersistenceQueueName
+ '\'' +
501 ", staticFileIncludes=" + staticFileIncludes
+
502 ", staticFileExcludes=" + staticFileExcludes
+
503 ", resourceFileIncludes=" + resourceFileIncludes
+
504 ", resourceFileExcludes=" + resourceFileExcludes
+
505 ", staticIncludePattern=" + staticIncludePattern
+
506 ", staticExcludePattern=" + staticExcludePattern
+
507 ", resourceIncludePattern=" + resourceIncludePattern
+
508 ", resourceExcludePattern=" + resourceExcludePattern
+
509 ", publicRoot='" + publicRoot
+ '\'' +
510 ", appRoot='" + appRoot
+ '\'' +
511 ", inboundServices=" + inboundServices
+
512 ", precompilationEnabled=" + precompilationEnabled
+
513 ", adminConsolePages=" + adminConsolePages
+
514 ", errorHandlers=" + errorHandlers
+
515 ", threadsafe=" + threadsafe
+
516 ", threadsafeValueProvided=" + threadsafeValueProvided
+
517 ", autoIdPolicy=" + autoIdPolicy
+
518 ", codeLock=" + codeLock
+
519 ", apiConfig=" + apiConfig
+
520 ", apiEndpointIds=" + apiEndpointIds
+
521 ", pagespeed=" + pagespeed
+
522 ", classLoaderConfig=" + classLoaderConfig
+
523 ", urlStreamHandlerType=" +
524 (urlStreamHandlerType
== null ? URL_HANDLER_URLFETCH
: urlStreamHandlerType
) +
525 ", useGoogleConnectorJ=" + useGoogleConnectorJ
+
530 public boolean equals(Object o
) {
534 if (o
== null || getClass() != o
.getClass()) {
538 AppEngineWebXml that
= (AppEngineWebXml
) o
;
540 if (asyncSessionPersistence
!= that
.asyncSessionPersistence
) {
543 if (precompilationEnabled
!= that
.precompilationEnabled
) {
546 if (sslEnabled
!= that
.sslEnabled
) {
549 if (threadsafe
!= that
.threadsafe
) {
552 if (threadsafeValueProvided
!= that
.threadsafeValueProvided
) {
555 if (autoIdPolicy
!= null ?
!autoIdPolicy
.equals(that
.autoIdPolicy
)
556 : that
.autoIdPolicy
!= null) {
559 if (codeLock
!= that
.codeLock
) {
562 if (useSessions
!= that
.useSessions
) {
565 if (adminConsolePages
!= null ?
!adminConsolePages
.equals(that
.adminConsolePages
)
566 : that
.adminConsolePages
!= null) {
569 if (appId
!= null ?
!appId
.equals(that
.appId
) : that
.appId
!= null) {
572 if (majorVersionId
!= null ?
!majorVersionId
.equals(that
.majorVersionId
)
573 : that
.majorVersionId
!= null) {
576 if (module
!= null ?
!module
.equals(that
.module
) : that
.module
!= null) {
579 if (instanceClass
!= null ?
!instanceClass
.equals(that
.instanceClass
)
580 : that
.instanceClass
!= null) {
583 if (!automaticScaling
.equals(that
.automaticScaling
)) {
586 if (!manualScaling
.equals(that
.manualScaling
)) {
589 if (!basicScaling
.equals(that
.basicScaling
)) {
592 if (appRoot
!= null ?
!appRoot
.equals(that
.appRoot
) : that
.appRoot
!= null) {
595 if (asyncSessionPersistenceQueueName
!= null ?
!asyncSessionPersistenceQueueName
596 .equals(that
.asyncSessionPersistenceQueueName
)
597 : that
.asyncSessionPersistenceQueueName
!= null) {
600 if (envVariables
!= null ?
!envVariables
.equals(that
.envVariables
)
601 : that
.envVariables
!= null) {
604 if (errorHandlers
!= null ?
!errorHandlers
.equals(that
.errorHandlers
)
605 : that
.errorHandlers
!= null) {
608 if (inboundServices
!= null ?
!inboundServices
.equals(that
.inboundServices
)
609 : that
.inboundServices
!= null) {
612 if (majorVersionId
!= null ?
!majorVersionId
.equals(that
.majorVersionId
)
613 : that
.majorVersionId
!= null) {
616 if (sourceLanguage
!= null ?
!sourceLanguage
.equals(that
.sourceLanguage
)
617 : that
.sourceLanguage
!= null) {
620 if (publicRoot
!= null ?
!publicRoot
.equals(that
.publicRoot
) : that
.publicRoot
!= null) {
623 if (resourceExcludePattern
!= null ?
!resourceExcludePattern
.equals(that
.resourceExcludePattern
)
624 : that
.resourceExcludePattern
!= null) {
627 if (resourceFileExcludes
!= null ?
!resourceFileExcludes
.equals(that
.resourceFileExcludes
)
628 : that
.resourceFileExcludes
!= null) {
631 if (resourceFileIncludes
!= null ?
!resourceFileIncludes
.equals(that
.resourceFileIncludes
)
632 : that
.resourceFileIncludes
!= null) {
635 if (resourceIncludePattern
!= null ?
!resourceIncludePattern
.equals(that
.resourceIncludePattern
)
636 : that
.resourceIncludePattern
!= null) {
639 if (staticExcludePattern
!= null ?
!staticExcludePattern
.equals(that
.staticExcludePattern
)
640 : that
.staticExcludePattern
!= null) {
643 if (staticFileExcludes
!= null ?
!staticFileExcludes
.equals(that
.staticFileExcludes
)
644 : that
.staticFileExcludes
!= null) {
647 if (staticFileIncludes
!= null ?
!staticFileIncludes
.equals(that
.staticFileIncludes
)
648 : that
.staticFileIncludes
!= null) {
651 if (staticIncludePattern
!= null ?
!staticIncludePattern
.equals(that
.staticIncludePattern
)
652 : that
.staticIncludePattern
!= null) {
655 if (systemProperties
!= null ?
!systemProperties
.equals(that
.systemProperties
)
656 : that
.systemProperties
!= null) {
659 if (vmSettings
!= null ?
!vmSettings
.equals(that
.vmSettings
) : that
.vmSettings
!= null) {
663 if (userPermissions
!= null ?
!userPermissions
.equals(that
.userPermissions
)
664 : that
.userPermissions
!= null) {
667 if (apiConfig
!= null ?
!apiConfig
.equals(that
.apiConfig
)
668 : that
.apiConfig
!= null) {
671 if (apiEndpointIds
!= null ?
!apiEndpointIds
.equals(that
.apiEndpointIds
)
672 : that
.apiEndpointIds
!= null) {
675 if (pagespeed
!= null ?
!pagespeed
.equals(that
.pagespeed
) : that
.pagespeed
!= null) {
678 if (classLoaderConfig
!= null ?
!classLoaderConfig
.equals(that
.classLoaderConfig
) :
679 that
.classLoaderConfig
!= null) {
682 if (urlStreamHandlerType
!= null ?
!urlStreamHandlerType
.equals(that
.urlStreamHandlerType
) :
683 that
.urlStreamHandlerType
!= null) {
686 if (useGoogleConnectorJ
!= that
.useGoogleConnectorJ
) {
694 public int hashCode() {
695 int result
= systemProperties
!= null ? systemProperties
.hashCode() : 0;
696 result
= 31 * result
+ (envVariables
!= null ? envVariables
.hashCode() : 0);
697 result
= 31 * result
+ (userPermissions
!= null ? userPermissions
.hashCode() : 0);
698 result
= 31 * result
+ (appId
!= null ? appId
.hashCode() : 0);
699 result
= 31 * result
+ (majorVersionId
!= null ? majorVersionId
.hashCode() : 0);
700 result
= 31 * result
+ (sourceLanguage
!= null ? sourceLanguage
.hashCode() : 0);
701 result
= 31 * result
+ (module
!= null ? module
.hashCode() : 0);
702 result
= 31 * result
+ (instanceClass
!= null ? instanceClass
.hashCode() : 0);
703 result
= 31 * result
+ automaticScaling
.hashCode();
704 result
= 31 * result
+ manualScaling
.hashCode();
705 result
= 31 * result
+ basicScaling
.hashCode();
706 result
= 31 * result
+ (sslEnabled ?
1 : 0);
707 result
= 31 * result
+ (useSessions ?
1 : 0);
708 result
= 31 * result
+ (asyncSessionPersistence ?
1 : 0);
710 31 * result
+ (asyncSessionPersistenceQueueName
!= null ? asyncSessionPersistenceQueueName
712 result
= 31 * result
+ (staticFileIncludes
!= null ? staticFileIncludes
.hashCode() : 0);
713 result
= 31 * result
+ (staticFileExcludes
!= null ? staticFileExcludes
.hashCode() : 0);
714 result
= 31 * result
+ (resourceFileIncludes
!= null ? resourceFileIncludes
.hashCode() : 0);
715 result
= 31 * result
+ (resourceFileExcludes
!= null ? resourceFileExcludes
.hashCode() : 0);
716 result
= 31 * result
+ (staticIncludePattern
!= null ? staticIncludePattern
.hashCode() : 0);
717 result
= 31 * result
+ (staticExcludePattern
!= null ? staticExcludePattern
.hashCode() : 0);
718 result
= 31 * result
+ (resourceIncludePattern
!= null ? resourceIncludePattern
.hashCode() : 0);
719 result
= 31 * result
+ (resourceExcludePattern
!= null ? resourceExcludePattern
.hashCode() : 0);
720 result
= 31 * result
+ (publicRoot
!= null ? publicRoot
.hashCode() : 0);
721 result
= 31 * result
+ (appRoot
!= null ? appRoot
.hashCode() : 0);
722 result
= 31 * result
+ (inboundServices
!= null ? inboundServices
.hashCode() : 0);
723 result
= 31 * result
+ (precompilationEnabled ?
1 : 0);
724 result
= 31 * result
+ (adminConsolePages
!= null ? adminConsolePages
.hashCode() : 0);
725 result
= 31 * result
+ (errorHandlers
!= null ? errorHandlers
.hashCode() : 0);
726 result
= 31 * result
+ (threadsafe ?
1 : 0);
727 result
= 31 * result
+ (autoIdPolicy
!= null ? autoIdPolicy
.hashCode() : 0);
728 result
= 31 * result
+ (threadsafeValueProvided ?
1 : 0);
729 result
= 31 * result
+ (codeLock ?
1 : 0);
730 result
= 31 * result
+ (apiConfig
!= null ? apiConfig
.hashCode() : 0);
731 result
= 31 * result
+ (apiEndpointIds
!= null ? apiEndpointIds
.hashCode() : 0);
732 result
= 31 * result
+ (pagespeed
!= null ? pagespeed
.hashCode() : 0);
733 result
= 31 * result
+ (classLoaderConfig
!= null ? classLoaderConfig
.hashCode() : 0);
734 result
= 31 * result
+ (urlStreamHandlerType
!= null ? urlStreamHandlerType
.hashCode() : 0);
735 result
= 31 * result
+ (useGoogleConnectorJ
.hashCode());
736 result
= 31 * result
+ (vmSettings
!= null ? vmSettings
.hashCode() : 0);
740 public boolean includesResource(String path
) {
741 if (resourceIncludePattern
== null) {
742 if (resourceFileIncludes
.size() == 0) {
743 resourceIncludePattern
= Pattern
.compile(".*");
745 resourceIncludePattern
= Pattern
.compile(makeRegexp(resourceFileIncludes
));
748 if (resourceExcludePattern
== null && resourceFileExcludes
.size() > 0) {
749 resourceExcludePattern
= Pattern
.compile(makeRegexp(resourceFileExcludes
));
752 return includes(path
, resourceIncludePattern
, resourceExcludePattern
);
755 public boolean includesStatic(String path
) {
756 if (staticIncludePattern
== null) {
757 if (staticFileIncludes
.size() == 0) {
759 if (publicRoot
.length() > 0) {
760 staticRoot
= publicRoot
+ "/**";
764 staticIncludePattern
= Pattern
.compile(
765 makeRegexp(Collections
.singletonList(staticRoot
)));
767 List
<String
> patterns
= new ArrayList
<String
>();
768 for (StaticFileInclude include
: staticFileIncludes
) {
769 patterns
.add(include
.getPattern());
771 staticIncludePattern
= Pattern
.compile(makeRegexp(patterns
));
774 if (staticExcludePattern
== null && staticFileExcludes
.size() > 0) {
775 staticExcludePattern
= Pattern
.compile(makeRegexp(staticFileExcludes
));
778 return includes(path
, staticIncludePattern
, staticExcludePattern
);
782 * Tests whether {@code path} is covered by the pattern {@code includes}
783 * while not being blocked by matching {@code excludes}.
785 * @param path a URL to test
786 * @param includes a non-{@code null} pattern for included URLs
787 * @param excludes a pattern for exclusion, or {@code null} to not exclude
788 * anything from the {@code includes} set.
790 public boolean includes(String path
, Pattern includes
, Pattern excludes
) {
791 assert(includes
!= null);
792 if (!includes
.matcher(path
).matches()) {
795 if (excludes
!= null && excludes
.matcher(path
).matches()) {
801 public String
makeRegexp(List
<String
> patterns
) {
802 StringBuilder builder
= new StringBuilder();
803 boolean first
= true;
804 for (String item
: patterns
) {
811 while (item
.charAt(0) == '/') {
812 item
= item
.substring(1);
816 if (appRoot
!= null) {
817 builder
.append(makeFileRegex(appRoot
));
820 builder
.append(makeFileRegex(item
));
823 return builder
.toString();
827 * Helper method to translate from appengine-web.xml "file globs" to
828 * proper regular expressions as used in app.yaml.
830 * @param fileGlob the glob to translate
831 * @return the regular expression string matching the input {@code file} pattern.
833 static String
makeFileRegex(String fileGlob
) {
834 fileGlob
= fileGlob
.replaceAll("([^A-Za-z0-9\\-_/])", "\\\\$1");
835 fileGlob
= fileGlob
.replaceAll("\\\\\\*\\\\\\*", ".*");
836 fileGlob
= fileGlob
.replaceAll("\\\\\\*", "[^/]*");
840 * Sets the application root directory, as a prefix for the regexps in
841 * {@link #includeResourcePattern(String)} and friends. This is needed
842 * because we want to match complete filenames relative to root.
846 public void setSourcePrefix(String appRoot
) {
847 this.appRoot
= appRoot
;
848 this.resourceIncludePattern
= null;
849 this.resourceExcludePattern
= null;
850 this.staticIncludePattern
= null;
851 this.staticExcludePattern
= null;
854 public String
getSourcePrefix() {
859 * Represents a {@link java.security.Permission} that needs to be
860 * granted to user code.
862 private static class UserPermission
{
863 private final String className
;
864 private final String name
;
865 private final String actions
;
867 private boolean hasHashCode
= false;
868 private int hashCode
;
870 public UserPermission(String className
, String name
, String actions
) {
871 this.className
= className
;
873 this.actions
= actions
;
876 public String
getClassName() {
880 public String
getName() {
884 public String
getActions() {
889 public int hashCode() {
894 int hash
= className
.hashCode();
895 hash
= 31 * hash
+ name
.hashCode();
896 if (actions
!= null) {
897 hash
= 31 * hash
+ actions
.hashCode();
906 public boolean equals(Object obj
) {
907 if (obj
instanceof UserPermission
) {
908 UserPermission perm
= (UserPermission
) obj
;
909 if (className
.equals(perm
.className
) && name
.equals(perm
.name
)) {
910 if (actions
== null ? perm
.actions
== null : actions
.equals(perm
.actions
)) {
920 * Represents an <include> element within the
921 * <static-files> element. Currently this includes both a
922 * pattern and an optional expiration time specification.
924 public static class StaticFileInclude
{
925 private final String pattern
;
926 private final String expiration
;
927 private final Map
<String
, String
> httpHeaders
;
929 public StaticFileInclude(String pattern
, String expiration
) {
930 this.pattern
= pattern
;
931 this.expiration
= expiration
;
932 this.httpHeaders
= new HashMap
<String
, String
>();
935 public String
getPattern() {
939 public Pattern
getRegularExpression() {
940 return Pattern
.compile(makeFileRegex(pattern
));
943 public String
getExpiration() {
947 public Map
<String
, String
> getHttpHeaders() {
952 public int hashCode() {
953 return Objects
.hashCode(pattern
, expiration
, httpHeaders
);
957 public boolean equals(Object obj
) {
958 if (!(obj
instanceof StaticFileInclude
)) {
962 StaticFileInclude other
= (StaticFileInclude
) obj
;
964 if (pattern
!= null) {
965 if (!pattern
.equals(other
.pattern
)) {
969 if (other
.pattern
!= null) {
974 if (expiration
!= null) {
975 if (!expiration
.equals(other
.expiration
)) {
979 if (other
.expiration
!= null) {
984 if (httpHeaders
!= null) {
985 if (!httpHeaders
.equals(other
.httpHeaders
)) {
989 if (other
.httpHeaders
!= null) {
998 public static class AdminConsolePage
{
999 private final String name
;
1000 private final String url
;
1002 public AdminConsolePage(String name
, String url
) {
1007 public String
getName() {
1011 public String
getUrl() {
1016 public int hashCode() {
1017 final int prime
= 31;
1019 result
= prime
* result
+ ((name
== null) ?
0 : name
.hashCode());
1020 result
= prime
* result
+ ((url
== null) ?
0 : url
.hashCode());
1025 public boolean equals(Object obj
) {
1026 if (this == obj
) return true;
1027 if (obj
== null) return false;
1028 if (getClass() != obj
.getClass()) return false;
1029 AdminConsolePage other
= (AdminConsolePage
) obj
;
1031 if (other
.name
!= null) return false;
1032 } else if (!name
.equals(other
.name
)) return false;
1034 if (other
.url
!= null) return false;
1035 } else if (!url
.equals(other
.url
)) return false;
1041 * Represents an <error-handler> element. Currently this includes both
1042 * a file name and an optional error code.
1044 public static class ErrorHandler
{
1045 private final String file
;
1046 private final String errorCode
;
1048 public ErrorHandler(String file
, String errorCode
) {
1050 this.errorCode
= errorCode
;
1053 public String
getFile() {
1057 public String
getErrorCode() {
1062 public int hashCode() {
1063 final int prime
= 31;
1065 result
= prime
* result
+ ((file
== null) ?
0 : file
.hashCode());
1066 result
= prime
* result
+
1067 ((errorCode
== null) ?
0 : errorCode
.hashCode());
1072 public boolean equals(Object obj
) {
1073 if (!(obj
instanceof ErrorHandler
)) {
1077 ErrorHandler handler
= (ErrorHandler
) obj
;
1078 if (!file
.equals(handler
.file
)) {
1082 if (errorCode
== null) {
1083 if (handler
.errorCode
!= null) {
1087 if (!errorCode
.equals(handler
.errorCode
)) {
1097 * Represents an <api-config> element. This is a singleton specifying
1098 * url-pattern and servlet-class for the api config server.
1100 public static class ApiConfig
{
1101 private final String servletClass
;
1102 private final String url
;
1104 public ApiConfig(String servletClass
, String url
) {
1105 this.servletClass
= servletClass
;
1109 public String
getservletClass() {
1110 return servletClass
;
1113 public String
getUrl() {
1118 public int hashCode() {
1119 final int prime
= 31;
1121 result
= prime
* result
+ ((servletClass
== null) ?
0 : servletClass
.hashCode());
1122 result
= prime
* result
+ ((url
== null) ?
0 : url
.hashCode());
1127 public boolean equals(Object obj
) {
1128 if (this == obj
) { return true; }
1129 if (obj
== null) { return false; }
1130 if (getClass() != obj
.getClass()) { return false; }
1131 ApiConfig other
= (ApiConfig
) obj
;
1132 if (servletClass
== null) {
1133 if (other
.servletClass
!= null) { return false; }
1134 } else if (!servletClass
.equals(other
.servletClass
)) { return false; }
1136 if (other
.url
!= null) { return false; }
1137 } else if (!url
.equals(other
.url
)) { return false; }
1142 public String
toString() {
1143 return "ApiConfig{servletClass=\"" + servletClass
+ "\", url=\"" + url
+ "\"}";
1148 * Holder for automatic settings.
1150 public static class AutomaticScaling
{
1151 private static final AutomaticScaling EMPTY_SETTINGS
= new AutomaticScaling();
1153 public static final String AUTOMATIC
= "automatic";
1154 private String minPendingLatency
;
1155 private String maxPendingLatency
;
1156 private String minIdleInstances
;
1157 private String maxIdleInstances
;
1158 private String maxConcurrentRequests
;
1160 public String
getMinPendingLatency() {
1161 return minPendingLatency
;
1165 * Sets minPendingLatency. Normalizes empty and null inputs to null.
1167 public void setMinPendingLatency(String minPendingLatency
) {
1168 this.minPendingLatency
= StringUtil
.toNullIfEmptyOrWhitespace(minPendingLatency
);
1171 public String
getMaxPendingLatency() {
1172 return maxPendingLatency
;
1176 * Sets maxPendingLatency. Normalizes empty and null inputs to null.
1178 public void setMaxPendingLatency(String maxPendingLatency
) {
1179 this.maxPendingLatency
= StringUtil
.toNullIfEmptyOrWhitespace(maxPendingLatency
);
1182 public String
getMinIdleInstances() {
1183 return minIdleInstances
;
1187 * Sets minIdleInstances. Normalizes empty and null inputs to null.
1189 public void setMinIdleInstances(String minIdleInstances
) {
1190 this.minIdleInstances
= StringUtil
.toNullIfEmptyOrWhitespace(minIdleInstances
);
1193 public String
getMaxIdleInstances() {
1194 return maxIdleInstances
;
1198 * Sets maxIdleInstances. Normalizes empty and null inputs to null.
1200 public void setMaxIdleInstances(String maxIdleInstances
) {
1201 this.maxIdleInstances
= StringUtil
.toNullIfEmptyOrWhitespace(maxIdleInstances
);
1204 public boolean isEmpty() {
1205 return this.equals(EMPTY_SETTINGS
);
1208 public String
getMaxConcurrentRequests() {
1209 return maxConcurrentRequests
;
1213 * Sets maxConcurrentRequests. Normalizes empty and null inputs to null.
1215 public void setMaxConcurrentRequests(String maxConcurrentRequests
) {
1216 this.maxConcurrentRequests
= StringUtil
.toNullIfEmptyOrWhitespace(maxConcurrentRequests
);
1220 public int hashCode() {
1221 return Objects
.hashCode(maxPendingLatency
, minPendingLatency
,
1222 maxIdleInstances
, minIdleInstances
, maxConcurrentRequests
);
1226 public boolean equals(Object obj
) {
1233 if (getClass() != obj
.getClass()) {
1236 AutomaticScaling other
= (AutomaticScaling
) obj
;
1237 return Objects
.equal(maxPendingLatency
, other
.maxPendingLatency
)
1238 && Objects
.equal(minPendingLatency
, other
.minPendingLatency
)
1239 && Objects
.equal(maxIdleInstances
, other
.maxIdleInstances
)
1240 && Objects
.equal(minIdleInstances
, other
.minIdleInstances
)
1241 && Objects
.equal(maxConcurrentRequests
, other
.maxConcurrentRequests
);
1245 public String
toString() {
1246 return "AutomaticScaling [minPendingLatency=" + minPendingLatency
1247 + ", maxPendingLatency=" + maxPendingLatency
1248 + ", minIdleInstances=" + minIdleInstances
1249 + ", maxIdleInstances=" + maxIdleInstances
1250 + ", maxConcurrentRequests=" + maxConcurrentRequests
+ "]";
1255 * Holder for manual settings.
1257 public static class ManualScaling
{
1258 private static final ManualScaling EMPTY_SETTINGS
= new ManualScaling();
1260 private String instances
;
1262 public String
getInstances() {
1267 * Sets instances. Normalizes empty and null inputs to null.
1269 public void setInstances(String instances
) {
1270 this.instances
= StringUtil
.toNullIfEmptyOrWhitespace(instances
);
1273 public boolean isEmpty() {
1274 return this.equals(EMPTY_SETTINGS
);
1278 public int hashCode() {
1279 return Objects
.hashCode(instances
);
1283 public boolean equals(Object obj
) {
1290 if (getClass() != obj
.getClass()) {
1293 ManualScaling other
= (ManualScaling
) obj
;
1294 return Objects
.equal(instances
, other
.instances
);
1298 public String
toString() {
1299 return "ManualScaling [" + "instances=" + instances
+ "]";
1304 * Holder for basic settings.
1306 public static class BasicScaling
{
1307 private static final BasicScaling EMPTY_SETTINGS
= new BasicScaling();
1309 private String maxInstances
;
1310 private String idleTimeout
;
1312 public String
getMaxInstances() {
1313 return maxInstances
;
1316 public String
getIdleTimeout() {
1321 * Sets maxInstances. Normalizes empty and null inputs to null.
1323 public void setMaxInstances(String maxInstances
) {
1324 this.maxInstances
= StringUtil
.toNullIfEmptyOrWhitespace(maxInstances
);
1328 * Sets idleTimeout. Normalizes empty and null inputs to null.
1330 public void setIdleTimeout(String idleTimeout
) {
1331 this.idleTimeout
= StringUtil
.toNullIfEmptyOrWhitespace(idleTimeout
);
1334 public boolean isEmpty() {
1335 return this.equals(EMPTY_SETTINGS
);
1339 public int hashCode() {
1340 return Objects
.hashCode(maxInstances
, idleTimeout
);
1344 public boolean equals(Object obj
) {
1351 if (getClass() != obj
.getClass()) {
1354 BasicScaling other
= (BasicScaling
) obj
;
1355 return Objects
.equal(maxInstances
, other
.maxInstances
)
1356 && Objects
.equal(idleTimeout
, other
.idleTimeout
);
1360 public String
toString() {
1361 return "BasicScaling [" + "maxInstances=" + maxInstances
1362 + ", idleTimeout=" + idleTimeout
+ "]";
1367 * Represents a <pagespeed> element. This is used to specify configuration for the Page
1368 * Speed Service, which can be used to automatically optimize the loading speed of app engine
1371 public static class Pagespeed
{
1372 private final List
<String
> urlBlacklist
= Lists
.newArrayList();
1373 private final List
<String
> domainsToRewrite
= Lists
.newArrayList();
1374 private final List
<String
> enabledRewriters
= Lists
.newArrayList();
1375 private final List
<String
> disabledRewriters
= Lists
.newArrayList();
1377 public void addUrlBlacklist(String url
) {
1378 urlBlacklist
.add(url
);
1381 public List
<String
> getUrlBlacklist() {
1382 return Collections
.unmodifiableList(urlBlacklist
);
1385 public void addDomainToRewrite(String domain
) {
1386 domainsToRewrite
.add(domain
);
1389 public List
<String
> getDomainsToRewrite() {
1390 return Collections
.unmodifiableList(domainsToRewrite
);
1393 public void addEnabledRewriter(String rewriter
) {
1394 enabledRewriters
.add(rewriter
);
1397 public List
<String
> getEnabledRewriters() {
1398 return Collections
.unmodifiableList(enabledRewriters
);
1401 public void addDisabledRewriter(String rewriter
) {
1402 disabledRewriters
.add(rewriter
);
1405 public List
<String
> getDisabledRewriters() {
1406 return Collections
.unmodifiableList(disabledRewriters
);
1409 public boolean isEmpty() {
1410 return urlBlacklist
.isEmpty() && domainsToRewrite
.isEmpty() && enabledRewriters
.isEmpty()
1411 && disabledRewriters
.isEmpty();
1415 public int hashCode() {
1416 return Objects
.hashCode(urlBlacklist
, domainsToRewrite
, enabledRewriters
, disabledRewriters
);
1420 public boolean equals(Object obj
) {
1427 if (getClass() != obj
.getClass()) {
1430 Pagespeed other
= (Pagespeed
) obj
;
1431 return Objects
.equal(urlBlacklist
, other
.urlBlacklist
)
1432 && Objects
.equal(domainsToRewrite
, other
.domainsToRewrite
)
1433 && Objects
.equal(enabledRewriters
, other
.enabledRewriters
)
1434 && Objects
.equal(disabledRewriters
, other
.disabledRewriters
);
1438 public String
toString() {
1439 return "Pagespeed [urlBlacklist=" + urlBlacklist
+ ", domainsToRewrite=" + domainsToRewrite
1440 + ", enabledRewriters=" + enabledRewriters
+ ", disabledRewriters=" + disabledRewriters
1445 public static class ClassLoaderConfig
{
1446 private final List
<PrioritySpecifierEntry
> entries
= Lists
.newArrayList();
1448 public void add(PrioritySpecifierEntry entry
) {
1452 public List
<PrioritySpecifierEntry
> getEntries() {
1457 public int hashCode() {
1458 final int prime
= 31;
1460 result
= prime
* result
+ ((entries
== null) ?
0 : entries
.hashCode());
1465 public boolean equals(Object obj
) {
1466 if (this == obj
) return true;
1467 if (obj
== null) return false;
1468 if (getClass() != obj
.getClass()) return false;
1469 ClassLoaderConfig other
= (ClassLoaderConfig
) obj
;
1470 if (entries
== null) {
1471 if (other
.entries
!= null) return false;
1472 } else if (!entries
.equals(other
.entries
)) return false;
1477 public String
toString() {
1478 return "ClassLoaderConfig{entries=\"" + entries
+ "\"}";
1482 public static class PrioritySpecifierEntry
{
1483 private String filename
;
1484 private Double priority
;
1486 private void checkNotAlreadySet() {
1487 if (filename
!= null) {
1488 throw new AppEngineConfigException("Found more that one file name matching tag. "
1489 + "Only one of 'filename' attribute allowed.");
1493 public String
getFilename() {
1497 public void setFilename(String filename
) {
1498 checkNotAlreadySet();
1499 this.filename
= filename
;
1502 public Double
getPriority() {
1506 public double getPriorityValue() {
1507 if (priority
== null) {
1513 public void setPriority(String priority
) {
1514 if (this.priority
!= null) {
1515 throw new AppEngineConfigException("The 'priority' tag may only be specified once.");
1518 if (priority
== null) {
1519 this.priority
= null;
1523 this.priority
= Double
.parseDouble(priority
);
1526 public void checkClassLoaderConfig() {
1527 if (filename
== null) {
1528 throw new AppEngineConfigException("Must have a filename attribute.");
1533 public int hashCode() {
1534 final int prime
= 31;
1536 result
= prime
* result
+ ((filename
== null) ?
0 : filename
.hashCode());
1537 result
= prime
* result
+ ((priority
== null) ?
0 : priority
.hashCode());
1542 public boolean equals(Object obj
) {
1543 if (this == obj
) return true;
1544 if (obj
== null) return false;
1545 if (getClass() != obj
.getClass()) return false;
1546 PrioritySpecifierEntry other
= (PrioritySpecifierEntry
) obj
;
1547 if (filename
== null) {
1548 if (other
.filename
!= null) return false;
1549 } else if (!filename
.equals(other
.filename
)) return false;
1550 if (priority
== null) {
1551 if (other
.priority
!= null) return false;
1552 } else if (!priority
.equals(other
.priority
)) return false;
1557 public String
toString() {
1558 return "PrioritySpecifierEntry{filename=\"" + filename
+ "\", priority=\"" + priority
+ "\"}";