1
/* FileChannelImpl.java --
2
Copyright (C) 2002, 2004 Free Software Foundation, Inc.
4
This file is part of GNU Classpath.
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)
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.
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
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
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. */
39
package gnu.java.nio.channels;
41
import gnu.classpath.Configuration;
42
import gnu.java.nio.FileLockImpl;
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;
56
import cli.System.Console;
57
import cli.System.IO.*;
58
import ikvm.lang.ByteArrayHack;
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.
69
public final class FileChannelImpl extends FileChannel
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;
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;
81
private Stream stream;
84
public FileChannelImpl ()
88
/* Open a file. MODE is a combination of the above mode flags. */
89
public FileChannelImpl (String path, int mode) throws FileNotFoundException
91
stream = open (path, mode);
95
public FileChannelImpl(Stream stream)
98
mode = (stream.get_CanRead() ? READ : 0) | (stream.get_CanWrite() ? WRITE : 0);
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());
105
private Stream open (String path, int mode) throws FileNotFoundException
108
throw new InternalError("FileChannelImpl already open");
109
if ((path == null) || path.equals(""))
110
throw new IllegalArgumentException("Path cannot be null");
116
// NOTE we don't support SYNC or DSYNC
117
switch(mode & (READ|WRITE|APPEND))
120
fileMode = FileMode.Open;
121
fileAccess = FileAccess.Read;
124
fileMode = FileMode.OpenOrCreate;
125
fileAccess = FileAccess.ReadWrite;
128
fileMode = FileMode.Create;
129
fileAccess = FileAccess.Write;
133
fileMode = FileMode.Append;
134
fileAccess = FileAccess.Write;
137
throw new IllegalArgumentException("Invalid mode value: " + mode);
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));
146
catch(cli.System.Security.SecurityException x1)
148
throw new SecurityException(x1.getMessage());
150
catch(cli.System.IO.IOException x2)
152
throw new FileNotFoundException(x2.getMessage());
154
catch(cli.System.UnauthorizedAccessException x3)
156
// this is caused by "name" being a directory instead of a file
157
throw new FileNotFoundException(x3.getMessage());
159
catch(cli.System.ArgumentException x4)
161
throw new FileNotFoundException(x4.getMessage());
163
catch(cli.System.NotSupportedException x5)
165
throw new FileNotFoundException(x5.getMessage());
169
private static String demanglePath(String path)
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) == ':')
175
path = path.substring(1);
180
public int available () throws IOException
183
throw new IOException("Invalid FileChannelImpl");
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()));
193
catch(cli.System.IO.IOException x)
195
throw new IOException(x.getMessage());
197
catch(cli.System.NotSupportedException x1)
199
// this means we have a broken Stream, because if CanSeek returns true, it must
200
// support Length and Position
205
private long implPosition () throws IOException
208
throw new IOException("Invalid FileChannelImpl");
212
if(false) throw new cli.System.IO.IOException();
213
return stream.get_Position();
215
catch(cli.System.IO.IOException x)
217
throw new IOException(x.getMessage());
219
// TODO map al the other exceptions as well...
222
private void seek (long newPosition) throws IOException
225
throw new IOException("Invalid FileChannelImpl");
229
if(false) throw new cli.System.IO.IOException();
230
stream.Seek(newPosition, SeekOrigin.wrap(SeekOrigin.Begin));
232
catch(cli.System.IO.IOException x)
234
throw new IOException(x.getMessage());
236
// TODO map al the other exceptions as well...
239
private void implTruncate (long size) throws IOException
242
throw new IOException("Invalid FileChannelImpl");
245
throw new IllegalArgumentException("Length cannot be less than zero " +
250
if(false) throw new cli.System.IO.IOException();
251
stream.SetLength(size);
253
catch(cli.System.IO.IOException x)
255
throw new IOException(x.getMessage());
257
// TODO map al the other exceptions as well...
260
public void unlock (long pos, long len) throws IOException
263
throw new IOException("Invalid FileChannelImpl");
267
if(false) throw new cli.System.IO.IOException();
268
if(false) throw new cli.System.ArgumentOutOfRangeException();
269
((FileStream)stream).Unlock(pos, len);
271
catch(ClassCastException c)
273
throw new IOException("Locking not supported");
275
catch(cli.System.ArgumentOutOfRangeException x1)
277
throw new IOException(x1.getMessage());
279
catch(cli.System.IO.IOException x)
281
throw new IOException(x.getMessage());
283
// TODO map al the other exceptions as well...
286
public long size () throws IOException
289
throw new IOException("Invalid FileChannelImpl");
293
if(false) throw new cli.System.IO.IOException();
294
return stream.get_Length();
296
catch(cli.System.IO.IOException x)
298
throw new IOException(x.getMessage());
300
// TODO map al the other exceptions as well...
303
protected void implCloseChannel() throws IOException
307
// HACK don't close stdin because that throws a NotSupportedException (bug in System.IO.__ConsoleStream)
308
if(stream != in.stream)
313
if(false) throw new cli.System.IO.IOException();
315
catch(cli.System.IO.IOException x)
317
throw new IOException(x.getMessage());
324
public int read (ByteBuffer dst) throws IOException
327
byte[] buffer = new byte [dst.remaining ()];
329
result = read (buffer, 0, buffer.length);
332
dst.put (buffer, 0, result);
337
public int read (ByteBuffer dst, long position)
341
throw new IllegalArgumentException ();
342
long oldPosition = implPosition ();
344
int result = read(dst);
345
position (oldPosition);
350
public int read () throws IOException
353
throw new IOException("Invalid FileChannelImpl");
357
if(false) throw new cli.System.IO.IOException();
358
return stream.ReadByte();
360
catch(cli.System.IO.IOException x)
362
throw new IOException(x.getMessage());
364
// TODO map al the other exceptions as well...
367
public int read (byte[] buf, int offset, int len) throws IOException
370
throw new IOException("Invalid FileChannelImpl");
375
if ((offset < 0) || (offset > buf.length))
376
throw new IllegalArgumentException("Offset invalid: " + offset);
378
if ((len < 0) || (len > (buf.length - offset)))
379
throw new IllegalArgumentException("Length invalid: " + len);
383
if(false) throw new cli.System.IO.IOException();
384
int count = stream.Read(ByteArrayHack.cast(buf), offset, len);
391
catch(cli.System.IO.IOException x)
393
throw new IOException(x.getMessage());
395
// TODO map al the other exceptions as well...
398
public long read (ByteBuffer[] dsts, int offset, int length)
403
for (int i = offset; i < offset + length; i++)
405
result += read (dsts [i]);
411
public int write (ByteBuffer src) throws IOException
413
int len = src.remaining ();
416
byte[] buffer = src.array();
417
write(buffer, src.arrayOffset() + src.position(), len);
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);
429
public int write (ByteBuffer src, long position)
433
throw new IllegalArgumentException ();
436
throw new ClosedChannelException ();
438
if ((mode & WRITE) == 0)
439
throw new NonWritableChannelException ();
444
oldPosition = implPosition ();
452
public void write (byte[] buf, int offset, int len) throws IOException
455
throw new IOException("Invalid FileChannelImpl");
460
if ((offset < 0) || (offset > buf.length))
461
throw new IllegalArgumentException("Offset invalid: " + offset);
463
if ((len < 0) || (len > (buf.length - offset)))
464
throw new IllegalArgumentException("Length invalid: " + len);
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
473
catch(cli.System.IO.IOException x)
475
throw new IOException(x.getMessage());
477
// TODO map al the other exceptions as well...
480
public void write (int b) throws IOException
482
stream.WriteByte(CIL.box_ubyte((byte)b));
485
public long write(ByteBuffer[] srcs, int offset, int length)
490
for (int i = offset;i < offset + length;i++)
492
result += write (srcs[i]);
498
public MappedByteBuffer mapImpl (char mode, long position, int size) throws IOException
501
throw new Error("not implemented");
504
public MappedByteBuffer map (FileChannel.MapMode mode,
505
long position, long size)
509
if (mode == MapMode.READ_ONLY)
512
if ((this.mode & READ) == 0)
513
throw new NonReadableChannelException();
515
else if (mode == MapMode.READ_WRITE || mode == MapMode.PRIVATE)
517
nmode = mode == MapMode.READ_WRITE ? '+' : 'c';
518
if ((this.mode & (READ|WRITE)) != (READ|WRITE))
519
throw new NonWritableChannelException();
522
throw new IllegalArgumentException ();
524
if (position < 0 || size < 0 || size > Integer.MAX_VALUE)
525
throw new IllegalArgumentException ();
526
return mapImpl(nmode, position, (int) size);
530
* msync with the disk
532
public void force (boolean metaData) throws IOException
535
throw new ClosedChannelException ();
538
public long transferTo (long position, long count, WritableByteChannel target)
543
throw new IllegalArgumentException ();
546
throw new ClosedChannelException ();
548
if ((mode & READ) == 0)
549
throw new NonReadableChannelException ();
551
// XXX: count needs to be casted from long to int. Dataloss ?
552
ByteBuffer buffer = ByteBuffer.allocate ((int) count);
553
read (buffer, position);
555
return target.write (buffer);
558
public long transferFrom (ReadableByteChannel src, long position, long count)
563
throw new IllegalArgumentException ();
566
throw new ClosedChannelException ();
568
if ((mode & WRITE) == 0)
569
throw new NonWritableChannelException ();
571
// XXX: count needs to be casted from long to int. Dataloss ?
572
ByteBuffer buffer = ByteBuffer.allocate ((int) count);
575
return write (buffer, position);
578
public FileLock tryLock (long position, long size, boolean shared)
583
throw new IllegalArgumentException ();
586
throw new ClosedChannelException ();
588
if (shared && (mode & READ) == 0)
589
throw new NonReadableChannelException ();
591
if (!shared && (mode & WRITE) == 0)
592
throw new NonWritableChannelException ();
594
boolean completed = false;
599
lock(position, size, shared, true);
601
return new FileLockImpl(this, position, size, shared);
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.
614
private boolean lock(long position, long size, boolean shared, boolean wait) throws IOException
617
throw new IOException("Invalid FileChannelImpl");
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);
627
catch(ClassCastException c)
629
throw new IOException("Locking not supported");
631
catch(cli.System.ArgumentOutOfRangeException x1)
633
throw new IOException(x1.getMessage());
635
catch(cli.System.IO.IOException x)
637
throw new IOException(x.getMessage());
639
// TODO map al the other exceptions as well...
642
public FileLock lock (long position, long size, boolean shared)
647
throw new IllegalArgumentException ();
650
throw new ClosedChannelException ();
652
boolean completed = false;
656
boolean lockable = lock(position, size, shared, false);
659
? new FileLockImpl(this, position, size, shared)
668
public long position ()
672
throw new ClosedChannelException ();
674
return implPosition ();
677
public FileChannel position (long newPosition)
681
throw new IllegalArgumentException ();
684
throw new ClosedChannelException ();
686
// FIXME note semantics if seeking beyond eof.
687
// We should seek lazily - only on a write.
692
public FileChannel truncate (long size)
696
throw new IllegalArgumentException ();
699
throw new ClosedChannelException ();
701
if ((mode & WRITE) == 0)
702
throw new NonWritableChannelException ();