View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.channel;
17  
18  import io.netty.util.concurrent.AbstractFuture;
19  import io.netty.util.concurrent.Future;
20  import io.netty.util.concurrent.GenericFutureListener;
21  import io.netty.util.internal.ObjectUtil;
22  import io.netty.util.internal.UnstableApi;
23  
24  import java.util.concurrent.TimeUnit;
25  
26  @UnstableApi
27  public final class VoidChannelPromise extends AbstractFuture<Void> implements ChannelPromise {
28  
29      private final Channel channel;
30      // Will be null if we should not propagate exceptions through the pipeline on failure case.
31      private final ChannelFutureListener fireExceptionListener;
32  
33      /**
34       * Creates a new instance.
35       *
36       * @param channel the {@link Channel} associated with this future
37       */
38      public VoidChannelPromise(final Channel channel, boolean fireException) {
39          ObjectUtil.checkNotNull(channel, "channel");
40          this.channel = channel;
41          if (fireException) {
42              fireExceptionListener = new ChannelFutureListener() {
43                  @Override
44                  public void operationComplete(ChannelFuture future) throws Exception {
45                      Throwable cause = future.cause();
46                      if (cause != null) {
47                          fireException0(cause);
48                      }
49                  }
50              };
51          } else {
52              fireExceptionListener = null;
53          }
54      }
55  
56      @Override
57      public VoidChannelPromise addListener(GenericFutureListener<? extends Future<? super Void>> listener) {
58          fail();
59          return this;
60      }
61  
62      @Override
63      public VoidChannelPromise addListeners(GenericFutureListener<? extends Future<? super Void>>... listeners) {
64          fail();
65          return this;
66      }
67  
68      @Override
69      public VoidChannelPromise removeListener(GenericFutureListener<? extends Future<? super Void>> listener) {
70          // NOOP
71          return this;
72      }
73  
74      @Override
75      public VoidChannelPromise removeListeners(GenericFutureListener<? extends Future<? super Void>>... listeners) {
76          // NOOP
77          return this;
78      }
79  
80      @Override
81      public VoidChannelPromise await() throws InterruptedException {
82          if (Thread.interrupted()) {
83              throw new InterruptedException();
84          }
85          return this;
86      }
87  
88      @Override
89      public boolean await(long timeout, TimeUnit unit) {
90          fail();
91          return false;
92      }
93  
94      @Override
95      public boolean await(long timeoutMillis) {
96          fail();
97          return false;
98      }
99  
100     @Override
101     public VoidChannelPromise awaitUninterruptibly() {
102         fail();
103         return this;
104     }
105 
106     @Override
107     public boolean awaitUninterruptibly(long timeout, TimeUnit unit) {
108         fail();
109         return false;
110     }
111 
112     @Override
113     public boolean awaitUninterruptibly(long timeoutMillis) {
114         fail();
115         return false;
116     }
117 
118     @Override
119     public Channel channel() {
120         return channel;
121     }
122 
123     @Override
124     public boolean isDone() {
125         return false;
126     }
127 
128     @Override
129     public boolean isSuccess() {
130         return false;
131     }
132 
133     @Override
134     public boolean setUncancellable() {
135         return true;
136     }
137 
138     @Override
139     public boolean isCancellable() {
140         return false;
141     }
142 
143     @Override
144     public boolean isCancelled() {
145         return false;
146     }
147 
148     @Override
149     public Throwable cause() {
150         return null;
151     }
152 
153     @Override
154     public VoidChannelPromise sync() {
155         fail();
156         return this;
157     }
158 
159     @Override
160     public VoidChannelPromise syncUninterruptibly() {
161         fail();
162         return this;
163     }
164 
165     @Override
166     public VoidChannelPromise setFailure(Throwable cause) {
167         fireException0(cause);
168         return this;
169     }
170 
171     @Override
172     public VoidChannelPromise setSuccess() {
173         return this;
174     }
175 
176     @Override
177     public boolean tryFailure(Throwable cause) {
178         fireException0(cause);
179         return false;
180     }
181 
182     /**
183      * {@inheritDoc}
184      *
185      * @param mayInterruptIfRunning this value has no effect in this implementation.
186      */
187     @Override
188     public boolean cancel(boolean mayInterruptIfRunning) {
189         return false;
190     }
191 
192     @Override
193     public boolean trySuccess() {
194         return false;
195     }
196 
197     private static void fail() {
198         throw new IllegalStateException("void future");
199     }
200 
201     @Override
202     public VoidChannelPromise setSuccess(Void result) {
203         return this;
204     }
205 
206     @Override
207     public boolean trySuccess(Void result) {
208         return false;
209     }
210 
211     @Override
212     public Void getNow() {
213         return null;
214     }
215 
216     @Override
217     public ChannelPromise unvoid() {
218         ChannelPromise promise = new DefaultChannelPromise(channel);
219         if (fireExceptionListener != null) {
220             promise.addListener(fireExceptionListener);
221         }
222         return promise;
223     }
224 
225     @Override
226     public boolean isVoid() {
227         return true;
228     }
229 
230     private void fireException0(Throwable cause) {
231         // Only fire the exception if the channel is open and registered
232         // if not the pipeline is not setup and so it would hit the tail
233         // of the pipeline.
234         // See https://github.com/netty/netty/issues/1517
235         if (fireExceptionListener != null && channel.isRegistered()) {
236             channel.pipeline().fireExceptionCaught(cause);
237         }
238     }
239 }