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