1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43:
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56:
57:
64: public final class FileChannelImpl extends FileChannel
65: {
66:
67: public static final int READ = 1;
68: public static final int WRITE = 2;
69: public static final int APPEND = 4;
70:
71:
72: public static final int EXCL = 8;
73: public static final int SYNC = 16;
74: public static final int DSYNC = 32;
75:
76: private static native void init();
77:
78: static
79: {
80: if (Configuration.INIT_LOAD_LIBRARY)
81: {
82: System.loadLibrary("javanio");
83: }
84:
85: init();
86: }
87:
88:
91:
92:
93:
94:
95:
96: private int fd = -1;
97:
98: private long pos;
99: private int mode;
100:
101: public FileChannelImpl ()
102: {
103: }
104:
105:
106: public FileChannelImpl (File file, int mode) throws FileNotFoundException
107: {
108: final String path = file.getPath();
109: fd = open (path, mode);
110: this.mode = mode;
111:
112:
113:
114: if (file.isDirectory())
115: {
116: try
117: {
118: close();
119: }
120: catch (IOException e)
121: {
122:
123: }
124:
125: throw new FileNotFoundException(path + " is a directory");
126: }
127: }
128:
129:
130: FileChannelImpl (int fd, int mode)
131: {
132: this.fd = fd;
133: this.mode = mode;
134: }
135:
136: public static FileChannelImpl in;
137: public static FileChannelImpl out;
138: public static FileChannelImpl err;
139:
140: private native int open (String path, int mode) throws FileNotFoundException;
141:
142: public native int available () throws IOException;
143: private native long implPosition () throws IOException;
144: private native void seek (long newPosition) throws IOException;
145: private native void implTruncate (long size) throws IOException;
146:
147: public native void unlock (long pos, long len) throws IOException;
148:
149: public native long size () throws IOException;
150:
151: protected native void implCloseChannel() throws IOException;
152:
153:
156: protected void finalize() throws IOException
157: {
158: this.close();
159: }
160:
161: public int read (ByteBuffer dst) throws IOException
162: {
163: int result;
164: byte[] buffer = new byte [dst.remaining ()];
165:
166: result = read (buffer, 0, buffer.length);
167:
168: if (result > 0)
169: dst.put (buffer, 0, result);
170:
171: return result;
172: }
173:
174: public int read (ByteBuffer dst, long position)
175: throws IOException
176: {
177: if (position < 0)
178: throw new IllegalArgumentException ();
179: long oldPosition = implPosition ();
180: position (position);
181: int result = read(dst);
182: position (oldPosition);
183:
184: return result;
185: }
186:
187: public native int read ()
188: throws IOException;
189:
190: public native int read (byte[] buffer, int offset, int length)
191: throws IOException;
192:
193: public long read (ByteBuffer[] dsts, int offset, int length)
194: throws IOException
195: {
196: long result = 0;
197:
198: for (int i = offset; i < offset + length; i++)
199: {
200: result += read (dsts [i]);
201: }
202:
203: return result;
204: }
205:
206: public int write (ByteBuffer src) throws IOException
207: {
208: int len = src.remaining ();
209: if (src.hasArray())
210: {
211: byte[] buffer = src.array();
212: write(buffer, src.arrayOffset() + src.position(), len);
213: src.position(src.position() + len);
214: }
215: else
216: {
217:
218: byte[] buffer = new byte [len];
219: src.get (buffer, 0, len);
220: write (buffer, 0, len);
221: }
222: return len;
223: }
224:
225: public int write (ByteBuffer src, long position)
226: throws IOException
227: {
228: if (position < 0)
229: throw new IllegalArgumentException ();
230:
231: if (!isOpen ())
232: throw new ClosedChannelException ();
233:
234: if ((mode & WRITE) == 0)
235: throw new NonWritableChannelException ();
236:
237: int result;
238: long oldPosition;
239:
240: oldPosition = implPosition ();
241: seek (position);
242: result = write(src);
243: seek (oldPosition);
244:
245: return result;
246: }
247:
248: public native void write (byte[] buffer, int offset, int length)
249: throws IOException;
250:
251: public native void write (int b) throws IOException;
252:
253: public long write(ByteBuffer[] srcs, int offset, int length)
254: throws IOException
255: {
256: long result = 0;
257:
258: for (int i = offset;i < offset + length;i++)
259: {
260: result += write (srcs[i]);
261: }
262:
263: return result;
264: }
265:
266: public native MappedByteBuffer mapImpl (char mode, long position, int size)
267: throws IOException;
268:
269: public MappedByteBuffer map (FileChannel.MapMode mode,
270: long position, long size)
271: throws IOException
272: {
273: char nmode = 0;
274: if (mode == MapMode.READ_ONLY)
275: {
276: nmode = 'r';
277: if ((this.mode & READ) == 0)
278: throw new NonReadableChannelException();
279: }
280: else if (mode == MapMode.READ_WRITE || mode == MapMode.PRIVATE)
281: {
282: nmode = mode == MapMode.READ_WRITE ? '+' : 'c';
283: if ((this.mode & (READ|WRITE)) != (READ|WRITE))
284: throw new NonWritableChannelException();
285: }
286: else
287: throw new IllegalArgumentException ();
288:
289: if (position < 0 || size < 0 || size > Integer.MAX_VALUE)
290: throw new IllegalArgumentException ();
291: return mapImpl(nmode, position, (int) size);
292: }
293:
294:
297: public void force (boolean metaData) throws IOException
298: {
299: if (!isOpen ())
300: throw new ClosedChannelException ();
301: }
302:
303:
304: private int smallTransferTo (long position, int count,
305: WritableByteChannel target)
306: throws IOException
307: {
308: ByteBuffer buffer;
309: try
310: {
311:
312:
313: buffer = map (MapMode.READ_ONLY, position, count);
314: }
315: catch (IOException e)
316: {
317: buffer = ByteBuffer.allocate (count);
318: read (buffer, position);
319: buffer.flip();
320: }
321:
322: return target.write (buffer);
323: }
324:
325: public long transferTo (long position, long count,
326: WritableByteChannel target)
327: throws IOException
328: {
329: if (position < 0
330: || count < 0)
331: throw new IllegalArgumentException ();
332:
333: if (!isOpen ())
334: throw new ClosedChannelException ();
335:
336: if ((mode & READ) == 0)
337: throw new NonReadableChannelException ();
338:
339: final int pageSize = 65536;
340: long total = 0;
341:
342: while (count > 0)
343: {
344: int transferred
345: = smallTransferTo (position, (int)Math.min (count, pageSize),
346: target);
347: if (transferred < 0)
348: break;
349: total += transferred;
350: position += transferred;
351: count -= transferred;
352: }
353:
354: return total;
355: }
356:
357:
358: private int smallTransferFrom (ReadableByteChannel src, long position,
359: int count)
360: throws IOException
361: {
362: ByteBuffer buffer = null;
363:
364: if (src instanceof FileChannel)
365: {
366: try
367: {
368:
369:
370: buffer = ((FileChannel)src).map (MapMode.READ_ONLY, position,
371: count);
372: }
373: catch (IOException e)
374: {
375: }
376: }
377:
378: if (buffer == null)
379: {
380: buffer = ByteBuffer.allocate ((int) count);
381: src.read (buffer);
382: buffer.flip();
383: }
384:
385: return write (buffer, position);
386: }
387:
388: public long transferFrom (ReadableByteChannel src, long position,
389: long count)
390: throws IOException
391: {
392: if (position < 0
393: || count < 0)
394: throw new IllegalArgumentException ();
395:
396: if (!isOpen ())
397: throw new ClosedChannelException ();
398:
399: if ((mode & WRITE) == 0)
400: throw new NonWritableChannelException ();
401:
402: final int pageSize = 65536;
403: long total = 0;
404:
405: while (count > 0)
406: {
407: int transferred = smallTransferFrom (src, position,
408: (int)Math.min (count, pageSize));
409: if (transferred < 0)
410: break;
411: total += transferred;
412: position += transferred;
413: count -= transferred;
414: }
415:
416: return total;
417: }
418:
419: public FileLock tryLock (long position, long size, boolean shared)
420: throws IOException
421: {
422: if (position < 0
423: || size < 0)
424: throw new IllegalArgumentException ();
425:
426: if (!isOpen ())
427: throw new ClosedChannelException ();
428:
429: if (shared && (mode & READ) == 0)
430: throw new NonReadableChannelException ();
431:
432: if (!shared && (mode & WRITE) == 0)
433: throw new NonWritableChannelException ();
434:
435: boolean completed = false;
436:
437: try
438: {
439: begin();
440: boolean lockable = lock(position, size, shared, false);
441: completed = true;
442: return (lockable
443: ? new FileLockImpl(this, position, size, shared)
444: : null);
445: }
446: finally
447: {
448: end(completed);
449: }
450: }
451:
452:
457: private native boolean lock(long position, long size,
458: boolean shared, boolean wait) throws IOException;
459:
460: public FileLock lock (long position, long size, boolean shared)
461: throws IOException
462: {
463: if (position < 0
464: || size < 0)
465: throw new IllegalArgumentException ();
466:
467: if (!isOpen ())
468: throw new ClosedChannelException ();
469:
470: boolean completed = false;
471:
472: try
473: {
474: boolean lockable = lock(position, size, shared, true);
475: completed = true;
476: return (lockable
477: ? new FileLockImpl(this, position, size, shared)
478: : null);
479: }
480: finally
481: {
482: end(completed);
483: }
484: }
485:
486: public long position ()
487: throws IOException
488: {
489: if (!isOpen ())
490: throw new ClosedChannelException ();
491:
492: return implPosition ();
493: }
494:
495: public FileChannel position (long newPosition)
496: throws IOException
497: {
498: if (newPosition < 0)
499: throw new IllegalArgumentException ();
500:
501: if (!isOpen ())
502: throw new ClosedChannelException ();
503:
504:
505:
506: seek (newPosition);
507: return this;
508: }
509:
510: public FileChannel truncate (long size)
511: throws IOException
512: {
513: if (size < 0)
514: throw new IllegalArgumentException ();
515:
516: if (!isOpen ())
517: throw new ClosedChannelException ();
518:
519: if ((mode & WRITE) == 0)
520: throw new NonWritableChannelException ();
521:
522: if (size < size ())
523: implTruncate (size);
524:
525: return this;
526: }
527: }