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