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 }