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