~ubuntu-branches/ubuntu/dapper/ikvm/dapper

« back to all changes in this revision

Viewing changes to classpath/gnu/java/nio/channels/FileChannelImpl.java

  • Committer: Bazaar Package Importer
  • Author(s): John Goerzen
  • Date: 2004-08-26 10:18:19 UTC
  • Revision ID: james.westby@ubuntu.com-20040826101819-plz8au2mx4uk1cvc
Tags: upstream-0.8.0.0
ImportĀ upstreamĀ versionĀ 0.8.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* FileChannelImpl.java -- 
 
2
   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
 
3
 
 
4
This file is part of GNU Classpath.
 
5
 
 
6
GNU Classpath is free software; you can redistribute it and/or modify
 
7
it under the terms of the GNU General Public License as published by
 
8
the Free Software Foundation; either version 2, or (at your option)
 
9
any later version.
 
10
 
 
11
GNU Classpath is distributed in the hope that it will be useful, but
 
12
WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
General Public License for more details.
 
15
 
 
16
You should have received a copy of the GNU General Public License
 
17
along with GNU Classpath; see the file COPYING.  If not, write to the
 
18
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 
19
02111-1307 USA.
 
20
 
 
21
Linking this library statically or dynamically with other modules is
 
22
making a combined work based on this library.  Thus, the terms and
 
23
conditions of the GNU General Public License cover the whole
 
24
combination.
 
25
 
 
26
As a special exception, the copyright holders of this library give you
 
27
permission to link this library with independent modules to produce an
 
28
executable, regardless of the license terms of these independent
 
29
modules, and to copy and distribute the resulting executable under
 
30
terms of your choice, provided that you also meet, for each linked
 
31
independent module, the terms and conditions of the license of that
 
32
module.  An independent module is a module which is not derived from
 
33
or based on this library.  If you modify this library, you may extend
 
34
this exception to your version of the library, but you are not
 
35
obligated to do so.  If you do not wish to do so, delete this
 
36
exception statement from your version. */
 
37
 
 
38
 
 
39
package gnu.java.nio.channels;
 
40
 
 
41
import gnu.classpath.Configuration;
 
42
import gnu.java.nio.FileLockImpl;
 
43
 
 
44
import java.io.FileNotFoundException;
 
45
import java.io.IOException;
 
46
import java.nio.ByteBuffer;
 
47
import java.nio.MappedByteBuffer;
 
48
import java.nio.channels.ClosedChannelException;
 
49
import java.nio.channels.FileChannel;
 
50
import java.nio.channels.FileLock;
 
51
import java.nio.channels.NonReadableChannelException;
 
52
import java.nio.channels.NonWritableChannelException;
 
53
import java.nio.channels.ReadableByteChannel;
 
54
import java.nio.channels.WritableByteChannel;
 
55
 
 
56
import cli.System.Console;
 
57
import cli.System.IO.*;
 
58
import ikvm.lang.ByteArrayHack;
 
59
import ikvm.lang.CIL;
 
60
 
 
61
/**
 
62
 * This file is not user visible !
 
63
 * But alas, Java does not have a concept of friendly packages
 
64
 * so this class is public. 
 
65
 * Instances of this class are created by invoking getChannel
 
66
 * Upon a Input/Output/RandomAccessFile object.
 
67
 */
 
68
 
 
69
public final class FileChannelImpl extends FileChannel
 
70
{
 
71
    // These are mode values for open().
 
72
    public static final int READ   = 1;
 
73
    public static final int WRITE  = 2;
 
74
    public static final int APPEND = 4;
 
75
 
 
76
    // EXCL is used only when making a temp file.
 
77
    public static final int EXCL   = 8;
 
78
    public static final int SYNC   = 16;
 
79
    public static final int DSYNC  = 32;
 
80
 
 
81
    private Stream stream;
 
82
    private int mode;
 
83
 
 
84
    public FileChannelImpl ()
 
85
    {
 
86
    }
 
87
 
 
88
    /* Open a file.  MODE is a combination of the above mode flags. */
 
89
    public FileChannelImpl (String path, int mode) throws FileNotFoundException
 
90
    {
 
91
        stream = open (path, mode);
 
92
        this.mode = mode;
 
93
    }
 
94
 
 
95
    public FileChannelImpl(Stream stream)
 
96
    {
 
97
        this.stream = stream;
 
98
        mode = (stream.get_CanRead() ? READ : 0) | (stream.get_CanWrite() ? WRITE : 0);
 
99
    }
 
100
 
 
101
    public static final FileChannelImpl in = new FileChannelImpl(Console.OpenStandardInput());
 
102
    public static final FileChannelImpl out = new FileChannelImpl(Console.OpenStandardOutput());
 
103
    public static final FileChannelImpl err = new FileChannelImpl(Console.OpenStandardError());
 
104
 
 
105
    private Stream open (String path, int mode) throws FileNotFoundException
 
106
    {
 
107
        if(stream != null)
 
108
            throw new InternalError("FileChannelImpl already open");
 
109
        if ((path == null) || path.equals(""))
 
110
            throw new IllegalArgumentException("Path cannot be null");
 
111
        try
 
112
        {
 
113
            int fileMode;
 
114
            int fileAccess;
 
115
            int fileShare;
 
116
            // NOTE we don't support SYNC or DSYNC
 
117
            switch(mode & (READ|WRITE|APPEND))
 
118
            {
 
119
                case READ:
 
120
                    fileMode = FileMode.Open;
 
121
                    fileAccess = FileAccess.Read;
 
122
                    break;
 
123
                case READ|WRITE:
 
124
                    fileMode = FileMode.OpenOrCreate;
 
125
                    fileAccess = FileAccess.ReadWrite;
 
126
                    break;
 
127
                case WRITE:
 
128
                    fileMode = FileMode.Create;
 
129
                    fileAccess = FileAccess.Write;
 
130
                    break;
 
131
                case APPEND:
 
132
                case APPEND|WRITE:
 
133
                    fileMode = FileMode.Append;
 
134
                    fileAccess = FileAccess.Write;
 
135
                    break;
 
136
                default:
 
137
                    throw new IllegalArgumentException("Invalid mode value: " + mode);
 
138
            }
 
139
            if(false) throw new cli.System.IO.IOException();
 
140
            if(false) throw new cli.System.Security.SecurityException();
 
141
            if(false) throw new cli.System.UnauthorizedAccessException();
 
142
            if(false) throw new cli.System.ArgumentException();
 
143
            if(false) throw new cli.System.NotSupportedException();
 
144
            return cli.System.IO.File.Open(demanglePath(path), FileMode.wrap(fileMode), FileAccess.wrap(fileAccess), FileShare.wrap(FileShare.ReadWrite));
 
145
        }
 
146
        catch(cli.System.Security.SecurityException x1)
 
147
        {
 
148
            throw new SecurityException(x1.getMessage());
 
149
        }
 
150
        catch(cli.System.IO.IOException x2)
 
151
        {
 
152
            throw new FileNotFoundException(x2.getMessage());
 
153
        }
 
154
        catch(cli.System.UnauthorizedAccessException x3)
 
155
        {
 
156
            // this is caused by "name" being a directory instead of a file
 
157
            throw new FileNotFoundException(x3.getMessage());
 
158
        }
 
159
        catch(cli.System.ArgumentException x4)
 
160
        {
 
161
            throw new FileNotFoundException(x4.getMessage());
 
162
        }
 
163
        catch(cli.System.NotSupportedException x5)
 
164
        {
 
165
            throw new FileNotFoundException(x5.getMessage());
 
166
        }
 
167
    }
 
168
 
 
169
    private static String demanglePath(String path)
 
170
    {
 
171
        // HACK for some reason Java accepts: \c:\foo.txt
 
172
        // I don't know what else, but for now lets just support this
 
173
        if(path.length() > 3 && (path.charAt(0) == '\\' || path.charAt(0) == '/') && path.charAt(2) == ':')
 
174
        {
 
175
            path = path.substring(1);
 
176
        }
 
177
        return path;
 
178
    }
 
179
 
 
180
    public int available () throws IOException
 
181
    {
 
182
        if(stream == null)
 
183
            throw new IOException("Invalid FileChannelImpl");
 
184
 
 
185
        try
 
186
        {
 
187
            if(false) throw new cli.System.IO.IOException();
 
188
            if(false) throw new cli.System.NotSupportedException();
 
189
            if(stream.get_CanSeek())
 
190
                return (int)Math.min(Integer.MAX_VALUE, Math.max(0, stream.get_Length() - stream.get_Position()));
 
191
            return 0;
 
192
        }
 
193
        catch(cli.System.IO.IOException x)
 
194
        {
 
195
            throw new IOException(x.getMessage());
 
196
        }
 
197
        catch(cli.System.NotSupportedException x1)
 
198
        {
 
199
            // this means we have a broken Stream, because if CanSeek returns true, it must
 
200
            // support Length and Position
 
201
            return 0;
 
202
        }
 
203
    }
 
204
 
 
205
    private long implPosition () throws IOException
 
206
    {
 
207
        if(stream == null)
 
208
            throw new IOException("Invalid FileChannelImpl");
 
209
 
 
210
        try
 
211
        {
 
212
            if(false) throw new cli.System.IO.IOException();
 
213
            return stream.get_Position();
 
214
        }
 
215
        catch(cli.System.IO.IOException x)
 
216
        {
 
217
            throw new IOException(x.getMessage());
 
218
        }
 
219
        // TODO map al the other exceptions as well...
 
220
    }
 
221
 
 
222
    private void seek (long newPosition) throws IOException
 
223
    {
 
224
        if(stream == null)
 
225
            throw new IOException("Invalid FileChannelImpl");
 
226
 
 
227
        try
 
228
        {
 
229
            if(false) throw new cli.System.IO.IOException();
 
230
            stream.Seek(newPosition, SeekOrigin.wrap(SeekOrigin.Begin));
 
231
        }
 
232
        catch(cli.System.IO.IOException x)
 
233
        {
 
234
            throw new IOException(x.getMessage());
 
235
        }
 
236
        // TODO map al the other exceptions as well...
 
237
    }
 
238
 
 
239
    private void implTruncate (long size) throws IOException
 
240
    {
 
241
        if(stream == null)
 
242
            throw new IOException("Invalid FileChannelImpl");
 
243
 
 
244
        if (size < 0)
 
245
            throw new IllegalArgumentException("Length cannot be less than zero " +
 
246
                size);
 
247
 
 
248
        try
 
249
        {
 
250
            if(false) throw new cli.System.IO.IOException();
 
251
            stream.SetLength(size);
 
252
        }
 
253
        catch(cli.System.IO.IOException x)
 
254
        {
 
255
            throw new IOException(x.getMessage());
 
256
        }
 
257
        // TODO map al the other exceptions as well...
 
258
    }
 
259
  
 
260
    public void unlock (long pos, long len) throws IOException
 
261
    {
 
262
        if(stream == null)
 
263
            throw new IOException("Invalid FileChannelImpl");
 
264
 
 
265
        try
 
266
        {
 
267
            if(false) throw new cli.System.IO.IOException();
 
268
            if(false) throw new cli.System.ArgumentOutOfRangeException();
 
269
            ((FileStream)stream).Unlock(pos, len);
 
270
        }
 
271
        catch(ClassCastException c)
 
272
        {
 
273
            throw new IOException("Locking not supported");
 
274
        }
 
275
        catch(cli.System.ArgumentOutOfRangeException x1)
 
276
        {
 
277
            throw new IOException(x1.getMessage());
 
278
        }
 
279
        catch(cli.System.IO.IOException x)
 
280
        {
 
281
            throw new IOException(x.getMessage());
 
282
        }
 
283
        // TODO map al the other exceptions as well...
 
284
    }
 
285
 
 
286
    public long size () throws IOException
 
287
    {
 
288
        if(stream == null)
 
289
            throw new IOException("Invalid FileChannelImpl");
 
290
 
 
291
        try
 
292
        {
 
293
            if(false) throw new cli.System.IO.IOException();
 
294
            return stream.get_Length();
 
295
        }
 
296
        catch(cli.System.IO.IOException x)
 
297
        {
 
298
            throw new IOException(x.getMessage());
 
299
        }
 
300
        // TODO map al the other exceptions as well...
 
301
    }
 
302
    
 
303
    protected void implCloseChannel() throws IOException
 
304
    {
 
305
        if(stream != null)
 
306
        {
 
307
            // HACK don't close stdin because that throws a NotSupportedException (bug in System.IO.__ConsoleStream)
 
308
            if(stream != in.stream)
 
309
            {
 
310
                try
 
311
                {
 
312
                    stream.Close();
 
313
                    if(false) throw new cli.System.IO.IOException();
 
314
                }
 
315
                catch(cli.System.IO.IOException x)
 
316
                {
 
317
                    throw new IOException(x.getMessage());
 
318
                }
 
319
            }
 
320
            stream = null;
 
321
        }
 
322
    }
 
323
 
 
324
    public int read (ByteBuffer dst) throws IOException
 
325
    {
 
326
        int result;
 
327
        byte[] buffer = new byte [dst.remaining ()];
 
328
    
 
329
        result = read (buffer, 0, buffer.length);
 
330
 
 
331
        if (result > 0)
 
332
            dst.put (buffer, 0, result);
 
333
 
 
334
        return result;
 
335
    }
 
336
 
 
337
    public int read (ByteBuffer dst, long position)
 
338
        throws IOException
 
339
    {
 
340
        if (position < 0)
 
341
            throw new IllegalArgumentException ();
 
342
        long oldPosition = implPosition ();
 
343
        position (position);
 
344
        int result = read(dst);
 
345
        position (oldPosition);
 
346
    
 
347
        return result;
 
348
    }
 
349
 
 
350
    public int read () throws IOException
 
351
    {
 
352
        if(stream == null)
 
353
            throw new IOException("Invalid FileChannelImpl");
 
354
 
 
355
        try
 
356
        {
 
357
            if(false) throw new cli.System.IO.IOException();
 
358
            return stream.ReadByte();
 
359
        }
 
360
        catch(cli.System.IO.IOException x)
 
361
        {
 
362
            throw new IOException(x.getMessage());
 
363
        }
 
364
        // TODO map al the other exceptions as well...
 
365
    }
 
366
 
 
367
    public int read (byte[] buf, int offset, int len) throws IOException
 
368
    {
 
369
        if(stream == null)
 
370
            throw new IOException("Invalid FileChannelImpl");
 
371
 
 
372
        if (len == 0)
 
373
            return(0);
 
374
 
 
375
        if ((offset < 0) || (offset > buf.length))
 
376
            throw new IllegalArgumentException("Offset invalid: " + offset);
 
377
 
 
378
        if ((len < 0) || (len > (buf.length - offset)))
 
379
            throw new IllegalArgumentException("Length invalid: " + len);
 
380
 
 
381
        try
 
382
        {
 
383
            if(false) throw new cli.System.IO.IOException();
 
384
            int count = stream.Read(ByteArrayHack.cast(buf), offset, len);
 
385
            if(count == 0)
 
386
            {
 
387
                count = -1;
 
388
            }
 
389
            return count;
 
390
        }
 
391
        catch(cli.System.IO.IOException x)
 
392
        {
 
393
            throw new IOException(x.getMessage());
 
394
        }
 
395
        // TODO map al the other exceptions as well...
 
396
    }
 
397
 
 
398
    public long read (ByteBuffer[] dsts, int offset, int length)
 
399
        throws IOException
 
400
    {
 
401
        long result = 0;
 
402
 
 
403
        for (int i = offset; i < offset + length; i++)
 
404
        {
 
405
            result += read (dsts [i]);
 
406
        }
 
407
 
 
408
        return result;
 
409
    }
 
410
 
 
411
    public int write (ByteBuffer src) throws IOException
 
412
    {
 
413
        int len = src.remaining ();
 
414
        if (src.hasArray())
 
415
        {
 
416
            byte[] buffer = src.array();
 
417
            write(buffer, src.arrayOffset() + src.position(), len);
 
418
        }
 
419
        else
 
420
        {
 
421
            // Use a more efficient native method! FIXME!
 
422
            byte[] buffer = new byte [len];
 
423
            src.get (buffer, 0, len);
 
424
            write (buffer, 0, len);
 
425
        }
 
426
        return len;
 
427
    }
 
428
    
 
429
    public int write (ByteBuffer src, long position)
 
430
        throws IOException
 
431
    {
 
432
        if (position < 0)
 
433
            throw new IllegalArgumentException ();
 
434
 
 
435
        if (!isOpen ())
 
436
            throw new ClosedChannelException ();
 
437
    
 
438
        if ((mode & WRITE) == 0)
 
439
            throw new NonWritableChannelException ();
 
440
 
 
441
        int result;
 
442
        long oldPosition;
 
443
 
 
444
        oldPosition = implPosition ();
 
445
        seek (position);
 
446
        result = write(src);
 
447
        seek (oldPosition);
 
448
    
 
449
        return result;
 
450
    }
 
451
 
 
452
    public void write (byte[] buf, int offset, int len) throws IOException
 
453
    {
 
454
        if(stream == null)
 
455
            throw new IOException("Invalid FileChannelImpl");
 
456
 
 
457
        if (len == 0)
 
458
            return;
 
459
 
 
460
        if ((offset < 0) || (offset > buf.length))
 
461
            throw new IllegalArgumentException("Offset invalid: " + offset);
 
462
 
 
463
        if ((len < 0) || (len > (buf.length - offset)))
 
464
            throw new IllegalArgumentException("Length invalid: " + len);
 
465
 
 
466
        try
 
467
        {
 
468
            if(false) throw new cli.System.IO.IOException();
 
469
            stream.Write(ByteArrayHack.cast(buf), offset, len);
 
470
            // NOTE FileStream buffers the output, so we have to flush explicitly
 
471
            stream.Flush();
 
472
        }
 
473
        catch(cli.System.IO.IOException x)
 
474
        {
 
475
            throw new IOException(x.getMessage());
 
476
        }
 
477
        // TODO map al the other exceptions as well...
 
478
    }
 
479
  
 
480
    public void write (int b) throws IOException
 
481
    {
 
482
        stream.WriteByte(CIL.box_ubyte((byte)b));
 
483
    }
 
484
 
 
485
    public long write(ByteBuffer[] srcs, int offset, int length)
 
486
        throws IOException
 
487
    {
 
488
        long result = 0;
 
489
 
 
490
        for (int i = offset;i < offset + length;i++)
 
491
        {
 
492
            result += write (srcs[i]);
 
493
        }
 
494
    
 
495
        return result;
 
496
    }
 
497
                                   
 
498
    public MappedByteBuffer mapImpl (char mode, long position, int size) throws IOException
 
499
    {
 
500
        // TODO
 
501
        throw new Error("not implemented");
 
502
    }
 
503
 
 
504
    public MappedByteBuffer map (FileChannel.MapMode mode,
 
505
        long position, long size)
 
506
        throws IOException
 
507
    {
 
508
        char nmode = 0;
 
509
        if (mode == MapMode.READ_ONLY)
 
510
        {
 
511
            nmode = 'r';
 
512
            if ((this.mode & READ) == 0)
 
513
                throw new NonReadableChannelException();
 
514
        }
 
515
        else if (mode == MapMode.READ_WRITE || mode == MapMode.PRIVATE)
 
516
        {
 
517
            nmode = mode == MapMode.READ_WRITE ? '+' : 'c';
 
518
            if ((this.mode & (READ|WRITE)) != (READ|WRITE))
 
519
                throw new NonWritableChannelException();
 
520
        }
 
521
        else
 
522
            throw new IllegalArgumentException ();
 
523
    
 
524
        if (position < 0 || size < 0 || size > Integer.MAX_VALUE)
 
525
            throw new IllegalArgumentException ();
 
526
        return mapImpl(nmode, position, (int) size);
 
527
    }
 
528
 
 
529
    /**
 
530
     * msync with the disk
 
531
     */
 
532
    public void force (boolean metaData) throws IOException
 
533
    {
 
534
        if (!isOpen ())
 
535
            throw new ClosedChannelException ();
 
536
    }
 
537
 
 
538
    public long transferTo (long position, long count, WritableByteChannel target)
 
539
        throws IOException
 
540
    {
 
541
        if (position < 0
 
542
            || count < 0)
 
543
            throw new IllegalArgumentException ();
 
544
 
 
545
        if (!isOpen ())
 
546
            throw new ClosedChannelException ();
 
547
 
 
548
        if ((mode & READ) == 0)
 
549
            throw new NonReadableChannelException ();
 
550
   
 
551
        // XXX: count needs to be casted from long to int. Dataloss ?
 
552
        ByteBuffer buffer = ByteBuffer.allocate ((int) count);
 
553
        read (buffer, position);
 
554
        buffer.flip();
 
555
        return target.write (buffer);
 
556
    }
 
557
 
 
558
    public long transferFrom (ReadableByteChannel src, long position, long count)
 
559
        throws IOException
 
560
    {
 
561
        if (position < 0
 
562
            || count < 0)
 
563
            throw new IllegalArgumentException ();
 
564
 
 
565
        if (!isOpen ())
 
566
            throw new ClosedChannelException ();
 
567
 
 
568
        if ((mode & WRITE) == 0)
 
569
            throw new NonWritableChannelException ();
 
570
 
 
571
        // XXX: count needs to be casted from long to int. Dataloss ?
 
572
        ByteBuffer buffer = ByteBuffer.allocate ((int) count);
 
573
        src.read (buffer);
 
574
        buffer.flip();
 
575
        return write (buffer, position);
 
576
    }
 
577
 
 
578
    public FileLock tryLock (long position, long size, boolean shared)
 
579
        throws IOException
 
580
    {
 
581
        if (position < 0
 
582
            || size < 0)
 
583
            throw new IllegalArgumentException ();
 
584
 
 
585
        if (!isOpen ())
 
586
            throw new ClosedChannelException ();
 
587
 
 
588
        if (shared && (mode & READ) == 0)
 
589
            throw new NonReadableChannelException ();
 
590
        
 
591
        if (!shared && (mode & WRITE) == 0)
 
592
            throw new NonWritableChannelException ();
 
593
        
 
594
        boolean completed = false;
 
595
    
 
596
        try
 
597
        {
 
598
            begin();
 
599
            lock(position, size, shared, true);
 
600
            completed = true;
 
601
            return new FileLockImpl(this, position, size, shared);
 
602
        }
 
603
        finally
 
604
        {
 
605
            end(completed);
 
606
        }
 
607
    }
 
608
 
 
609
    /** Try to acquire a lock at the given position and size.
 
610
     * On success return true.
 
611
     * If wait as specified, block until we can get it.
 
612
     * Otherwise return false.
 
613
     */
 
614
    private boolean lock(long position, long size, boolean shared, boolean wait) throws IOException
 
615
    {
 
616
        if(stream == null)
 
617
            throw new IOException("Invalid FileChannelImpl");
 
618
 
 
619
        try
 
620
        {
 
621
            if(false) throw new cli.System.IO.IOException();
 
622
            if(false) throw new cli.System.ArgumentOutOfRangeException();
 
623
            // TODO if wait is false, we shouldn't block...
 
624
            ((FileStream)stream).Lock(position, size);
 
625
            return true;
 
626
        }
 
627
        catch(ClassCastException c)
 
628
        {
 
629
            throw new IOException("Locking not supported");
 
630
        }
 
631
        catch(cli.System.ArgumentOutOfRangeException x1)
 
632
        {
 
633
            throw new IOException(x1.getMessage());
 
634
        }
 
635
        catch(cli.System.IO.IOException x)
 
636
        {
 
637
            throw new IOException(x.getMessage());
 
638
        }
 
639
        // TODO map al the other exceptions as well...  
 
640
    }
 
641
  
 
642
    public FileLock lock (long position, long size, boolean shared)
 
643
        throws IOException
 
644
    {
 
645
        if (position < 0
 
646
            || size < 0)
 
647
            throw new IllegalArgumentException ();
 
648
 
 
649
        if (!isOpen ())
 
650
            throw new ClosedChannelException ();
 
651
 
 
652
        boolean completed = false;
 
653
 
 
654
        try
 
655
        {
 
656
            boolean lockable = lock(position, size, shared, false);
 
657
            completed = true;
 
658
            return (lockable
 
659
                ? new FileLockImpl(this, position, size, shared)
 
660
                : null);
 
661
        }
 
662
        finally
 
663
        {
 
664
            end(completed);
 
665
        }
 
666
    }
 
667
 
 
668
    public long position ()
 
669
        throws IOException
 
670
    {
 
671
        if (!isOpen ())
 
672
            throw new ClosedChannelException ();
 
673
 
 
674
        return implPosition ();
 
675
    }
 
676
  
 
677
    public FileChannel position (long newPosition)
 
678
        throws IOException
 
679
    {
 
680
        if (newPosition < 0)
 
681
            throw new IllegalArgumentException ();
 
682
 
 
683
        if (!isOpen ())
 
684
            throw new ClosedChannelException ();
 
685
 
 
686
        // FIXME note semantics if seeking beyond eof.
 
687
        // We should seek lazily - only on a write.
 
688
        seek (newPosition);
 
689
        return this;
 
690
    }
 
691
  
 
692
    public FileChannel truncate (long size)
 
693
        throws IOException
 
694
    {
 
695
        if (size < 0)
 
696
            throw new IllegalArgumentException ();
 
697
 
 
698
        if (!isOpen ())
 
699
            throw new ClosedChannelException ();
 
700
 
 
701
        if ((mode & WRITE) == 0)
 
702
            throw new NonWritableChannelException ();
 
703
 
 
704
        implTruncate (size);
 
705
        return this;
 
706
    }
 
707
}