Merge from the pain train
[official-gcc.git] / libjava / gnu / java / nio / channels / FileChannelImpl.java
blob887d1dcc3961e2a008ceb3ddd7beabdc31875e43
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)
9 any later version.
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
19 02111-1307 USA.
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.
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 /**
57 * This file is not user visible !
58 * But alas, Java does not have a concept of friendly packages
59 * so this class is public.
60 * Instances of this class are created by invoking getChannel
61 * Upon a Input/Output/RandomAccessFile object.
63 public final class FileChannelImpl extends FileChannel
65 // These are mode values for open().
66 public static final int READ = 1;
67 public static final int WRITE = 2;
68 public static final int APPEND = 4;
70 // EXCL is used only when making a temp file.
71 public static final int EXCL = 8;
72 public static final int SYNC = 16;
73 public static final int DSYNC = 32;
75 private static native void init();
77 static
79 if (Configuration.INIT_LOAD_LIBRARY)
81 System.loadLibrary("javanio");
84 init();
87 /**
88 * This is the actual native file descriptor value
90 // System's notion of file descriptor. It might seem redundant to
91 // initialize this given that it is reassigned in the constructors.
92 // However, this is necessary because if open() throws an exception
93 // we want to make sure this has the value -1. This is the most
94 // efficient way to accomplish that.
95 private int fd = -1;
97 private long pos;
98 private int mode;
100 public FileChannelImpl ()
104 /* Open a file. MODE is a combination of the above mode flags. */
105 public FileChannelImpl (String path, int mode) throws FileNotFoundException
107 fd = open (path, mode);
108 this.mode = mode;
111 /* Used by init() (native code) */
112 FileChannelImpl (int fd, int mode)
114 this.fd = fd;
115 this.mode = mode;
118 public static FileChannelImpl in;
119 public static FileChannelImpl out;
120 public static FileChannelImpl err;
122 private native int open (String path, int mode) throws FileNotFoundException;
124 public native int available () throws IOException;
125 private native long implPosition () throws IOException;
126 private native void seek (long newPosition) throws IOException;
127 private native void implTruncate (long size) throws IOException;
129 public native void unlock (long pos, long len) throws IOException;
131 public native long size () throws IOException;
133 protected native void implCloseChannel() throws IOException;
136 * Makes sure the Channel is properly closed.
138 protected void finalize() throws IOException
140 this.close();
143 public int read (ByteBuffer dst) throws IOException
145 int result;
146 byte[] buffer = new byte [dst.remaining ()];
148 result = read (buffer, 0, buffer.length);
150 if (result > 0)
151 dst.put (buffer, 0, result);
153 return result;
156 public int read (ByteBuffer dst, long position)
157 throws IOException
159 if (position < 0)
160 throw new IllegalArgumentException ();
161 long oldPosition = implPosition ();
162 position (position);
163 int result = read(dst);
164 position (oldPosition);
166 return result;
169 public native int read ()
170 throws IOException;
172 public native int read (byte[] buffer, int offset, int length)
173 throws IOException;
175 public long read (ByteBuffer[] dsts, int offset, int length)
176 throws IOException
178 long result = 0;
180 for (int i = offset; i < offset + length; i++)
182 result += read (dsts [i]);
185 return result;
188 public int write (ByteBuffer src) throws IOException
190 int len = src.remaining ();
191 if (src.hasArray())
193 byte[] buffer = src.array();
194 write(buffer, src.arrayOffset() + src.position(), len);
195 src.position(src.position() + len);
197 else
199 // Use a more efficient native method! FIXME!
200 byte[] buffer = new byte [len];
201 src.get (buffer, 0, len);
202 write (buffer, 0, len);
204 return len;
207 public int write (ByteBuffer src, long position)
208 throws IOException
210 if (position < 0)
211 throw new IllegalArgumentException ();
213 if (!isOpen ())
214 throw new ClosedChannelException ();
216 if ((mode & WRITE) == 0)
217 throw new NonWritableChannelException ();
219 int result;
220 long oldPosition;
222 oldPosition = implPosition ();
223 seek (position);
224 result = write(src);
225 seek (oldPosition);
227 return result;
230 public native void write (byte[] buffer, int offset, int length)
231 throws IOException;
233 public native void write (int b) throws IOException;
235 public long write(ByteBuffer[] srcs, int offset, int length)
236 throws IOException
238 long result = 0;
240 for (int i = offset;i < offset + length;i++)
242 result += write (srcs[i]);
245 return result;
248 public native MappedByteBuffer mapImpl (char mode, long position, int size)
249 throws IOException;
251 public MappedByteBuffer map (FileChannel.MapMode mode,
252 long position, long size)
253 throws IOException
255 char nmode = 0;
256 if (mode == MapMode.READ_ONLY)
258 nmode = 'r';
259 if ((this.mode & READ) == 0)
260 throw new NonReadableChannelException();
262 else if (mode == MapMode.READ_WRITE || mode == MapMode.PRIVATE)
264 nmode = mode == MapMode.READ_WRITE ? '+' : 'c';
265 if ((this.mode & (READ|WRITE)) != (READ|WRITE))
266 throw new NonWritableChannelException();
268 else
269 throw new IllegalArgumentException ();
271 if (position < 0 || size < 0 || size > Integer.MAX_VALUE)
272 throw new IllegalArgumentException ();
273 return mapImpl(nmode, position, (int) size);
277 * msync with the disk
279 public void force (boolean metaData) throws IOException
281 if (!isOpen ())
282 throw new ClosedChannelException ();
285 public long transferTo (long position, long count, WritableByteChannel target)
286 throws IOException
288 if (position < 0
289 || count < 0)
290 throw new IllegalArgumentException ();
292 if (!isOpen ())
293 throw new ClosedChannelException ();
295 if ((mode & READ) == 0)
296 throw new NonReadableChannelException ();
298 // XXX: count needs to be casted from long to int. Dataloss ?
299 ByteBuffer buffer = ByteBuffer.allocate ((int) count);
300 read (buffer, position);
301 buffer.flip();
302 return target.write (buffer);
305 public long transferFrom (ReadableByteChannel src, long position, long count)
306 throws IOException
308 if (position < 0
309 || count < 0)
310 throw new IllegalArgumentException ();
312 if (!isOpen ())
313 throw new ClosedChannelException ();
315 if ((mode & WRITE) == 0)
316 throw new NonWritableChannelException ();
318 // XXX: count needs to be casted from long to int. Dataloss ?
319 ByteBuffer buffer = ByteBuffer.allocate ((int) count);
320 src.read (buffer);
321 buffer.flip();
322 return write (buffer, position);
325 public FileLock tryLock (long position, long size, boolean shared)
326 throws IOException
328 if (position < 0
329 || size < 0)
330 throw new IllegalArgumentException ();
332 if (!isOpen ())
333 throw new ClosedChannelException ();
335 if (shared && (mode & READ) == 0)
336 throw new NonReadableChannelException ();
338 if (!shared && (mode & WRITE) == 0)
339 throw new NonWritableChannelException ();
341 boolean completed = false;
345 begin();
346 lock(position, size, shared, true);
347 completed = true;
348 return new FileLockImpl(this, position, size, shared);
350 finally
352 end(completed);
356 /** Try to acquire a lock at the given position and size.
357 * On success return true.
358 * If wait as specified, block until we can get it.
359 * Otherwise return false.
361 private native boolean lock(long position, long size,
362 boolean shared, boolean wait) throws IOException;
364 public FileLock lock (long position, long size, boolean shared)
365 throws IOException
367 if (position < 0
368 || size < 0)
369 throw new IllegalArgumentException ();
371 if (!isOpen ())
372 throw new ClosedChannelException ();
374 boolean completed = false;
378 boolean lockable = lock(position, size, shared, false);
379 completed = true;
380 return (lockable
381 ? new FileLockImpl(this, position, size, shared)
382 : null);
384 finally
386 end(completed);
390 public long position ()
391 throws IOException
393 if (!isOpen ())
394 throw new ClosedChannelException ();
396 return implPosition ();
399 public FileChannel position (long newPosition)
400 throws IOException
402 if (newPosition < 0)
403 throw new IllegalArgumentException ();
405 if (!isOpen ())
406 throw new ClosedChannelException ();
408 // FIXME note semantics if seeking beyond eof.
409 // We should seek lazily - only on a write.
410 seek (newPosition);
411 return this;
414 public FileChannel truncate (long size)
415 throws IOException
417 if (size < 0)
418 throw new IllegalArgumentException ();
420 if (!isOpen ())
421 throw new ClosedChannelException ();
423 if ((mode & WRITE) == 0)
424 throw new NonWritableChannelException ();
426 if (size < size ())
427 implTruncate (size);
429 return this;