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, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.commons.crypto.stream.input; 019 020import java.io.IOException; 021import java.nio.ByteBuffer; 022import java.nio.channels.ReadableByteChannel; 023 024import org.apache.commons.crypto.stream.CryptoInputStream; 025 026/** 027 * The ChannelInput class takes a {@link ReadableByteChannel} object and 028 * wraps it as {@link Input} object acceptable by 029 * {@link CryptoInputStream}. 030 */ 031public class ChannelInput implements Input { 032 private static final int SKIP_BUFFER_SIZE = 2048; 033 034 private ByteBuffer buf; 035 private final ReadableByteChannel channel; 036 037 /** 038 * Constructs the 039 * {@link org.apache.commons.crypto.stream.input.ChannelInput}. 040 * 041 * @param channel the ReadableByteChannel object. 042 */ 043 public ChannelInput(final ReadableByteChannel channel) { 044 this.channel = channel; 045 } 046 047 /** 048 * Overrides the {@link Input#available()}. Returns an estimate of the 049 * number of bytes that can be read (or skipped over) from this input stream 050 * without blocking by the next invocation of a method for this input 051 * stream. The next invocation might be the same thread or another thread. A 052 * single read or skip of this many bytes will not block, but may read or 053 * skip fewer bytes. 054 * 055 * @return an estimate of the number of bytes that can be read (or skipped 056 * over) from this input stream without blocking or {@code 0} when 057 * it reaches the end of the input stream. 058 * @throws IOException if an I/O error occurs. 059 */ 060 @Override 061 public int available() throws IOException { 062 return 0; 063 } 064 065 /** 066 * Overrides the 067 * {@link org.apache.commons.crypto.stream.input.Input#seek(long)}. Closes 068 * this input and releases any system resources associated with the under 069 * layer input. 070 * 071 * @throws IOException if an I/O error occurs. 072 */ 073 @Override 074 public void close() throws IOException { 075 channel.close(); 076 } 077 078 /** 079 * Gets the skip buffer. 080 * 081 * @return the buffer. 082 */ 083 private ByteBuffer getSkipBuf() { 084 if (buf == null) { 085 buf = ByteBuffer.allocate(SKIP_BUFFER_SIZE); 086 } 087 return buf; 088 } 089 090 /** 091 * Overrides the 092 * {@link org.apache.commons.crypto.stream.input.Input#read(ByteBuffer)}. 093 * Reads a sequence of bytes from input into the given buffer. 094 * 095 * @param dst The buffer into which bytes are to be transferred. 096 * @return the total number of bytes read into the buffer, or 097 * {@code -1} if there is no more data because the end of the 098 * stream has been reached. 099 * @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}