001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 *
019 */
020package org.apache.mina.core.write;
021
022import java.net.SocketAddress;
023import java.util.concurrent.TimeUnit;
024
025import org.apache.mina.core.future.IoFutureListener;
026import org.apache.mina.core.future.WriteFuture;
027import org.apache.mina.core.session.IoSession;
028
029/**
030 * The default implementation of {@link WriteRequest}.
031 *
032 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
033 */
034public class DefaultWriteRequest implements WriteRequest {
035    /** An empty message */
036    public static final byte[] EMPTY_MESSAGE = new byte[] {};
037
038    /** An empty FUTURE */
039    private static final WriteFuture UNUSED_FUTURE = new WriteFuture() {
040        public boolean isWritten() {
041            return false;
042        }
043
044        public void setWritten() {
045            // Do nothing
046        }
047
048        public IoSession getSession() {
049            return null;
050        }
051
052        public void join() {
053            // Do nothing
054        }
055
056        public boolean join(long timeoutInMillis) {
057            return true;
058        }
059
060        public boolean isDone() {
061            return true;
062        }
063
064        public WriteFuture addListener(IoFutureListener<?> listener) {
065            throw new IllegalStateException("You can't add a listener to a dummy future.");
066        }
067
068        public WriteFuture removeListener(IoFutureListener<?> listener) {
069            throw new IllegalStateException("You can't add a listener to a dummy future.");
070        }
071
072        public WriteFuture await() throws InterruptedException {
073            return this;
074        }
075
076        public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
077            return true;
078        }
079
080        public boolean await(long timeoutMillis) throws InterruptedException {
081            return true;
082        }
083
084        public WriteFuture awaitUninterruptibly() {
085            return this;
086        }
087
088        public boolean awaitUninterruptibly(long timeout, TimeUnit unit) {
089            return true;
090        }
091
092        public boolean awaitUninterruptibly(long timeoutMillis) {
093            return true;
094        }
095
096        public Throwable getException() {
097            return null;
098        }
099
100        public void setException(Throwable cause) {
101            // Do nothing
102        }
103    };
104
105    private final Object message;
106
107    private final WriteFuture future;
108
109    private final SocketAddress destination;
110
111    /**
112     * Creates a new instance without {@link WriteFuture}.  You'll get
113     * an instance of {@link WriteFuture} even if you called this constructor
114     * because {@link #getFuture()} will return a bogus future.
115     * 
116     * @param message The message that will be written
117     */
118    public DefaultWriteRequest(Object message) {
119        this(message, null, null);
120    }
121
122    /**
123     * Creates a new instance with {@link WriteFuture}.
124     * 
125     * @param message The message that will be written
126     * @param future The associated {@link WriteFuture}
127     */
128    public DefaultWriteRequest(Object message, WriteFuture future) {
129        this(message, future, null);
130    }
131
132    /**
133     * Creates a new instance.
134     *
135     * @param message a message to write
136     * @param future a future that needs to be notified when an operation is finished
137     * @param destination the destination of the message.  This property will be
138     *                    ignored unless the transport supports it.
139     */
140    public DefaultWriteRequest(Object message, WriteFuture future, SocketAddress destination) {
141        if (message == null) {
142            throw new IllegalArgumentException("message");
143        }
144
145        if (future == null) {
146            future = UNUSED_FUTURE;
147        }
148
149        this.message = message;
150        this.future = future;
151        this.destination = destination;
152    }
153
154    public WriteFuture getFuture() {
155        return future;
156    }
157
158    public Object getMessage() {
159        return message;
160    }
161
162    public WriteRequest getOriginalRequest() {
163        return this;
164    }
165
166    public SocketAddress getDestination() {
167        return destination;
168    }
169
170    @Override
171    public String toString() {
172        StringBuilder sb = new StringBuilder();
173
174        sb.append("WriteRequest: ");
175
176        // Special case for the CLOSE_REQUEST writeRequest : it just
177        // carries a native Object instance
178        if (message.getClass().getName().equals(Object.class.getName())) {
179            sb.append("CLOSE_REQUEST");
180        } else {
181            if (getDestination() == null) {
182                sb.append(message);
183            } else {
184                sb.append(message);
185                sb.append(" => ");
186                sb.append(getDestination());
187            }
188        }
189
190        return sb.toString();
191    }
192
193    public boolean isEncoded() {
194        return false;
195    }
196}