View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.core.write;
21  
22  import java.net.SocketAddress;
23  import java.util.concurrent.TimeUnit;
24  
25  import org.apache.mina.core.buffer.IoBuffer;
26  import org.apache.mina.core.future.IoFutureListener;
27  import org.apache.mina.core.future.WriteFuture;
28  import org.apache.mina.core.session.IoSession;
29  
30  /**
31   * The default implementation of {@link WriteRequest}.
32   *
33   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
34   */
35  public class DefaultWriteRequest implements WriteRequest {
36      /** An empty message */
37      public static final byte[] EMPTY_MESSAGE = new byte[] {};
38  
39      /** An empty FUTURE */
40      private static final WriteFuturere.html#WriteFuture">WriteFuture UNUSED_FUTURE = new WriteFuture() {
41          /**
42           * {@inheritDoc}
43           */
44          @Override
45          public boolean isWritten() {
46              return false;
47          }
48  
49          /**
50           * {@inheritDoc}
51           */
52          @Override
53          public void setWritten() {
54              // Do nothing
55          }
56  
57          /**
58           * {@inheritDoc}
59           */
60          @Override
61          public IoSession getSession() {
62              return null;
63          }
64  
65          /**
66           * {@inheritDoc}
67           */
68          @Override
69          public void join() {
70              // Do nothing
71          }
72  
73          /**
74           * {@inheritDoc}
75           */
76          @Override
77          public boolean join(long timeoutInMillis) {
78              return true;
79          }
80  
81          /**
82           * {@inheritDoc}
83           */
84          @Override
85          public boolean isDone() {
86              return true;
87          }
88  
89          /**
90           * {@inheritDoc}
91           */
92          @Override
93          public WriteFuture addListener(IoFutureListener<?> listener) {
94              throw new IllegalStateException("You can't add a listener to a dummy future.");
95          }
96  
97          /**
98           * {@inheritDoc}
99           */
100         @Override
101         public WriteFuture removeListener(IoFutureListener<?> listener) {
102             throw new IllegalStateException("You can't add a listener to a dummy future.");
103         }
104 
105         /**
106          * {@inheritDoc}
107          */
108         @Override
109         public WriteFuture await() throws InterruptedException {
110             return this;
111         }
112 
113         /**
114          * {@inheritDoc}
115          */
116         @Override
117         public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
118             return true;
119         }
120 
121         /**
122          * {@inheritDoc}
123          */
124         @Override
125         public boolean await(long timeoutMillis) throws InterruptedException {
126             return true;
127         }
128 
129         /**
130          * {@inheritDoc}
131          */
132         @Override
133         public WriteFuture awaitUninterruptibly() {
134             return this;
135         }
136 
137         /**
138          * {@inheritDoc}
139          */
140         @Override
141         public boolean awaitUninterruptibly(long timeout, TimeUnit unit) {
142             return true;
143         }
144 
145         /**
146          * {@inheritDoc}
147          */
148         @Override
149         public boolean awaitUninterruptibly(long timeoutMillis) {
150             return true;
151         }
152 
153         /**
154          * {@inheritDoc}
155          */
156         @Override
157         public Throwable getException() {
158             return null;
159         }
160 
161         /**
162          * {@inheritDoc}
163          */
164         @Override
165         public void setException(Throwable cause) {
166             // Do nothing
167         }
168     };
169 
170     /** 
171      * The original message as it was written by the IoHandler. It will be sent back
172      * in the messageSent event 
173      */ 
174     private final Object originalMessage;
175 
176     /** The message that will ultimately be written to the remote peer */ 
177     private Object message;
178 
179     /** The associated Future */
180     private final WriteFuture future;
181 
182     /** The peer destination (useless ???) */
183     private final SocketAddress destination;
184 
185     /**
186      * Creates a new instance without {@link WriteFuture}.  You'll get
187      * an instance of {@link WriteFuture} even if you called this constructor
188      * because {@link #getFuture()} will return a bogus future.
189      * 
190      * @param message The message that will be written
191      */
192     public DefaultWriteRequest(Object message) {
193         this(message, null, null);
194     }
195 
196     /**
197      * Creates a new instance with {@link WriteFuture}.
198      * 
199      * @param message The message that will be written
200      * @param future The associated {@link WriteFuture}
201      */
202     public DefaultWriteRequest(Object message, WriteFuture future) {
203         this(message, future, null);
204     }
205 
206     /**
207      * Creates a new instance.
208      *
209      * @param message a message to write
210      * @param future a future that needs to be notified when an operation is finished
211      * @param destination the destination of the message.  This property will be
212      *                    ignored unless the transport supports it.
213      */
214     public DefaultWriteRequest(Object message, WriteFuture future, SocketAddress destination) {
215         if (message == null) {
216             throw new IllegalArgumentException("message");
217         }
218 
219         if (future == null) {
220             future = UNUSED_FUTURE;
221         }
222 
223         this.message = message;
224         this.originalMessage = message;
225         
226         if (message instanceof IoBuffer) {
227             // duplicate it, so that any modification made on it
228             // won't change the original message
229             this.message = ((IoBuffer)message).duplicate();
230         }
231 
232         
233         this.future = future;
234         this.destination = destination;
235     }
236 
237     /**
238      * {@inheritDoc}
239      */
240     @Override
241     public WriteFuture getFuture() {
242         return future;
243     }
244 
245     /**
246      * {@inheritDoc}
247      */
248     @Override
249     public Object getMessage() {
250         return message;
251     }
252 
253     /**
254      * {@inheritDoc}
255      */
256     @Override
257     public void setMessage(Object modifiedMessage) {
258         message = modifiedMessage;
259     }
260 
261     /**
262      * {@inheritDoc}
263      */
264     @Override
265     public Object getOriginalMessage() {
266         if (originalMessage != null) {
267             return originalMessage;
268         } else {
269             return message;
270         }
271     }
272 
273     /**
274      * {@inheritDoc}
275      */
276     @Override
277     public WriteRequest getOriginalRequest() {
278         return this;
279     }
280 
281     /**
282      * {@inheritDoc}
283      */
284     @Override
285     public SocketAddress getDestination() {
286         return destination;
287     }
288 
289     @Override
290     public String toString() {
291         StringBuilder sb = new StringBuilder();
292 
293         sb.append("WriteRequest: ");
294 
295         // Special case for the CLOSE_REQUEST writeRequest : it just
296         // carries a native Object instance
297         if (message.getClass().getName().equals(Object.class.getName())) {
298             sb.append("CLOSE_REQUEST");
299         } else {
300             sb.append(originalMessage);
301 
302             if (getDestination() != null) {
303                 sb.append(" => ");
304                 sb.append(getDestination());
305             }
306         }
307 
308         return sb.toString();
309     }
310 
311     /**
312      * {@inheritDoc}
313      */
314     @Override
315     public boolean isEncoded() {
316         return false;
317     }
318 }