1 /* FileChannelImpl.java --
2 Copyright (C) 2002, 2004, 2005 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 public FileChannelImpl (File file
, int mode
) throws FileNotFoundException
108 final String path
= file
.getPath();
109 fd
= open (path
, mode
);
112 // First open the file and then check if it is a a directory
113 // to avoid race condition.
114 if (file
.isDirectory())
120 catch (IOException e
)
125 throw new FileNotFoundException(path
+ " is a directory");
129 /* Used by init() (native code) */
130 FileChannelImpl (int fd
, int mode
)
136 public static FileChannelImpl in
;
137 public static FileChannelImpl out
;
138 public static FileChannelImpl err
;
140 private native int open (String path
, int mode
) throws FileNotFoundException
;
142 public native int available () throws IOException
;
143 private native long implPosition () throws IOException
;
144 private native void seek (long newPosition
) throws IOException
;
145 private native void implTruncate (long size
) throws IOException
;
147 public native void unlock (long pos
, long len
) throws IOException
;
149 public native long size () throws IOException
;
151 protected native void implCloseChannel() throws IOException
;
154 * Makes sure the Channel is properly closed.
156 protected void finalize() throws IOException
161 public int read (ByteBuffer dst
) throws IOException
164 byte[] buffer
= new byte [dst
.remaining ()];
166 result
= read (buffer
, 0, buffer
.length
);
169 dst
.put (buffer
, 0, result
);
174 public int read (ByteBuffer dst
, long position
)
178 throw new IllegalArgumentException ();
179 long oldPosition
= implPosition ();
181 int result
= read(dst
);
182 position (oldPosition
);
187 public native int read ()
190 public native int read (byte[] buffer
, int offset
, int length
)
193 public long read (ByteBuffer
[] dsts
, int offset
, int length
)
198 for (int i
= offset
; i
< offset
+ length
; i
++)
200 result
+= read (dsts
[i
]);
206 public int write (ByteBuffer src
) throws IOException
208 int len
= src
.remaining ();
211 byte[] buffer
= src
.array();
212 write(buffer
, src
.arrayOffset() + src
.position(), len
);
213 src
.position(src
.position() + len
);
217 // Use a more efficient native method! FIXME!
218 byte[] buffer
= new byte [len
];
219 src
.get (buffer
, 0, len
);
220 write (buffer
, 0, len
);
225 public int write (ByteBuffer src
, long position
)
229 throw new IllegalArgumentException ();
232 throw new ClosedChannelException ();
234 if ((mode
& WRITE
) == 0)
235 throw new NonWritableChannelException ();
240 oldPosition
= implPosition ();
248 public native void write (byte[] buffer
, int offset
, int length
)
251 public native void write (int b
) throws IOException
;
253 public long write(ByteBuffer
[] srcs
, int offset
, int length
)
258 for (int i
= offset
;i
< offset
+ length
;i
++)
260 result
+= write (srcs
[i
]);
266 public native MappedByteBuffer
mapImpl (char mode
, long position
, int size
)
269 public MappedByteBuffer
map (FileChannel
.MapMode mode
,
270 long position
, long size
)
274 if (mode
== MapMode
.READ_ONLY
)
277 if ((this.mode
& READ
) == 0)
278 throw new NonReadableChannelException();
280 else if (mode
== MapMode
.READ_WRITE
|| mode
== MapMode
.PRIVATE
)
282 nmode
= mode
== MapMode
.READ_WRITE ?
'+' : 'c';
283 if ((this.mode
& (READ
|WRITE
)) != (READ
|WRITE
))
284 throw new NonWritableChannelException();
287 throw new IllegalArgumentException ();
289 if (position
< 0 || size
< 0 || size
> Integer
.MAX_VALUE
)
290 throw new IllegalArgumentException ();
291 return mapImpl(nmode
, position
, (int) size
);
295 * msync with the disk
297 public void force (boolean metaData
) throws IOException
300 throw new ClosedChannelException ();
303 // like transferTo, but with a count of less than 2Gbytes
304 private int smallTransferTo (long position
, int count
,
305 WritableByteChannel target
)
311 // Try to use a mapped buffer if we can. If this fails for
312 // any reason we'll fall back to using a ByteBuffer.
313 buffer
= map (MapMode
.READ_ONLY
, position
, count
);
315 catch (IOException e
)
317 buffer
= ByteBuffer
.allocate (count
);
318 read (buffer
, position
);
322 return target
.write (buffer
);
325 public long transferTo (long position
, long count
,
326 WritableByteChannel target
)
331 throw new IllegalArgumentException ();
334 throw new ClosedChannelException ();
336 if ((mode
& READ
) == 0)
337 throw new NonReadableChannelException ();
339 final int pageSize
= 65536;
345 = smallTransferTo (position
, (int)Math
.min (count
, pageSize
),
349 total
+= transferred
;
350 position
+= transferred
;
351 count
-= transferred
;
357 // like transferFrom, but with a count of less than 2Gbytes
358 private int smallTransferFrom (ReadableByteChannel src
, long position
,
362 ByteBuffer buffer
= null;
364 if (src
instanceof FileChannel
)
368 // Try to use a mapped buffer if we can. If this fails
369 // for any reason we'll fall back to using a ByteBuffer.
370 buffer
= ((FileChannel
)src
).map (MapMode
.READ_ONLY
, position
,
373 catch (IOException e
)
380 buffer
= ByteBuffer
.allocate ((int) count
);
385 return write (buffer
, position
);
388 public long transferFrom (ReadableByteChannel src
, long position
,
394 throw new IllegalArgumentException ();
397 throw new ClosedChannelException ();
399 if ((mode
& WRITE
) == 0)
400 throw new NonWritableChannelException ();
402 final int pageSize
= 65536;
407 int transferred
= smallTransferFrom (src
, position
,
408 (int)Math
.min (count
, pageSize
));
411 total
+= transferred
;
412 position
+= transferred
;
413 count
-= transferred
;
419 public FileLock
tryLock (long position
, long size
, boolean shared
)
424 throw new IllegalArgumentException ();
427 throw new ClosedChannelException ();
429 if (shared
&& (mode
& READ
) == 0)
430 throw new NonReadableChannelException ();
432 if (!shared
&& (mode
& WRITE
) == 0)
433 throw new NonWritableChannelException ();
435 boolean completed
= false;
440 boolean lockable
= lock(position
, size
, shared
, false);
443 ?
new FileLockImpl(this, position
, size
, shared
)
452 /** Try to acquire a lock at the given position and size.
453 * On success return true.
454 * If wait as specified, block until we can get it.
455 * Otherwise return false.
457 private native boolean lock(long position
, long size
,
458 boolean shared
, boolean wait
) throws IOException
;
460 public FileLock
lock (long position
, long size
, boolean shared
)
465 throw new IllegalArgumentException ();
468 throw new ClosedChannelException ();
470 boolean completed
= false;
474 boolean lockable
= lock(position
, size
, shared
, true);
477 ?
new FileLockImpl(this, position
, size
, shared
)
486 public long position ()
490 throw new ClosedChannelException ();
492 return implPosition ();
495 public FileChannel
position (long newPosition
)
499 throw new IllegalArgumentException ();
502 throw new ClosedChannelException ();
504 // FIXME note semantics if seeking beyond eof.
505 // We should seek lazily - only on a write.
510 public FileChannel
truncate (long size
)
514 throw new IllegalArgumentException ();
517 throw new ClosedChannelException ();
519 if ((mode
& WRITE
) == 0)
520 throw new NonWritableChannelException ();