1 //
2 // ========================================================================
3 // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
8 //
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
11 //
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
14 //
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
17 //
18
19 package org.eclipse.jetty.util;
20
21 import java.util.concurrent.CompletableFuture;
22
23 import org.eclipse.jetty.util.thread.Invocable;
24
25 /**
26 * <p>A callback abstraction that handles completed/failed events of asynchronous operations.</p>
27 *
28 * <p>Semantically this is equivalent to an optimise Promise<Void>, but callback is a more meaningful
29 * name than EmptyPromise</p>
30 */
31 public interface Callback extends Invocable
32 {
33 /**
34 * Instance of Adapter that can be used when the callback methods need an empty
35 * implementation without incurring in the cost of allocating a new Adapter object.
36 */
37 static Callback NOOP = new Callback()
38 {
39 };
40
41 /**
42 * <p>Callback invoked when the operation completes.</p>
43 *
44 * @see #failed(Throwable)
45 */
46 default void succeeded()
47 {
48 }
49
50 /**
51 * <p>Callback invoked when the operation fails.</p>
52 * @param x the reason for the operation failure
53 */
54 default void failed(Throwable x)
55 {
56 }
57
58 /**
59 * <p>Creates a non-blocking callback from the given incomplete CompletableFuture.</p>
60 * <p>When the callback completes, either succeeding or failing, the
61 * CompletableFuture is also completed, respectively via
62 * {@link CompletableFuture#complete(Object)} or
63 * {@link CompletableFuture#completeExceptionally(Throwable)}.</p>
64 *
65 * @param completable the CompletableFuture to convert into a callback
66 * @return a callback that when completed, completes the given CompletableFuture
67 */
68 static Callback from(CompletableFuture<?> completable)
69 {
70 return from(completable, InvocationType.NON_BLOCKING);
71 }
72
73 /**
74 * <p>Creates a callback from the given incomplete CompletableFuture,
75 * with the given {@code blocking} characteristic.</p>
76 *
77 * @param completable the CompletableFuture to convert into a callback
78 * @param invocation whether the callback is blocking
79 * @return a callback that when completed, completes the given CompletableFuture
80 */
81 static Callback from(CompletableFuture<?> completable, InvocationType invocation)
82 {
83 if (completable instanceof Callback)
84 return (Callback)completable;
85
86 return new Callback()
87 {
88 @Override
89 public void succeeded()
90 {
91 completable.complete(null);
92 }
93
94 @Override
95 public void failed(Throwable x)
96 {
97 completable.completeExceptionally(x);
98 }
99
100 @Override
101 public InvocationType getInvocationType()
102 {
103 return invocation;
104 }
105 };
106 }
107
108 class Nested implements Callback
109 {
110 private final Callback callback;
111
112 public Nested(Callback callback)
113 {
114 this.callback = callback;
115 }
116
117 public Nested(Nested nested)
118 {
119 this.callback = nested.callback;
120 }
121
122 @Override
123 public void succeeded()
124 {
125 callback.succeeded();
126 }
127
128 @Override
129 public void failed(Throwable x)
130 {
131 callback.failed(x);
132 }
133
134 @Override
135 public InvocationType getInvocationType()
136 {
137 return callback.getInvocationType();
138 }
139 }
140 /**
141 * <p>A CompletableFuture that is also a Callback.</p>
142 */
143 class Completable extends CompletableFuture<Void> implements Callback
144 {
145 private final InvocationType invocation;
146
147 public Completable()
148 {
149 this(Invocable.InvocationType.NON_BLOCKING);
150 }
151
152 public Completable(InvocationType invocation)
153 {
154 this.invocation = invocation;
155 }
156
157 @Override
158 public void succeeded()
159 {
160 complete(null);
161 }
162
163 @Override
164 public void failed(Throwable x)
165 {
166 completeExceptionally(x);
167 }
168
169 @Override
170 public InvocationType getInvocationType()
171 {
172 return invocation;
173 }
174 }
175 }