001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.microservice.tomcat;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020
021import java.time.*;
022
023/**
024 * Programmatic settings for the embedded Tomcat server contributed by {@link TomcatConfiguration}.
025 *
026 * <p>
027 * Users who need to override the defaults pulled from <c>Config</c> / <c>ManifestFile</c> should
028 * contribute a <c>@Bean TomcatSettings</c> from their own <c>@Configuration</c> class.  Any value
029 * left {@code null} on this settings bean falls back to the corresponding <c>Config</c> / <c>ManifestFile</c>
030 * entry, then to a hard-coded default.
031 *
032 * <h5 class='section'>Example:</h5>
033 * <p class='bjava'>
034 *    <ja>@Configuration</ja>
035 *    <jk>public class</jk> MyAppConfig {
036 *       <ja>@Bean</ja>
037 *       <jk>public</jk> TomcatSettings tomcatSettings() {
038 *          <jk>return</jk> TomcatSettings.<jsm>create</jsm>()
039 *             .ports(8080, 0)
040 *             .build();
041 *       }
042 *    }
043 * </p>
044 *
045 * <h5 class='section'>See Also:</h5><ul>
046 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceTomcat">juneau-microservice-tomcat</a>
047 * </ul>
048 *
049 * @since 10.0.0
050 */
051public class TomcatSettings {
052
053   /**
054    * Builder for {@link TomcatSettings}.
055    */
056   public static class Builder {
057
058      int[] ports;
059      String baseDir;
060      Duration stopTimeout;
061      Duration shutdownSettleDelay;
062
063      Builder() {}
064
065      /**
066       * Builds a new {@link TomcatSettings} from this builder.
067       *
068       * @return A new settings instance.
069       */
070      public TomcatSettings build() {
071         return new TomcatSettings(this);
072      }
073
074      /**
075       * Specifies the ports to try when binding the Tomcat server.
076       *
077       * <p>
078       * The first available port is used.  A value of <c>0</c> indicates "try a random port".  When set, this
079       * value takes precedence over the <c>Tomcat/port</c> config-file entry and the <c>Tomcat-Port</c>
080       * manifest entry.
081       *
082       * @param value The candidate ports, in priority order.  Can be <jk>null</jk> to defer to config / manifest.
083       * @return This object.
084       */
085      public Builder ports(int...value) {
086         ports = cp(value);
087         return this;
088      }
089
090      /**
091       * Specifies the Catalina base directory used by the embedded Tomcat server for its work files.
092       *
093       * <p>
094       * When set, the {@link TomcatServerFactory} uses this directory as both the Catalina base and the root
095       * context doc-base, and the directory is left in place after the server stops.  When not set, the
096       * {@link TomcatServerComponent} creates a fresh temp directory on start-up and deletes it on stop.
097       *
098       * @param value The absolute or relative path to the base directory.  Can be <jk>null</jk> to use an
099       *    auto-created temp directory.
100       * @return This object.
101       */
102      public Builder baseDir(String value) {
103         baseDir = value;
104         return this;
105      }
106
107      /**
108       * Specifies the bounded graceful-shutdown drain timeout for the Tomcat server.
109       *
110       * <p>
111       * On stop, the connector is paused (stops accepting new requests) and the component waits up to this
112       * duration for in-flight requests to complete before the server stops.  When set, this value takes
113       * precedence over the <c>Tomcat/stopTimeout</c> config-file entry (in milliseconds).  When neither is set,
114       * a default of {@code 30s} is applied.
115       *
116       * @param value The drain timeout.  Can be <jk>null</jk> to defer to config, then to the default.
117       * @return This object.
118       */
119      public Builder stopTimeout(Duration value) {
120         stopTimeout = value;
121         return this;
122      }
123
124      /**
125       * Specifies the settle delay applied between flipping the readiness probe out of service and stopping the
126       * connector.
127       *
128       * <p>
129       * On stop, the readiness probe ({@code /readyz}) flips to {@code 503} <i>before</i> the connector is paused
130       * so a load balancer / Kubernetes stops routing new traffic.  This brief delay gives the load balancer time
131       * to observe the {@code 503} before in-flight requests are drained.  When set, this value takes precedence
132       * over the <c>Tomcat/shutdownSettleDelay</c> config-file entry (in milliseconds).  When neither is set, no
133       * settle delay is applied (defaults to {@code 0}) &mdash; the recommended Kubernetes pattern is a
134       * {@code preStop} hook sleep instead.
135       *
136       * @param value The settle delay.  Can be <jk>null</jk> to defer to config, then to the default.
137       * @return This object.
138       */
139      public Builder shutdownSettleDelay(Duration value) {
140         shutdownSettleDelay = value;
141         return this;
142      }
143   }
144
145   /**
146    * Creates a new builder for this object.
147    *
148    * @return A new builder.
149    */
150   public static Builder create() {
151      return new Builder();
152   }
153
154   private final int[] ports;
155   private final String baseDir;
156   private final Duration stopTimeout;
157   private final Duration shutdownSettleDelay;
158
159   TomcatSettings(Builder b) {
160      ports = b.ports;
161      baseDir = b.baseDir;
162      stopTimeout = b.stopTimeout;
163      shutdownSettleDelay = b.shutdownSettleDelay;
164   }
165
166   /**
167    * Returns the candidate ports to try when binding the Tomcat server, in priority order.
168    *
169    * @return The ports, or <jk>null</jk> if not set.
170    */
171   public int[] getPorts() {
172      return cp(ports);
173   }
174
175   /**
176    * Returns the Catalina base directory to use when building the Tomcat server.
177    *
178    * @return The base directory path, or <jk>null</jk> if not set (an auto-created temp directory is used).
179    */
180   public String getBaseDir() {
181      return baseDir;
182   }
183
184   /**
185    * Returns the bounded graceful-shutdown drain timeout for the Tomcat server.
186    *
187    * @return The drain timeout, or <jk>null</jk> if not set.
188    */
189   public Duration getStopTimeout() {
190      return stopTimeout;
191   }
192
193   /**
194    * Returns the settle delay applied between flipping the readiness probe out of service and stopping the connector.
195    *
196    * @return The settle delay, or <jk>null</jk> if not set.
197    */
198   public Duration getShutdownSettleDelay() {
199      return shutdownSettleDelay;
200   }
201}