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, 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 package org.apache.commons.crypto.stream.input;
19
20 import java.io.IOException;
21 import java.nio.ByteBuffer;
22 import java.nio.channels.ReadableByteChannel;
23
24 import org.apache.commons.crypto.stream.CryptoInputStream;
25
26 /**
27 * The ChannelInput class takes a {@link ReadableByteChannel} object and
28 * wraps it as {@link Input} object acceptable by
29 * {@link CryptoInputStream}.
30 */
31 public class ChannelInput implements Input {
32 private static final int SKIP_BUFFER_SIZE = 2048;
33
34 private ByteBuffer buf;
35 private final ReadableByteChannel channel;
36
37 /**
38 * Constructs the
39 * {@link org.apache.commons.crypto.stream.input.ChannelInput}.
40 *
41 * @param channel the ReadableByteChannel object.
42 */
43 public ChannelInput(final ReadableByteChannel channel) {
44 this.channel = channel;
45 }
46
47 /**
48 * Overrides the {@link Input#available()}. Returns an estimate of the
49 * number of bytes that can be read (or skipped over) from this input stream
50 * without blocking by the next invocation of a method for this input
51 * stream. The next invocation might be the same thread or another thread. A
52 * single read or skip of this many bytes will not block, but may read or
53 * skip fewer bytes.
54 *
55 * @return an estimate of the number of bytes that can be read (or skipped
56 * over) from this input stream without blocking or {@code 0} when
57 * it reaches the end of the input stream.
58 * @throws IOException if an I/O error occurs.
59 */
60 @Override
61 public int available() throws IOException {
62 return 0;
63 }
64
65 /**
66 * Overrides the
67 * {@link org.apache.commons.crypto.stream.input.Input#seek(long)}. Closes
68 * this input and releases any system resources associated with the under
69 * layer input.
70 *
71 * @throws IOException if an I/O error occurs.
72 */
73 @Override
74 public void close() throws IOException {
75 channel.close();
76 }
77
78 /**
79 * Gets the skip buffer.
80 *
81 * @return the buffer.
82 */
83 private ByteBuffer getSkipBuf() {
84 if (buf == null) {
85 buf = ByteBuffer.allocate(SKIP_BUFFER_SIZE);
86 }
87 return buf;
88 }
89
90 /**
91 * Overrides the
92 * {@link org.apache.commons.crypto.stream.input.Input#read(ByteBuffer)}.
93 * Reads a sequence of bytes from input into the given buffer.
94 *
95 * @param dst The buffer into which bytes are to be transferred.
96 * @return the total number of bytes read into the buffer, or
97 * {@code -1} if there is no more data because the end of the
98 * stream has been reached.
99 * @throws IOException if an I/O error occurs.
100 */
101 @Override
102 public int read(final ByteBuffer dst) throws IOException {
103 return channel.read(dst);
104 }
105
106 /**
107 * Overrides the
108 * {@link org.apache.commons.crypto.stream.input.Input#read(long, byte[], int, int)}
109 * . Reads up to {@code len} bytes of data from the input stream into
110 * an array of bytes. An attempt is made to read as many as {@code len}
111 * bytes, but a smaller number may be read. The number of bytes actually
112 * read is returned as an integer.
113 *
114 * @param position the given position within a stream.
115 * @param buffer the buffer into which the data is read.
116 * @param offset the start offset in array buffer.
117 * @param length the maximum number of bytes to read.
118 * @return the total number of bytes read into the buffer, or
119 * {@code -1} if there is no more data because the end of the
120 * stream has been reached.
121 * @throws IOException if an I/O error occurs.
122 */
123 @Override
124 public int read(final long position, final byte[] buffer, final int offset, final int length)
125 throws IOException {
126 throw new UnsupportedOperationException(
127 "Positioned read is not supported by this implementation");
128 }
129
130 /**
131 * Overrides the
132 * {@link org.apache.commons.crypto.stream.input.Input#seek(long)}. Seeks to
133 * the given offset from the start of the stream. The next read() will be
134 * from that location.
135 *
136 * @param position the offset from the start of the stream.
137 * @throws IOException if an I/O error occurs.
138 */
139 @Override
140 public void seek(final long position) throws IOException {
141 throw new UnsupportedOperationException(
142 "Seek is not supported by this implementation");
143 }
144
145 /**
146 * Overrides the
147 * {@link org.apache.commons.crypto.stream.input.Input#skip(long)}. Skips
148 * over and discards {@code n} bytes of data from this input stream.
149 *
150 * @param n the number of bytes to be skipped.
151 * @return the actual number of bytes skipped.
152 * @throws IOException if an I/O error occurs.
153 */
154 @Override
155 public long skip(final long n) throws IOException {
156 long remaining = n;
157 int nr;
158
159 if (n <= 0) {
160 return 0;
161 }
162
163 final int size = (int) Math.min(SKIP_BUFFER_SIZE, remaining);
164 final ByteBuffer skipBuffer = getSkipBuf();
165 while (remaining > 0) {
166 skipBuffer.clear();
167 skipBuffer.limit((int) Math.min(size, remaining));
168 nr = read(skipBuffer);
169 if (nr < 0) {
170 break;
171 }
172 remaining -= nr;
173 }
174
175 return n - remaining;
176 }
177 }