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    *   http://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.UnstableApi;
22  
23  import java.util.concurrent.TimeUnit;
24  
25  @UnstableApi
26  public final class VoidChannelPromise extends AbstractFuture<Void> implements ChannelPromise {
27  
28      private final Channel channel;
29      // Will be null if we should not propagate exceptions through the pipeline on failure case.
30      private final ChannelFutureListener fireExceptionListener;
31  
32      /**
33       * Creates a new instance.
34       *
35       * @param channel the {@link Channel} associated with this future
36       */
37      public VoidChannelPromise(final Channel channel, boolean fireException) {
38          if (channel == null) {
39              throw new NullPointerException("channel");
40          }
41          this.channel = channel;
42          if (fireException) {
43              fireExceptionListener = new ChannelFutureListener() {
44                  @Override
45                  public void operationComplete(ChannelFuture future) throws Exception {
46                      Throwable cause = future.cause();
47                      if (cause != null) {
48                          fireException0(cause);
49                      }
50                  }
51              };
52          } else {
53              fireExceptionListener = null;
54          }
55      }
56  
57      @Override
58      public VoidChannelPromise addListener(GenericFutureListener<? extends Future<? super Void>> listener) {
59          fail();
60          return this;
61      }
62  
63      @Override
64      public VoidChannelPromise addListeners(GenericFutureListener<? extends Future<? super Void>>... listeners) {
65          fail();
66          return this;
67      }
68  
69      @Override
70      public VoidChannelPromise removeListener(GenericFutureListener<? extends Future<? super Void>> listener) {
71          // NOOP
72          return this;
73      }
74  
75      @Override
76      public VoidChannelPromise removeListeners(GenericFutureListener<? extends Future<? super Void>>... listeners) {
77          // NOOP
78          return this;
79      }
80  
81      @Override
82      public VoidChannelPromise await() throws InterruptedException {
83          if (Thread.interrupted()) {
84              throw new InterruptedException();
85          }
86          return this;
87      }
88  
89      @Override
90      public boolean await(long timeout, TimeUnit unit) {
91          fail();
92          return false;
93      }
94  
95      @Override
96      public boolean await(long timeoutMillis) {
97          fail();
98          return false;
99      }
100 
101     @Override
102     public VoidChannelPromise awaitUninterruptibly() {
103         fail();
104         return this;
105     }
106 
107     @Override
108     public boolean awaitUninterruptibly(long timeout, TimeUnit unit) {
109         fail();
110         return false;
111     }
112 
113     @Override
114     public boolean awaitUninterruptibly(long timeoutMillis) {
115         fail();
116         return false;
117     }
118 
119     @Override
120     public Channel channel() {
121         return channel;
122     }
123 
124     @Override
125     public boolean isDone() {
126         return false;
127     }
128 
129     @Override
130     public boolean isSuccess() {
131         return false;
132     }
133 
134     @Override
135     public boolean setUncancellable() {
136         return true;
137     }
138 
139     @Override
140     public boolean isCancellable() {
141         return false;
142     }
143 
144     @Override
145     public boolean isCancelled() {
146         return false;
147     }
148 
149     @Override
150     public Throwable cause() {
151         return null;
152     }
153 
154     @Override
155     public VoidChannelPromise sync() {
156         fail();
157         return this;
158     }
159 
160     @Override
161     public VoidChannelPromise syncUninterruptibly() {
162         fail();
163         return this;
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 }