1 // Copyright 2011 Google Inc. All Rights Reserved.
3 package com
.google
.apphosting
.utils
.config
;
5 import com
.google
.common
.base
.Joiner
;
7 import java
.util
.ArrayList
;
10 import java
.util
.Collections
;
13 * Parsed backends.xml file.
16 public class BackendsXml
{
18 public static final Set
<Option
> EMPTY_OPTIONS
= Collections
.<Option
>emptySet();
20 private final List
<Entry
> backends
= new ArrayList
<Entry
>();
22 public List
<Entry
> getBackends() {
23 return Collections
.unmodifiableList(backends
);
26 public void addBackend(Entry entry
) {
31 public String
toString() {
32 return backends
.toString();
36 public boolean equals(Object obj
) {
37 if (obj
instanceof BackendsXml
) {
38 return backends
.equals(((BackendsXml
) obj
).backends
);
44 public int hashCode() {
45 return backends
.hashCode();
49 * Get the YAML equivalent of this backends.xml file.
51 * @return contents of an equivalent {@code backends.yaml} file.
53 public String
toYaml() {
54 StringBuilder builder
= new StringBuilder();
55 List
<BackendsXml
.Entry
> backends
= getBackends();
56 if (!backends
.isEmpty()) {
57 builder
.append("backends:\n");
58 for (BackendsXml
.Entry entry
: backends
) {
59 builder
.append("- name: " + entry
.getName() + "\n");
60 if (entry
.getInstances() != null) {
61 builder
.append(" instances: " + entry
.getInstances() + "\n");
63 if (entry
.getInstanceClass() != null) {
64 builder
.append(" class: " + entry
.getInstanceClass() + "\n");
66 if (entry
.getMaxConcurrentRequests() != null) {
67 builder
.append(" max_concurrent_requests: " + entry
.getMaxConcurrentRequests() + "\n");
69 List
<String
> options
= new ArrayList
<String
>();
70 for (BackendsXml
.Option option
: entry
.getOptions()) {
71 options
.add(option
.getYamlValue());
73 if (!options
.isEmpty()) {
74 builder
.append(" options: " + Joiner
.on(", ").useForNull("null").join(options
) + "\n");
78 return builder
.toString();
82 * A {@code Entry} encapsulates the definition of a
83 * long-running, addressable server.
85 public static class Entry
{
86 private final String name
;
87 private final Integer instances
;
88 private final String instanceClass
;
89 private final Integer maxConcurrentRequests
;
90 private final Set
<Option
> options
;
91 private final State state
;
93 public Entry(String name
, Integer instances
, String instanceClass
,
94 Integer maxConcurrentRequests
,
95 Set
<Option
> options
, State state
) {
97 this.instances
= instances
;
98 this.instanceClass
= instanceClass
;
99 this.maxConcurrentRequests
= maxConcurrentRequests
;
100 if (options
== null) {
101 throw new NullPointerException("options must be specified");
103 this.options
= options
;
107 public String
getName() {
112 * The number of instances of this server to run. Each will be
113 * individually addressable. If {@code null}, the default number
114 * of instances will be used.
116 public Integer
getInstances() {
121 * The instance class of the instances. If {@code null}, the
122 * default instance class will be used.
124 public String
getInstanceClass() {
125 return instanceClass
;
129 * The maximum number of threads used to serve concurrent
130 * requests. If {@code null} and the application is marked
131 * thread-safe in {@code appengine-web.xml}, the default number of
132 * concurrent requests will be used. If it is not marked
133 * threadsafe, this value is assumed to be 1.
135 public Integer
getMaxConcurrentRequests() {
136 return maxConcurrentRequests
;
140 * The set of boolean options enabled for this server.
142 public Set
<Option
> getOptions() {
147 * If true, indicates that requests to this backend will fail if
148 * they cannot be handled immediately. If false, requests to this
149 * backend will wait nia pending queue for up to 10 seconds before
152 public boolean isFailFast() {
153 return options
.contains(Option
.FAIL_FAST
);
157 * If true, indicates that instances of this backend will only be
158 * started when user requests arrive, and are turned down when
159 * idle. If false, this backend is started automatically and is
160 * resident in memory until manually stopped.
162 public boolean isDynamic() {
163 return options
.contains(Option
.DYNAMIC
);
167 * If true, indicates that this backend is publicly accessible and
168 * can serve HTTP on the web. If false, this backend is private
169 * and can only be accessed by internal requests, such as
170 * URLFetch, Task Queue, and Cron requests.
172 public boolean isPublic() {
173 return options
.contains(Option
.PUBLIC
);
177 * The current state of the server, or {@code null} if the state is unknown.
179 public State
getState() {
184 public int hashCode() {
186 result
= 31 * result
+ name
.hashCode();
187 result
= 31 * result
+ ((instances
== null) ?
0 : instances
.hashCode());
188 result
= 31 * result
+ ((instanceClass
== null) ?
0 : instanceClass
.hashCode());
189 result
= 31 * result
+ ((maxConcurrentRequests
== null) ?
0 :
190 maxConcurrentRequests
.hashCode());
191 result
= 31 * result
+ ((options
== null) ?
0 : options
.hashCode());
196 public boolean equals(Object obj
) {
197 if (!(obj
instanceof Entry
)) {
201 Entry entry
= (Entry
) obj
;
202 if (!name
.equals(entry
.name
)) {
205 if ((instances
== null) ? entry
.instances
!= null : !instances
.equals(entry
.instances
)) {
208 if ((instanceClass
== null) ? entry
.instanceClass
!= null :
209 !instanceClass
.equals(entry
.instanceClass
)) {
212 if ((maxConcurrentRequests
== null) ? entry
.maxConcurrentRequests
!= null :
213 !maxConcurrentRequests
.equals(entry
.maxConcurrentRequests
)) {
216 if ((options
== null) ? entry
.options
!= null : !options
.equals(entry
.options
)) {
223 public String
toString() {
224 StringBuilder builder
= new StringBuilder();
225 builder
.append("Backend: ");
226 builder
.append(name
);
227 if (instances
!= null) {
228 builder
.append(", instances = " + instances
);
230 if (instanceClass
!= null) {
231 builder
.append(", instanceClass = " + instanceClass
);
233 if (maxConcurrentRequests
!= null) {
234 builder
.append(", maxConcurrentRequests = " + maxConcurrentRequests
);
236 if (options
!= null) {
237 builder
.append(", options = " + options
);
240 builder
.append(", state = " + state
);
242 return builder
.toString();
248 FAIL_FAST("failfast"),
251 private final String yamlValue
;
253 Option(String yamlValue
) {
254 this.yamlValue
= yamlValue
;
257 public String
getYamlValue() {
261 public static Option
fromYamlValue(String yamlValue
) {
262 for (Option option
: values()) {
263 if (option
.getYamlValue().equals(yamlValue
)) {
267 throw new IllegalArgumentException("Unknown value: " + yamlValue
);
272 * Defines the current or desired state of a particular server.
278 private final String yamlValue
;
280 State(String yamlValue
) {
281 this.yamlValue
= yamlValue
;
284 public String
getYamlValue() {
288 public static State
fromYamlValue(String yamlValue
) {
289 for (State state
: values()) {
290 if (state
.getYamlValue().equals(yamlValue
)) {
294 throw new IllegalArgumentException("Unknown value: " + yamlValue
);