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,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 */
20 package org.apache.directory.mavibot.btree.serializer;
21
22
23 import java.io.EOFException;
24 import java.io.IOException;
25 import java.nio.ByteBuffer;
26 import java.nio.channels.FileChannel;
27
28
29 /**
30 * A class used to hide the buffer read from the underlying file.
31 *
32 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
33 */
34 public class BufferHandler
35 {
36 /** The channel we read bytes from */
37 private FileChannel channel;
38
39 /** The buffer containing the bytes we read from the channel */
40 private ByteBuffer buffer;
41
42
43 /**
44 * Create a new BufferHandler
45 * @param buffer The buffer used to transfer data
46 */
47 public BufferHandler( byte[] buffer )
48 {
49 this.buffer = ByteBuffer.allocate( buffer.length );
50 this.buffer.put( buffer );
51 this.buffer.flip();
52 }
53
54
55 /**
56 * Create a new BufferHandler
57 * @param channel The channel to read
58 * @param buffer The buffer used to transfer data
59 */
60 public BufferHandler( FileChannel channel, ByteBuffer buffer )
61 {
62 this.channel = channel;
63 this.buffer = buffer;
64
65 try
66 {
67 // Initial read
68 channel.read( buffer );
69 buffer.flip();
70 }
71 catch ( IOException ioe )
72 {
73
74 }
75 }
76
77
78 public byte[] getBuffer()
79 {
80 byte[] bytes = new byte[buffer.capacity()];
81
82 buffer.get( bytes );
83
84 return bytes;
85 }
86
87
88 /**
89 * Read a buffer containing the given number of bytes
90 * @param len The number of bytes to read
91 * @return
92 */
93 public byte[] read( int len ) throws IOException
94 {
95 byte[] result = new byte[len];
96
97 if ( len <= buffer.remaining() )
98 {
99 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 }