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, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.mavibot.btree.serializer; 021 022 023import java.io.EOFException; 024import java.io.IOException; 025import java.nio.ByteBuffer; 026import java.nio.channels.FileChannel; 027 028 029/** 030 * A class used to hide the buffer read from the underlying file. 031 * 032 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 033 */ 034public class BufferHandler 035{ 036 /** The channel we read bytes from */ 037 private FileChannel channel; 038 039 /** The buffer containing the bytes we read from the channel */ 040 private ByteBuffer buffer; 041 042 043 /** 044 * Create a new BufferHandler 045 * @param buffer The buffer used to transfer data 046 */ 047 public BufferHandler( byte[] buffer ) 048 { 049 this.buffer = ByteBuffer.allocate( buffer.length ); 050 this.buffer.put( buffer ); 051 this.buffer.flip(); 052 } 053 054 055 /** 056 * Create a new BufferHandler 057 * @param channel The channel to read 058 * @param buffer The buffer used to transfer data 059 */ 060 public BufferHandler( FileChannel channel, ByteBuffer buffer ) 061 { 062 this.channel = channel; 063 this.buffer = buffer; 064 065 try 066 { 067 // Initial read 068 channel.read( buffer ); 069 buffer.flip(); 070 } 071 catch ( IOException ioe ) 072 { 073 074 } 075 } 076 077 078 public byte[] getBuffer() 079 { 080 byte[] bytes = new byte[buffer.capacity()]; 081 082 buffer.get( bytes ); 083 084 return bytes; 085 } 086 087 088 /** 089 * Read a buffer containing the given number of bytes 090 * @param len The number of bytes to read 091 * @return 092 */ 093 public byte[] read( int len ) throws IOException 094 { 095 byte[] result = new byte[len]; 096 097 if ( len <= buffer.remaining() ) 098 { 099 buffer.get( result ); 100 101 return result; 102 } 103 104 int requested = len; 105 int position = 0; 106 107 while ( requested != 0 ) 108 { 109 int nbRemainingRead = buffer.limit() - buffer.position(); 110 111 if ( nbRemainingRead > requested ) 112 { 113 buffer.get( result, position, requested ); 114 break; 115 } 116 else 117 { 118 System.arraycopy( buffer.array(), buffer.position(), result, position, nbRemainingRead ); 119 position += nbRemainingRead; 120 } 121 122 buffer.clear(); 123 124 if ( channel != null ) 125 { 126 int nbReads = channel.read( buffer ); 127 buffer.flip(); 128 129 if ( nbReads <= 0 ) 130 { 131 throw new EOFException(); 132 } 133 } 134 else 135 { 136 throw new IOException( "Not enough bytes in the buffer" ); 137 } 138 139 requested -= nbRemainingRead; 140 } 141 142 return result; 143 } 144}