1 /*
2 * ====================================================================
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 * ====================================================================
20 *
21 * This software consists of voluntary contributions made by many
22 * individuals on behalf of the Apache Software Foundation. For more
23 * information on the Apache Software Foundation, please see
24 * <http://www.apache.org/>.
25 *
26 */
27
28 package org.apache.hc.core5.util;
29
30 import java.text.ParseException;
31 import java.time.Duration;
32 import java.util.concurrent.TimeUnit;
33
34 import org.apache.hc.core5.annotation.Contract;
35 import org.apache.hc.core5.annotation.ThreadingBehavior;
36
37 /**
38 * Represents a timeout value as a non-negative {@code long} time and {@link TimeUnit}.
39 *
40 * @since 5.0
41 */
42 @Contract(threading = ThreadingBehavior.IMMUTABLE)
43 public class Timeout extends TimeValue {
44
45 /**
46 * A zero milliseconds {@link Timeout}.
47 */
48 public static final Timeout ZERO_MILLISECONDS = Timeout.of(0, TimeUnit.MILLISECONDS);
49
50 /**
51 * A one milliseconds {@link Timeout}.
52 */
53 public static final Timeout ONE_MILLISECOND = Timeout.of(1, TimeUnit.MILLISECONDS);
54
55 /**
56 * A disabled timeout represented as 0 {@code MILLISECONDS}.
57 */
58 public static final Timeout DISABLED = ZERO_MILLISECONDS;
59
60 /**
61 * An infinite timeout represented as 0 {@code MILLISECONDS}.
62 *
63 * @since 5.3
64 */
65 public static final Timeout INFINITE = ZERO_MILLISECONDS;
66
67 /**
68 * Returns the given {@code timeout} if it is not {@code null}, if {@code null} then returns {@link #DISABLED}.
69 *
70 * @param timeout may be {@code null}
71 * @return {@code timeValue} or {@link #DISABLED}
72 */
73 public static Timeout defaultsToDisabled(final Timeout timeout) {
74 return defaultsTo(timeout, DISABLED);
75 }
76
77 /**
78 * Returns the given {@code timeout} if it is not {@code null}, if {@code null} then returns {@link #INFINITE}.
79 *
80 * @param timeout may be {@code null}
81 * @return {@code timeValue} or {@link #INFINITE}
82 *
83 * @since 5.3
84 */
85 public static Timeout defaultsToInfinite(final Timeout timeout) {
86 return defaultsTo(timeout, DISABLED);
87 }
88
89 /**
90 * Creates a Timeout from a Duration.
91 *
92 * @param duration the time duration.
93 * @return a Timeout.
94 * @since 5.2
95 */
96 public static Timeout of(final Duration duration) {
97 final long seconds = duration.getSeconds();
98 final long nanoOfSecond = duration.getNano();
99 if (seconds == 0) {
100 // no conversion
101 return of(nanoOfSecond, TimeUnit.NANOSECONDS);
102 } else if (nanoOfSecond == 0) {
103 // no conversion
104 return of(seconds, TimeUnit.SECONDS);
105 }
106 // conversion attempts
107 try {
108 return of(duration.toNanos(), TimeUnit.NANOSECONDS);
109 } catch (final ArithmeticException e) {
110 try {
111 return of(duration.toMillis(), TimeUnit.MILLISECONDS);
112 } catch (final ArithmeticException e1) {
113 // backstop
114 return of(seconds, TimeUnit.SECONDS);
115 }
116 }
117 }
118
119 /**
120 * Creates a Timeout.
121 *
122 * @param duration the time duration.
123 * @param timeUnit the time unit for the given duration.
124 * @return a Timeout
125 */
126 public static Timeout of(final long duration, final TimeUnit timeUnit) {
127 return new Timeout(duration, timeUnit);
128 }
129
130 /**
131 * Creates a Timeout.
132 *
133 * @param days the duration in days and the given {@code timeUnit}.
134 * @return a Timeout
135 */
136 public static Timeout ofDays(final long days) {
137 return of(days, TimeUnit.DAYS);
138 }
139
140 /**
141 * Creates a Timeout.
142 *
143 * @param hours the duration in hours and the given {@code timeUnit}.
144 * @return a Timeout
145 */
146 public static Timeout ofHours(final long hours) {
147 return of(hours, TimeUnit.HOURS);
148 }
149
150 /**
151 * Creates a Timeout.
152 *
153 * @param microseconds the duration in seconds and the given {@code timeUnit}.
154 * @return a Timeout
155 */
156 public static Timeout ofMicroseconds(final long microseconds) {
157 return of(microseconds, TimeUnit.MICROSECONDS);
158 }
159
160 /**
161 * Creates a Timeout.
162 *
163 * @param milliseconds the duration in milliseconds and the given {@code timeUnit}.
164 * @return a Timeout
165 */
166 public static Timeout ofMilliseconds(final long milliseconds) {
167 return of(milliseconds, TimeUnit.MILLISECONDS);
168 }
169
170 /**
171 * Creates a Timeout.
172 *
173 * @param minutes the duration in minutes and the given {@code timeUnit}.
174 * @return a Timeout
175 */
176 public static Timeout ofMinutes(final long minutes) {
177 return of(minutes, TimeUnit.MINUTES);
178 }
179
180 /**
181 * Creates a Timeout.
182 *
183 * @param nanoseconds the duration in seconds and the given {@code timeUnit}.
184 * @return a Timeout
185 */
186 public static Timeout ofNanoseconds(final long nanoseconds) {
187 return of(nanoseconds, TimeUnit.NANOSECONDS);
188 }
189
190 /**
191 * Creates a Timeout.
192 *
193 * @param seconds the duration in seconds and the given {@code timeUnit}.
194 * @return a Timeout
195 */
196 public static Timeout ofSeconds(final long seconds) {
197 return of(seconds, TimeUnit.SECONDS);
198 }
199
200 /**
201 * Parses a Timeout in the format {@code <Integer><SPACE><TimeUnit>}, for example {@code "1,200 MILLISECONDS"}
202 *
203 * @param value the TimeValue to parse
204 * @return a new TimeValue
205 * @throws ParseException if the number cannot be parsed
206 */
207 public static Timeout parse(final String value) throws ParseException {
208 return TimeValue.parse(value).toTimeout();
209 }
210
211 Timeout(final long duration, final TimeUnit timeUnit) {
212 super(Args.notNegative(duration, "duration"), Args.notNull(timeUnit, "timeUnit"));
213 }
214
215 /**
216 * Whether this timeout is disabled.
217 *
218 * @return Whether this timeout is disabled.
219 */
220 public boolean isDisabled() {
221 return getDuration() == 0;
222 }
223
224 /**
225 * Whether this timeout is enabled.
226 *
227 * @return Whether this timeout is disabled.
228 */
229 public boolean isEnabled() {
230 return !isDisabled();
231 }
232
233 }