• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

devonfw / IDEasy / 22284264868

22 Feb 2026 08:00PM UTC coverage: 70.75% (+0.3%) from 70.474%
22284264868

Pull #1714

github

web-flow
Merge 98f01421f into 379acdc9d
Pull Request #1714: #404: #1713: advanced logging

4063 of 6346 branches covered (64.02%)

Branch coverage included in aggregate %.

10636 of 14430 relevant lines covered (73.71%)

3.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

51.47
cli/src/main/java/com/devonfw/tools/ide/step/Step.java
1
package com.devonfw.tools.ide.step;
2

3
import java.util.concurrent.Callable;
4
import java.util.function.Supplier;
5

6
/**
7
 * Interface for a {@link Step} of the process. Allows to split larger processes into smaller steps that are traced and measured. Also prevents that if one step
8
 * fails, the overall process can still continue so a sub-step (e.g. "plugin installation" or "git update") does not automatically block the entire process. At
9
 * the end you can get a report with the hierarchy of all steps and their success/failure status, duration in absolute and relative numbers to gain
10
 * transparency.<br> The typical use should follow this pattern:
11
 *
12
 * <pre>
13
 * Step step = context.{@link com.devonfw.tools.ide.context.IdeContext#newStep(String) newStep}("My step description");
14
 * step.run(() -> {
15
 *   // ... do something ...
16
 *   if (success) {
17
 *     step.{@link #success(String) success}("Did something successfully.");
18
 *   } else {
19
 *     step.{@link #error(String) error}("Failed to do something.");
20
 *   }
21
 * });
22
 * </pre>
23
 * No need to manually catch exceptions and report them as error. All this will happen automatically in {@link #run(Runnable)} method. You may pass a private
24
 * method as lambda to avoid multiline lambda syntax.
25
 */
26
public interface Step {
2!
27

28
  /**
29
   * Empty object array for no parameters.
30
   */
31
  Object[] NO_PARAMS = new Object[0];
4✔
32

33
  /**
34
   * @return the name of this {@link Step} as given to constructor.
35
   */
36
  String getName();
37

38
  /**
39
   * @return the duration of this {@link Step} from construction to {@link #success()} or {@link #close()}. Will be {@code 0} if not {@link #close() ended}.
40
   */
41
  long getDuration();
42

43
  /**
44
   * @return {@code Boolean#TRUE} if this {@link Step} has {@link #success() succeeded}, {@code Boolean#FALSE} if the {@link Step} has {@link #close() ended}
45
   *     without {@link #success() success} and {@code null} if the {@link Step} is still running.
46
   */
47
  Boolean getSuccess();
48

49
  /**
50
   * @return {@code true} if this step completed {@link #success() successfully}, {@code false} otherwise.
51
   */
52
  default boolean isSuccess() {
53

54
    return Boolean.TRUE.equals(getSuccess());
×
55
  }
56

57
  /**
58
   * @return {@code true} if this step {@link #close() ended} without {@link #success() success} e.g. with an {@link #error(String) error}, {@code false}
59
   *     otherwise.
60
   */
61
  default boolean isFailure() {
62

63
    return Boolean.FALSE.equals(getSuccess());
×
64
  }
65

66
  /**
67
   * @return {@code true} if this step is silent and not logged by default, {@code false} otherwise (default).
68
   */
69
  boolean isSilent();
70

71
  /**
72
   * Should be called to end this {@link Step} {@link #getSuccess() successfully}. May be called only once.
73
   *
74
   * @param silent to suppress the success message from being logged.
75
   */
76
  default void success(boolean silent) {
77
    success();
×
78
  }
×
79

80
  /**
81
   * Should be called to end this {@link Step} {@link #getSuccess() successfully}. May be called only once.
82
   */
83
  default void success() {
84

85
    success(null);
3✔
86
  }
1✔
87

88
  /**
89
   * Should be called to end this {@link Step} {@link #getSuccess() successfully}. May be called only once.
90
   *
91
   * @param message the explicit message to log as success.
92
   */
93
  default void success(String message) {
94

95
    success(message, (Object[]) null);
5✔
96
  }
1✔
97

98
  /**
99
   * Should be called to end this {@link Step} {@link #getSuccess() successfully}. May be called only once.
100
   *
101
   * @param message the explicit message to log as success.
102
   * @param args the optional arguments to fill as placeholder into the {@code message}.
103
   */
104
  void success(String message, Object... args);
105

106
  /**
107
   * Ensures this {@link Step} is properly ended. Has to be called from a finally block. Do not call manually but always use {@link #run(Runnable)} or
108
   * {@link #call(Callable)}.
109
   */
110
  void close();
111

112
  /**
113
   * Should be called to end this {@link Step} as {@link #isFailure() failure} with an explicit error message. May be called only once.
114
   *
115
   * @param message the explicit message to log as error.
116
   */
117
  default void error(String message) {
118

119
    error(null, message);
4✔
120
  }
1✔
121

122
  /**
123
   * Should be called to end this {@link Step} as {@link #isFailure() failure} with an explicit error message and/or {@link Throwable exception}. May be called
124
   * only once.
125
   *
126
   * @param message the explicit message to log as error.
127
   * @param args the optional arguments to fill as placeholder into the {@code message}.
128
   */
129
  default void error(String message, Object... args) {
130

131
    error(null, message, args);
5✔
132
  }
1✔
133

134
  /**
135
   * Should be called to end this {@link Step} as {@link #isFailure() failure} with an explicit error message and/or {@link Throwable exception}. May be called
136
   * only once.
137
   *
138
   * @param error the caught {@link Throwable}.
139
   */
140
  default void error(Throwable error) {
141

142
    error(error, false);
4✔
143
  }
1✔
144

145
  /**
146
   * Should be called to end this {@link Step} as {@link #isFailure() failure} with an explicit error message and/or {@link Throwable exception}. May be called
147
   * only once.
148
   *
149
   * @param error the caught {@link Throwable}.
150
   * @param suppress to suppress the error logging (if error will be rethrown and duplicated error messages shall be avoided).
151
   */
152
  default void error(Throwable error, boolean suppress) {
153

154
    assert (error != null);
4!
155
    error(error, suppress, null, (Object[]) null);
7✔
156
  }
1✔
157

158
  /**
159
   * Should be called to end this {@link Step} as {@link #isFailure() failure} with an explicit error message and/or {@link Throwable exception}. May be called
160
   * only once.
161
   *
162
   * @param error the catched {@link Throwable}. May be {@code null} if only a {@code message} is provided.
163
   * @param message the explicit message to log as error.
164
   */
165
  default void error(Throwable error, String message) {
166

167
    error(error, message, (Object[]) null);
6✔
168
  }
1✔
169

170
  /**
171
   * Should be called to end this {@link Step} as {@link #isFailure() failure} with an explicit error message and/or {@link Throwable exception}. May be called
172
   * only once.
173
   *
174
   * @param error the caught {@link Throwable}. May be {@code null} if only a {@code message} is provided.
175
   * @param message the explicit message to log as error.
176
   * @param args the optional arguments to fill as placeholder into the {@code message}.
177
   */
178
  default void error(Throwable error, String message, Object... args) {
179

180
    error(error, false, message, args);
6✔
181
  }
1✔
182

183
  /**
184
   * Should be called to end this {@link Step} as {@link #isFailure() failure} with an explicit error message and/or {@link Throwable exception}. May be called
185
   * only once.
186
   *
187
   * @param error the caught {@link Throwable}. May be {@code null} if only a {@code message} is provided.
188
   * @param suppress to suppress the error logging (if error will be rethrown and duplicated error messages shall be avoided).
189
   * @param message the explicit message to log as error.
190
   * @param args the optional arguments to fill as placeholder into the {@code message}.
191
   */
192
  void error(Throwable error, boolean suppress, String message, Object... args);
193

194
  /**
195
   * @return the parent {@link Step} or {@code null} if there is no parent.
196
   */
197
  Step getParent();
198

199
  /**
200
   * @param i the index of the requested parameter. Should be in the range from {@code 0} to
201
   *     <code>{@link #getParameterCount()}-1</code>.
202
   * @return the parameter at the given index {@code i} or {@code null} if no such parameter exists.
203
   */
204
  Object getParameter(int i);
205

206
  /**
207
   * @return the number of {@link #getParameter(int) parameters}.
208
   */
209
  int getParameterCount();
210

211
  /**
212
   * @param stepCode the {@link Runnable} to {@link Runnable#run() execute} for this {@link Step}.
213
   * @return {@code true} on success, {@code false} on error.
214
   */
215
  default boolean run(Runnable stepCode) {
216

217
    return run(stepCode, false);
5✔
218
  }
219

220
  /**
221
   * @param stepCode the {@link Runnable} to {@link Runnable#run() execute} for this {@link Step}.
222
   * @param rethrow - {@code true} to rethrow a potential {@link Throwable error}.
223
   * @return {@code true} on success, {@code false} on error (if {@code rethrow} is {@code false}).
224
   */
225
  default boolean run(Runnable stepCode, boolean rethrow) {
226

227
    try {
228
      stepCode.run();
2✔
229
      if (getSuccess() == null) {
3✔
230
        success();
2✔
231
      }
232
      return true;
4✔
233
    } catch (RuntimeException | Error e) {
1✔
234
      error(e);
3✔
235
      if (rethrow) {
2!
236
        throw e;
×
237
      }
238
      return false;
4✔
239
    } finally {
240
      close();
2✔
241
    }
242
  }
243

244
  /**
245
   * @param stepCode the {@link Callable} to {@link Callable#call() execute} for this {@link Step}.
246
   * @param <R> type of the return value.
247
   * @return the value returned from {@link Callable#call()}.
248
   */
249
  default <R> R call(Callable<R> stepCode) {
250

251
    return call(stepCode, true, null);
×
252
  }
253

254
  /**
255
   * @param stepCode the {@link Callable} to {@link Callable#call() execute} for this {@link Step}.
256
   * @param resultOnErrorSupplier the {@link Supplier} {@link Supplier#get() providing} the result to be returned in case of a {@link Throwable error}.
257
   * @param <R> type of the return value.
258
   * @return the value returned from {@link Callable#call()}.
259
   */
260
  default <R> R call(Callable<R> stepCode, Supplier<R> resultOnErrorSupplier) {
261

262
    return call(stepCode, false, resultOnErrorSupplier);
×
263
  }
264

265
  /**
266
   * @param stepCode the {@link Callable} to {@link Callable#call() execute} for this {@link Step}.
267
   * @param rethrow - {@code true} to rethrow a potential {@link Throwable error}.
268
   * @param resultOnErrorSupplier the {@link Supplier} {@link Supplier#get() providing} the result to be returned in case of a {@link Throwable error}.
269
   * @param <R> type of the return value.
270
   * @return the value returned from {@link Callable#call()}.
271
   */
272
  default <R> R call(Callable<R> stepCode, boolean rethrow, Supplier<R> resultOnErrorSupplier) {
273

274
    try {
275
      R result = stepCode.call();
×
276
      if (getSuccess() == null) {
×
277
        success();
×
278
      }
279
      return result;
×
280
    } catch (Throwable e) {
×
281
      error(e);
×
282
      if (rethrow) {
×
283
        if (e instanceof RuntimeException re) {
×
284
          throw re;
×
285
        } else if (e instanceof Error error) {
×
286
          throw error;
×
287
        } else {
288
          throw new IllegalStateException(e);
×
289
        }
290
      }
291
      return resultOnErrorSupplier.get();
×
292
    } finally {
293
      close();
×
294
    }
295
  }
296

297
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc