1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.io.nio;
16
17 import java.io.File;
18 import java.io.FileInputStream;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.OutputStream;
22 import java.nio.ByteBuffer;
23 import java.nio.channels.Channels;
24 import java.nio.channels.FileChannel;
25 import java.nio.channels.ReadableByteChannel;
26 import java.nio.channels.WritableByteChannel;
27
28 import org.mortbay.io.AbstractBuffer;
29 import org.mortbay.io.Buffer;
30
31
32
33
34
35
36 public class NIOBuffer extends AbstractBuffer
37 {
38 public final static boolean
39 DIRECT=true,
40 INDIRECT=false;
41
42 protected ByteBuffer _buf;
43 private ReadableByteChannel _in;
44 private InputStream _inStream;
45 private WritableByteChannel _out;
46 private OutputStream _outStream;
47
48 public NIOBuffer(int size, boolean direct)
49 {
50 super(READWRITE,NON_VOLATILE);
51 _buf = direct
52 ?ByteBuffer.allocateDirect(size)
53 :ByteBuffer.allocate(size);
54 _buf.position(0);
55 _buf.limit(_buf.capacity());
56 }
57
58 public NIOBuffer(ByteBuffer buffer,boolean immutable)
59 {
60 super(immutable?IMMUTABLE:READWRITE,NON_VOLATILE);
61 _buf = buffer;
62 setGetIndex(buffer.position());
63 setPutIndex(buffer.limit());
64 }
65
66
67
68
69 public NIOBuffer(File file) throws IOException
70 {
71 super(READONLY,NON_VOLATILE);
72 FileInputStream fis = new FileInputStream(file);
73 FileChannel fc = fis.getChannel();
74 _buf = fc.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
75 setGetIndex(0);
76 setPutIndex((int)file.length());
77 _access=IMMUTABLE;
78 }
79
80 public byte[] array()
81 {
82 if (!_buf.hasArray())
83 return null;
84 return _buf.array();
85 }
86
87 public int capacity()
88 {
89 return _buf.capacity();
90 }
91
92 public byte peek(int position)
93 {
94 return _buf.get(position);
95 }
96
97 public int peek(int index, byte[] b, int offset, int length)
98 {
99 int l = length;
100 if (index+l > capacity())
101 {
102 l=capacity()-index;
103 if (l==0)
104 return -1;
105 }
106
107 if (l < 0)
108 return -1;
109 try
110 {
111 _buf.position(index);
112 _buf.get(b,offset,l);
113 }
114 finally
115 {
116 _buf.position(0);
117 }
118
119 return l;
120 }
121
122 public void poke(int index, byte b)
123 {
124 if (isReadOnly()) throw new IllegalStateException(__READONLY);
125 if (index < 0) throw new IllegalArgumentException("index<0: " + index + "<0");
126 if (index > capacity())
127 throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
128 _buf.put(index,b);
129 }
130
131 public int poke(int index, Buffer src)
132 {
133 if (isReadOnly()) throw new IllegalStateException(__READONLY);
134
135 byte[] array=src.array();
136 if (array!=null)
137 {
138 int length = poke(index,array,src.getIndex(),src.length());
139 return length;
140 }
141 else
142 {
143 Buffer src_buf=src.buffer();
144 if (src_buf instanceof NIOBuffer)
145 {
146 ByteBuffer src_bytebuf = ((NIOBuffer)src_buf)._buf;
147 if (src_bytebuf==_buf)
148 src_bytebuf=_buf.duplicate();
149 try
150 {
151 _buf.position(index);
152 int space = _buf.remaining();
153
154 int length=src.length();
155 if (length>space)
156 length=space;
157
158 src_bytebuf.position(src.getIndex());
159 src_bytebuf.limit(src.getIndex()+length);
160
161 _buf.put(src_bytebuf);
162 return length;
163 }
164 finally
165 {
166 _buf.position(0);
167 src_bytebuf.limit(src_bytebuf.capacity());
168 src_bytebuf.position(0);
169 }
170 }
171 else
172 return super.poke(index,src);
173 }
174 }
175
176 public int poke(int index, byte[] b, int offset, int length)
177 {
178 if (isReadOnly()) throw new IllegalStateException(__READONLY);
179
180 if (index < 0) throw new IllegalArgumentException("index<0: " + index + "<0");
181
182 if (index + length > capacity())
183 {
184 length=capacity()-index;
185 if (length<0)
186 throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
187 }
188
189 try
190 {
191 _buf.position(index);
192
193 int space=_buf.remaining();
194
195 if (length>space)
196 length=space;
197 if (length>0)
198 _buf.put(b,offset,length);
199 return length;
200 }
201 finally
202 {
203 _buf.position(0);
204 }
205 }
206
207
208 public ByteBuffer getByteBuffer()
209 {
210 return _buf;
211 }
212
213
214 public int readFrom(InputStream in, int max) throws IOException
215 {
216 if (_in==null || !_in.isOpen() || in!=_inStream)
217 {
218 _in=Channels.newChannel(in);
219 _inStream=in;
220 }
221
222 if (max<0 || max>space())
223 max=space();
224 int p = putIndex();
225
226 try
227 {
228 int len=0, total=0, available=max;
229 int loop=0;
230 while (total<max)
231 {
232 _buf.position(p);
233 _buf.limit(p+available);
234 len=_in.read(_buf);
235 if (len<0)
236 {
237 _in=null;
238 _inStream=in;
239 break;
240 }
241 else if (len>0)
242 {
243 p += len;
244 total += len;
245 available -= len;
246 setPutIndex(p);
247 loop=0;
248 }
249 else if (loop++>1)
250 break;
251 if (in.available()<=0)
252 break;
253 }
254 if (len<0 && total==0)
255 return -1;
256 return total;
257
258 }
259 catch(IOException e)
260 {
261 _in=null;
262 _inStream=in;
263 throw e;
264 }
265 finally
266 {
267 if (_in!=null && !_in.isOpen())
268 {
269 _in=null;
270 _inStream=in;
271 }
272 _buf.position(0);
273 _buf.limit(_buf.capacity());
274 }
275 }
276
277
278 public void writeTo(OutputStream out) throws IOException
279 {
280 if (_out==null || !_out.isOpen() || _out!=_outStream)
281 {
282 _out=Channels.newChannel(out);
283 _outStream=out;
284 }
285
286 try
287 {
288 int loop=0;
289 while(hasContent() && _out.isOpen())
290 {
291 _buf.position(getIndex());
292 _buf.limit(putIndex());
293 int len=_out.write(_buf);
294 if (len<0)
295 break;
296 else if (len>0)
297 {
298 skip(len);
299 loop=0;
300 }
301 else if (loop++>1)
302 break;
303 }
304 }
305 catch(IOException e)
306 {
307 _out=null;
308 _outStream=null;
309 throw e;
310 }
311 finally
312 {
313 if (_out!=null && !_out.isOpen())
314 {
315 _out=null;
316 _outStream=null;
317 }
318 _buf.position(0);
319 _buf.limit(_buf.capacity());
320 }
321
322 }
323
324
325 }