1 /* FileChannelImpl.java --
2 Copyright (C) 2002, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, 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;
45 import java.io.FileNotFoundException;
46 import java.io.IOException;
47 import java.nio.ByteBuffer;
48 import java.nio.MappedByteBuffer;
49 import java.nio.channels.ClosedChannelException;
50 import java.nio.channels.FileChannel;
51 import java.nio.channels.FileLock;
52 import java.nio.channels.NonReadableChannelException;
53 import java.nio.channels.NonWritableChannelException;
54 import java.nio.channels.ReadableByteChannel;
55 import java.nio.channels.WritableByteChannel;
58 * This file is not user visible !
59 * But alas, Java does not have a concept of friendly packages
60 * so this class is public.
61 * Instances of this class are created by invoking getChannel
62 * Upon a Input/Output/RandomAccessFile object.
64 public final class FileChannelImpl extends FileChannel
66 // These are mode values for open().
67 public static final int READ = 1;
68 public static final int WRITE = 2;
69 public static final int APPEND = 4;
71 // EXCL is used only when making a temp file.
72 public static final int EXCL = 8;
73 public static final int SYNC = 16;
74 public static final int DSYNC = 32;
76 private static native void init();
80 if (Configuration.INIT_LOAD_LIBRARY)
82 System.loadLibrary("javanio");
89 * This is the actual native file descriptor value
91 // System's notion of file descriptor. It might seem redundant to
92 // initialize this given that it is reassigned in the constructors.
93 // However, this is necessary because if open() throws an exception
94 // we want to make sure this has the value -1. This is the most
95 // efficient way to accomplish that.
101 public FileChannelImpl ()
105 /* Open a file. MODE is a combination of the above mode flags. */
106 /* This is a static factory method, so that VM implementors can decide
107 * substitute subclasses of FileChannelImpl. */
108 public static FileChannelImpl create(File file, int mode)
109 throws FileNotFoundException
111 return new FileChannelImpl(file, mode);
114 /* Open a file. MODE is a combination of the above mode flags. */
115 private FileChannelImpl (File file, int mode) throws FileNotFoundException
117 final String path = file.getPath();
118 fd = open (path, mode);
121 // First open the file and then check if it is a a directory
122 // to avoid race condition.
123 if (file.isDirectory())
129 catch (IOException e)
134 throw new FileNotFoundException(path + " is a directory");
138 /* Used by init() (native code) */
139 FileChannelImpl (int fd, int mode)
145 public static FileChannelImpl in;
146 public static FileChannelImpl out;
147 public static FileChannelImpl err;
149 private native int open (String path, int mode) throws FileNotFoundException;
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;
156 public native void unlock (long pos, long len) throws IOException;
158 public native long size () throws IOException;
160 protected native void implCloseChannel() throws IOException;
163 * Makes sure the Channel is properly closed.
165 protected void finalize() throws IOException
170 public int read (ByteBuffer dst) throws IOException
173 byte[] buffer = new byte [dst.remaining ()];
175 result = read (buffer, 0, buffer.length);
178 dst.put (buffer, 0, result);
183 public int read (ByteBuffer dst, long position)
187 throw new IllegalArgumentException ();
188 long oldPosition = implPosition ();
190 int result = read(dst);
191 position (oldPosition);
196 public native int read ()
199 public native int read (byte[] buffer, int offset, int length)
202 public long read (ByteBuffer[] dsts, int offset, int length)
207 for (int i = offset; i < offset + length; i++)
209 result += read (dsts [i]);
215 public int write (ByteBuffer src) throws IOException
217 int len = src.remaining ();
220 byte[] buffer = src.array();
221 write(buffer, src.arrayOffset() + src.position(), len);
222 src.position(src.position() + len);
226 // Use a more efficient native method! FIXME!
227 byte[] buffer = new byte [len];
228 src.get (buffer, 0, len);
229 write (buffer, 0, len);
234 public int write (ByteBuffer src, long position)
238 throw new IllegalArgumentException ();
241 throw new ClosedChannelException ();
243 if ((mode & WRITE) == 0)
244 throw new NonWritableChannelException ();
249 oldPosition = implPosition ();
257 public native void write (byte[] buffer, int offset, int length)
260 public native void write (int b) throws IOException;
262 public long write(ByteBuffer[] srcs, int offset, int length)
267 for (int i = offset;i < offset + length;i++)
269 result += write (srcs[i]);
275 public native MappedByteBuffer mapImpl (char mode, long position, int size)
278 public MappedByteBuffer map (FileChannel.MapMode mode,
279 long position, long size)
283 if (mode == MapMode.READ_ONLY)
286 if ((this.mode & READ) == 0)
287 throw new NonReadableChannelException();
289 else if (mode == MapMode.READ_WRITE || mode == MapMode.PRIVATE)
291 nmode = mode == MapMode.READ_WRITE ? '+' : 'c';
292 if ((this.mode & (READ|WRITE)) != (READ|WRITE))
293 throw new NonWritableChannelException();
296 throw new IllegalArgumentException ();
298 if (position < 0 || size < 0 || size > Integer.MAX_VALUE)
299 throw new IllegalArgumentException ();
300 return mapImpl(nmode, position, (int) size);
304 * msync with the disk
306 public void force (boolean metaData) throws IOException
309 throw new ClosedChannelException ();
312 // like transferTo, but with a count of less than 2Gbytes
313 private int smallTransferTo (long position, int count,
314 WritableByteChannel target)
320 // Try to use a mapped buffer if we can. If this fails for
321 // any reason we'll fall back to using a ByteBuffer.
322 buffer = map (MapMode.READ_ONLY, position, count);
324 catch (IOException e)
326 buffer = ByteBuffer.allocate (count);
327 read (buffer, position);
331 return target.write (buffer);
334 public long transferTo (long position, long count,
335 WritableByteChannel target)
340 throw new IllegalArgumentException ();
343 throw new ClosedChannelException ();
345 if ((mode & READ) == 0)
346 throw new NonReadableChannelException ();
348 final int pageSize = 65536;
354 = smallTransferTo (position, (int)Math.min (count, pageSize),
358 total += transferred;
359 position += transferred;
360 count -= transferred;
366 // like transferFrom, but with a count of less than 2Gbytes
367 private int smallTransferFrom (ReadableByteChannel src, long position,
371 ByteBuffer buffer = null;
373 if (src instanceof FileChannel)
377 // Try to use a mapped buffer if we can. If this fails
378 // for any reason we'll fall back to using a ByteBuffer.
379 buffer = ((FileChannel)src).map (MapMode.READ_ONLY, position,
382 catch (IOException e)
389 buffer = ByteBuffer.allocate ((int) count);
394 return write (buffer, position);
397 public long transferFrom (ReadableByteChannel src, long position,
403 throw new IllegalArgumentException ();
406 throw new ClosedChannelException ();
408 if ((mode & WRITE) == 0)
409 throw new NonWritableChannelException ();
411 final int pageSize = 65536;
416 int transferred = smallTransferFrom (src, position,
417 (int)Math.min (count, pageSize));
420 total += transferred;
421 position += transferred;
422 count -= transferred;
428 public FileLock tryLock (long position, long size, boolean shared)
433 throw new IllegalArgumentException ();
436 throw new ClosedChannelException ();
438 if (shared && (mode & READ) == 0)
439 throw new NonReadableChannelException ();
441 if (!shared && (mode & WRITE) == 0)
442 throw new NonWritableChannelException ();
444 boolean completed = false;
449 boolean lockable = lock(position, size, shared, false);
452 ? new FileLockImpl(this, position, size, shared)
461 /** Try to acquire a lock at the given position and size.
462 * On success return true.
463 * If wait as specified, block until we can get it.
464 * Otherwise return false.
466 private native boolean lock(long position, long size,
467 boolean shared, boolean wait) throws IOException;
469 public FileLock lock (long position, long size, boolean shared)
474 throw new IllegalArgumentException ();
477 throw new ClosedChannelException ();
479 boolean completed = false;
483 boolean lockable = lock(position, size, shared, true);
486 ? new FileLockImpl(this, position, size, shared)
495 public long position ()
499 throw new ClosedChannelException ();
501 return implPosition ();
504 public FileChannel position (long newPosition)
508 throw new IllegalArgumentException ();
511 throw new ClosedChannelException ();
513 // FIXME note semantics if seeking beyond eof.
514 // We should seek lazily - only on a write.
519 public FileChannel truncate (long size)
523 throw new IllegalArgumentException ();
526 throw new ClosedChannelException ();
528 if ((mode & WRITE) == 0)
529 throw new NonWritableChannelException ();
538 * @return The native file descriptor.
540 public int getNativeFD()