1 /*
2  * JBoss, Home of Professional Open Source
3  *
4  * Copyright 2013 Red Hat, Inc. and/or its affiliates.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * 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, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 package org.xnio.conduits;
20
21 import java.io.IOException;
22 import java.nio.ByteBuffer;
23 import java.nio.channels.FileChannel;
24 import java.util.concurrent.TimeUnit;
25 import org.xnio.ChannelListener;
26 import org.xnio.Option;
27 import org.xnio.XnioExecutor;
28 import org.xnio.XnioIoThread;
29 import org.xnio.XnioWorker;
30 import org.xnio.channels.CloseListenerSettable;
31 import org.xnio.channels.Configurable;
32 import org.xnio.channels.StreamSinkChannel;
33 import org.xnio.channels.StreamSourceChannel;
34 import org.xnio.channels.WriteListenerSettable;
35
36 /**
37  * A stream sink channel which wraps a stream sink conduit.
38  *
39  * @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
40  */

41 public final class ConduitStreamSinkChannel implements StreamSinkChannel, WriteListenerSettable<ConduitStreamSinkChannel>, CloseListenerSettable<ConduitStreamSinkChannel>, Cloneable {
42     private final Configurable configurable;
43
44     private StreamSinkConduit conduit;
45     private ChannelListener<? super ConduitStreamSinkChannel> writeListener;
46     private ChannelListener<? super ConduitStreamSinkChannel> closeListener;
47
48     /**
49      * Construct a new instance.
50      *
51      * @param configurable the configurable to delegate configuration requests to
52      * @param conduit the initial conduit to use for data transport
53      */

54     public ConduitStreamSinkChannel(final Configurable configurable, final StreamSinkConduit conduit) {
55         this.configurable = configurable;
56         this.conduit = conduit;
57         conduit.setWriteReadyHandler(new WriteReadyHandler.ChannelListenerHandler<ConduitStreamSinkChannel>(this));
58     }
59
60     /**
61      * Get the underlying conduit for this channel.
62      *
63      * @return the underlying conduit for this channel
64      */

65     public StreamSinkConduit getConduit() {
66         return conduit;
67     }
68
69     /**
70      * Set the underlying conduit for this channel.
71      *
72      * @param conduit the underlying conduit for this channel
73      */

74     public void setConduit(final StreamSinkConduit conduit) {
75         this.conduit = conduit;
76     }
77
78     public ChannelListener<? super ConduitStreamSinkChannel> getWriteListener() {
79         return writeListener;
80     }
81
82     public void setWriteListener(final ChannelListener<? super ConduitStreamSinkChannel> writeListener) {
83         this.writeListener = writeListener;
84     }
85
86     public ChannelListener<? super ConduitStreamSinkChannel> getCloseListener() {
87         return closeListener;
88     }
89
90     public void setCloseListener(final ChannelListener<? super ConduitStreamSinkChannel> closeListener) {
91         this.closeListener = closeListener;
92     }
93
94     public ChannelListener.Setter<ConduitStreamSinkChannel> getWriteSetter() {
95         return new WriteListenerSettable.Setter<ConduitStreamSinkChannel>(this);
96     }
97
98     public ChannelListener.Setter<ConduitStreamSinkChannel> getCloseSetter() {
99         return new CloseListenerSettable.Setter<ConduitStreamSinkChannel>(this);
100     }
101
102     @Override
103     public int writeFinal(ByteBuffer src) throws IOException {
104         return conduit.writeFinal(src);
105     }
106
107     @Override
108     public long writeFinal(ByteBuffer[] srcs, int offset, int length) throws IOException {
109         return conduit.writeFinal(srcs, offset, length);
110     }
111
112     @Override
113     public long writeFinal(ByteBuffer[] srcs) throws IOException {
114         return conduit.writeFinal(srcs, 0, srcs.length);
115     }
116
117     public void suspendWrites() {
118         conduit.suspendWrites();
119     }
120
121     public void resumeWrites() {
122         conduit.resumeWrites();
123     }
124
125     public void wakeupWrites() {
126         conduit.wakeupWrites();
127     }
128
129     public boolean isWriteResumed() {
130         return conduit.isWriteResumed();
131     }
132
133     public void awaitWritable() throws IOException {
134         conduit.awaitWritable();
135     }
136
137     public void awaitWritable(final long time, final TimeUnit timeUnit) throws IOException {
138         conduit.awaitWritable(time, timeUnit);
139     }
140
141     public long transferFrom(final FileChannel src, final long position, final long count) throws IOException {
142         return conduit.transferFrom(src, position, count);
143     }
144
145     public long transferFrom(final StreamSourceChannel source, final long count, final ByteBuffer throughBuffer) throws IOException {
146         return conduit.transferFrom(source, count, throughBuffer);
147     }
148
149     public int write(final ByteBuffer dst) throws IOException {
150         return conduit.write(dst);
151     }
152
153     public long write(final ByteBuffer[] srcs) throws IOException {
154         return conduit.write(srcs, 0, srcs.length);
155     }
156
157     public long write(final ByteBuffer[] dsts, final int offs, final int len) throws IOException {
158         return conduit.write(dsts, offs, len);
159     }
160
161     public boolean flush() throws IOException {
162         return conduit.flush();
163     }
164
165     public boolean supportsOption(final Option<?> option) {
166         return configurable.supportsOption(option);
167     }
168
169     public <T> T getOption(final Option<T> option) throws IOException {
170         return configurable.getOption(option);
171     }
172
173     public <T> T setOption(final Option<T> option, final T value) throws IllegalArgumentException, IOException {
174         return configurable.setOption(option, value);
175     }
176
177     public void shutdownWrites() throws IOException {
178         conduit.terminateWrites();
179     }
180
181     public boolean isOpen() {
182         return ! conduit.isWriteShutdown();
183     }
184
185     public void close() throws IOException {
186         conduit.truncateWrites();
187     }
188
189     @Deprecated
190     public XnioExecutor getWriteThread() {
191         return conduit.getWriteThread();
192     }
193
194     public XnioIoThread getIoThread() {
195         return conduit.getWriteThread();
196     }
197
198     public XnioWorker getWorker() {
199         return conduit.getWorker();
200     }
201
202     /**
203      * Duplicate this channel.  Changing the delegate conduit in one channel will not affect the other.
204      *
205      * @return the cloned channel
206      */

207     public ConduitStreamSinkChannel clone() {
208         try {
209             return (ConduitStreamSinkChannel) super.clone();
210         } catch (CloneNotSupportedException e) {
211             throw new IllegalStateException(e);
212         }
213     }
214 }
215