FileChannelImpl.java [plain text]
package gnu.java.nio.channels;
import gnu.classpath.Configuration;
import gnu.java.nio.FileLockImpl;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.NonReadableChannelException;
import java.nio.channels.NonWritableChannelException;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
public final class FileChannelImpl extends FileChannel
{
public static final int READ = 1;
public static final int WRITE = 2;
public static final int APPEND = 4;
public static final int EXCL = 8;
public static final int SYNC = 16;
public static final int DSYNC = 32;
private static native void init();
static
{
if (Configuration.INIT_LOAD_LIBRARY)
{
System.loadLibrary("javanio");
}
init();
}
private int fd = -1;
private long pos;
private int mode;
public FileChannelImpl ()
{
}
public FileChannelImpl (String path, int mode) throws FileNotFoundException
{
fd = open (path, mode);
this.mode = mode;
}
FileChannelImpl (int fd, int mode)
{
this.fd = fd;
this.mode = mode;
}
public static FileChannelImpl in;
public static FileChannelImpl out;
public static FileChannelImpl err;
private native int open (String path, int mode) throws FileNotFoundException;
public native int available () throws IOException;
private native long implPosition () throws IOException;
private native void seek (long newPosition) throws IOException;
private native void implTruncate (long size) throws IOException;
public native void unlock (long pos, long len) throws IOException;
public native long size () throws IOException;
protected native void implCloseChannel() throws IOException;
protected void finalize() throws IOException
{
this.close();
}
public int read (ByteBuffer dst) throws IOException
{
int result;
byte[] buffer = new byte [dst.remaining ()];
result = read (buffer, 0, buffer.length);
if (result > 0)
dst.put (buffer, 0, result);
return result;
}
public int read (ByteBuffer dst, long position)
throws IOException
{
if (position < 0)
throw new IllegalArgumentException ();
long oldPosition = implPosition ();
position (position);
int result = read(dst);
position (oldPosition);
return result;
}
public native int read ()
throws IOException;
public native int read (byte[] buffer, int offset, int length)
throws IOException;
public long read (ByteBuffer[] dsts, int offset, int length)
throws IOException
{
long result = 0;
for (int i = offset; i < offset + length; i++)
{
result += read (dsts [i]);
}
return result;
}
public int write (ByteBuffer src) throws IOException
{
int len = src.remaining ();
if (src.hasArray())
{
byte[] buffer = src.array();
write(buffer, src.arrayOffset() + src.position(), len);
src.position(src.position() + len);
}
else
{
byte[] buffer = new byte [len];
src.get (buffer, 0, len);
write (buffer, 0, len);
}
return len;
}
public int write (ByteBuffer src, long position)
throws IOException
{
if (position < 0)
throw new IllegalArgumentException ();
if (!isOpen ())
throw new ClosedChannelException ();
if ((mode & WRITE) == 0)
throw new NonWritableChannelException ();
int result;
long oldPosition;
oldPosition = implPosition ();
seek (position);
result = write(src);
seek (oldPosition);
return result;
}
public native void write (byte[] buffer, int offset, int length)
throws IOException;
public native void write (int b) throws IOException;
public long write(ByteBuffer[] srcs, int offset, int length)
throws IOException
{
long result = 0;
for (int i = offset;i < offset + length;i++)
{
result += write (srcs[i]);
}
return result;
}
public native MappedByteBuffer mapImpl (char mode, long position, int size)
throws IOException;
public MappedByteBuffer map (FileChannel.MapMode mode,
long position, long size)
throws IOException
{
char nmode = 0;
if (mode == MapMode.READ_ONLY)
{
nmode = 'r';
if ((this.mode & READ) == 0)
throw new NonReadableChannelException();
}
else if (mode == MapMode.READ_WRITE || mode == MapMode.PRIVATE)
{
nmode = mode == MapMode.READ_WRITE ? '+' : 'c';
if ((this.mode & (READ|WRITE)) != (READ|WRITE))
throw new NonWritableChannelException();
}
else
throw new IllegalArgumentException ();
if (position < 0 || size < 0 || size > Integer.MAX_VALUE)
throw new IllegalArgumentException ();
return mapImpl(nmode, position, (int) size);
}
public void force (boolean metaData) throws IOException
{
if (!isOpen ())
throw new ClosedChannelException ();
}
private int smallTransferTo (long position, int count,
WritableByteChannel target)
throws IOException
{
ByteBuffer buffer;
try
{
buffer = map (MapMode.READ_ONLY, position, count);
}
catch (IOException e)
{
buffer = ByteBuffer.allocate (count);
read (buffer, position);
buffer.flip();
}
return target.write (buffer);
}
public long transferTo (long position, long count,
WritableByteChannel target)
throws IOException
{
if (position < 0
|| count < 0)
throw new IllegalArgumentException ();
if (!isOpen ())
throw new ClosedChannelException ();
if ((mode & READ) == 0)
throw new NonReadableChannelException ();
final int pageSize = 65536;
long total = 0;
while (count > 0)
{
int transferred
= smallTransferTo (position, (int)Math.min (count, pageSize),
target);
if (transferred < 0)
break;
total += transferred;
position += transferred;
count -= transferred;
}
return total;
}
private int smallTransferFrom (ReadableByteChannel src, long position,
int count)
throws IOException
{
ByteBuffer buffer = null;
if (src instanceof FileChannel)
{
try
{
buffer = ((FileChannel)src).map (MapMode.READ_ONLY, position,
count);
}
catch (IOException e)
{
}
}
if (buffer == null)
{
buffer = ByteBuffer.allocate ((int) count);
src.read (buffer);
buffer.flip();
}
return write (buffer, position);
}
public long transferFrom (ReadableByteChannel src, long position,
long count)
throws IOException
{
if (position < 0
|| count < 0)
throw new IllegalArgumentException ();
if (!isOpen ())
throw new ClosedChannelException ();
if ((mode & WRITE) == 0)
throw new NonWritableChannelException ();
final int pageSize = 65536;
long total = 0;
while (count > 0)
{
int transferred = smallTransferFrom (src, position,
(int)Math.min (count, pageSize));
if (transferred < 0)
break;
total += transferred;
position += transferred;
count -= transferred;
}
return total;
}
public FileLock tryLock (long position, long size, boolean shared)
throws IOException
{
if (position < 0
|| size < 0)
throw new IllegalArgumentException ();
if (!isOpen ())
throw new ClosedChannelException ();
if (shared && (mode & READ) == 0)
throw new NonReadableChannelException ();
if (!shared && (mode & WRITE) == 0)
throw new NonWritableChannelException ();
boolean completed = false;
try
{
begin();
boolean lockable = lock(position, size, shared, false);
completed = true;
return (lockable
? new FileLockImpl(this, position, size, shared)
: null);
}
finally
{
end(completed);
}
}
private native boolean lock(long position, long size,
boolean shared, boolean wait) throws IOException;
public FileLock lock (long position, long size, boolean shared)
throws IOException
{
if (position < 0
|| size < 0)
throw new IllegalArgumentException ();
if (!isOpen ())
throw new ClosedChannelException ();
boolean completed = false;
try
{
boolean lockable = lock(position, size, shared, true);
completed = true;
return (lockable
? new FileLockImpl(this, position, size, shared)
: null);
}
finally
{
end(completed);
}
}
public long position ()
throws IOException
{
if (!isOpen ())
throw new ClosedChannelException ();
return implPosition ();
}
public FileChannel position (long newPosition)
throws IOException
{
if (newPosition < 0)
throw new IllegalArgumentException ();
if (!isOpen ())
throw new ClosedChannelException ();
seek (newPosition);
return this;
}
public FileChannel truncate (long size)
throws IOException
{
if (size < 0)
throw new IllegalArgumentException ();
if (!isOpen ())
throw new ClosedChannelException ();
if ((mode & WRITE) == 0)
throw new NonWritableChannelException ();
if (size < size ())
implTruncate (size);
return this;
}
}