App Engine 1.8.4.
[gae.git] / java / src / main / com / google / apphosting / utils / config / BackendsXml.java
blob75fd0d310fb499cf90963226068b021eeb1c01d9
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;
8 import java.util.List;
9 import java.util.Set;
10 import java.util.Collections;
12 /**
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) {
27 backends.add(entry);
30 @Override
31 public String toString() {
32 return backends.toString();
35 @Override
36 public boolean equals(Object obj) {
37 if (obj instanceof BackendsXml) {
38 return backends.equals(((BackendsXml) obj).backends);
40 return false;
43 @Override
44 public int hashCode() {
45 return backends.hashCode();
48 /**
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();
81 /**
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) {
96 this.name = name;
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;
104 this.state = state;
107 public String getName() {
108 return name;
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() {
117 return instances;
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() {
143 return options;
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
150 * being aborted.
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() {
180 return state;
183 @Override
184 public int hashCode() {
185 int result = 1;
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());
192 return result;
195 @Override
196 public boolean equals(Object obj) {
197 if (!(obj instanceof Entry)) {
198 return false;
201 Entry entry = (Entry) obj;
202 if (!name.equals(entry.name)) {
203 return false;
205 if ((instances == null) ? entry.instances != null : !instances.equals(entry.instances)) {
206 return false;
208 if ((instanceClass == null) ? entry.instanceClass != null :
209 !instanceClass.equals(entry.instanceClass)) {
210 return false;
212 if ((maxConcurrentRequests == null) ? entry.maxConcurrentRequests != null :
213 !maxConcurrentRequests.equals(entry.maxConcurrentRequests)) {
214 return false;
216 if ((options == null) ? entry.options != null : !options.equals(entry.options)) {
217 return false;
219 return true;
222 @Override
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);
239 if (state != null) {
240 builder.append(", state = " + state);
242 return builder.toString();
246 public enum Option {
247 DYNAMIC("dynamic"),
248 FAIL_FAST("failfast"),
249 PUBLIC("public");
251 private final String yamlValue;
253 Option(String yamlValue) {
254 this.yamlValue = yamlValue;
257 public String getYamlValue() {
258 return yamlValue;
261 public static Option fromYamlValue(String yamlValue) {
262 for (Option option : values()) {
263 if (option.getYamlValue().equals(yamlValue)) {
264 return option;
267 throw new IllegalArgumentException("Unknown value: " + yamlValue);
272 * Defines the current or desired state of a particular server.
274 public enum State {
275 START("START"),
276 STOP("STOP");
278 private final String yamlValue;
280 State(String yamlValue) {
281 this.yamlValue = yamlValue;
284 public String getYamlValue() {
285 return yamlValue;
288 public static State fromYamlValue(String yamlValue) {
289 for (State state : values()) {
290 if (state.getYamlValue().equals(yamlValue)) {
291 return state;
294 throw new IllegalArgumentException("Unknown value: " + yamlValue);