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.ReadListenerSettable;
33 import org.xnio.channels.StreamSinkChannel;
34 import org.xnio.channels.StreamSourceChannel;
35
36 /**
37  * A stream source channel which wraps a stream source conduit.
38  *
39  * @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
40  */

41 public final class ConduitStreamSourceChannel implements StreamSourceChannel, ReadListenerSettable<ConduitStreamSourceChannel>, CloseListenerSettable<ConduitStreamSourceChannel>, Cloneable {
42     private final Configurable configurable;
43
44     private StreamSourceConduit conduit;
45     private ChannelListener<? super ConduitStreamSourceChannel> readListener;
46     private ChannelListener<? super ConduitStreamSourceChannel> 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 ConduitStreamSourceChannel(final Configurable configurable, final StreamSourceConduit conduit) {
55         this.configurable = configurable;
56         this.conduit = conduit;
57         conduit.setReadReadyHandler(new ReadReadyHandler.ChannelListenerHandler<ConduitStreamSourceChannel>(this));
58     }
59
60     /**
61      * Get the underlying conduit for this channel.
62      *
63      * @return the underlying conduit for this channel
64      */

65     public StreamSourceConduit 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 StreamSourceConduit conduit) {
75         this.conduit = conduit;
76     }
77
78     public boolean isOpen() {
79         return ! conduit.isReadShutdown();
80     }
81
82     public long transferTo(final long position, final long count, final FileChannel target) throws IOException {
83         return conduit.transferTo(position, count, target);
84     }
85
86     public long transferTo(final long count, final ByteBuffer throughBuffer, final StreamSinkChannel target) throws IOException {
87         return conduit.transferTo(count, throughBuffer, target);
88     }
89
90     public void setReadListener(final ChannelListener<? super ConduitStreamSourceChannel> readListener) {
91         this.readListener = readListener;
92     }
93
94     public ChannelListener<? super ConduitStreamSourceChannel> getReadListener() {
95         return readListener;
96     }
97
98     public void setCloseListener(final ChannelListener<? super ConduitStreamSourceChannel> closeListener) {
99         this.closeListener = closeListener;
100     }
101
102     public ChannelListener<? super ConduitStreamSourceChannel> getCloseListener() {
103         return closeListener;
104     }
105
106     public ChannelListener.Setter<ConduitStreamSourceChannel> getReadSetter() {
107         return new ReadListenerSettable.Setter<ConduitStreamSourceChannel>(this);
108     }
109
110     public ChannelListener.Setter<ConduitStreamSourceChannel> getCloseSetter() {
111         return new CloseListenerSettable.Setter<ConduitStreamSourceChannel>(this);
112     }
113
114     public XnioWorker getWorker() {
115         return conduit.getWorker();
116     }
117
118     public long read(final ByteBuffer[] dsts, final int offset, final int length) throws IOException {
119         return conduit.read(dsts, offset, length);
120     }
121
122     public long read(final ByteBuffer[] dsts) throws IOException {
123         return conduit.read(dsts, 0, dsts.length);
124     }
125
126     public int read(final ByteBuffer dst) throws IOException {
127         return conduit.read(dst);
128     }
129
130     public void suspendReads() {
131         conduit.suspendReads();
132     }
133
134     public void resumeReads() {
135         conduit.resumeReads();
136     }
137
138     public boolean isReadResumed() {
139         return conduit.isReadResumed();
140     }
141
142     public void wakeupReads() {
143         conduit.wakeupReads();
144     }
145
146     public void shutdownReads() throws IOException {
147         conduit.terminateReads();
148     }
149
150     public void awaitReadable() throws IOException {
151         conduit.awaitReadable();
152     }
153
154     public void awaitReadable(final long time, final TimeUnit timeUnit) throws IOException {
155         conduit.awaitReadable(time, timeUnit);
156     }
157
158     @Deprecated
159     public XnioExecutor getReadThread() {
160         return conduit.getReadThread();
161     }
162
163     public XnioIoThread getIoThread() {
164         return conduit.getReadThread();
165     }
166
167     public void close() throws IOException {
168         conduit.terminateReads();
169     }
170
171     public boolean supportsOption(final Option<?> option) {
172         return configurable.supportsOption(option);
173     }
174
175     public <T> T getOption(final Option<T> option) throws IOException {
176         return configurable.getOption(option);
177     }
178
179     public <T> T setOption(final Option<T> option, final T value) throws IllegalArgumentException, IOException {
180         return configurable.setOption(option, value);
181     }
182
183     /**
184      * Duplicate this channel.  Changing the delegate conduit in one channel will not affect the other.
185      *
186      * @return the cloned channel
187      */

188     public ConduitStreamSourceChannel clone() {
189         try {
190             return (ConduitStreamSourceChannel) super.clone();
191         } catch (CloneNotSupportedException e) {
192             throw new IllegalStateException(e);
193         }
194     }
195 }
196