001/* FileOutputStream.java -- Writes to a file on disk.
002   Copyright (C) 1998, 2001, 2003, 2004, 2005  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.io;
040
041import gnu.java.nio.FileChannelImpl;
042
043import java.nio.ByteBuffer;
044import java.nio.channels.FileChannel;
045
046/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
047 * "The Java Language Specification", ISBN 0-201-63451-1
048 * Status:  Complete to version 1.1.
049 */
050
051/**
052 * This classes allows a stream of data to be written to a disk file or
053 * any open <code>FileDescriptor</code>.
054 *
055 * @author Aaron M. Renn (arenn@urbanophile.com)
056 * @author Tom Tromey (tromey@cygnus.com)
057 */
058public class FileOutputStream extends OutputStream
059{
060  private FileDescriptor fd;
061
062  private final FileChannelImpl ch;
063
064  /**
065   * This method initializes a <code>FileOutputStream</code> object to write
066   * to the named file.  The file is created if it does not exist, and
067   * the bytes written are written starting at the beginning of the file if
068   * the <code>append</code> argument is <code>false</code> or at the end
069   * of the file if the <code>append</code> argument is true.
070   * <p>
071   * Before opening a file, a security check is performed by calling the
072   * <code>checkWrite</code> method of the <code>SecurityManager</code> (if
073   * one exists) with the name of the file to be opened.  An exception is
074   * thrown if writing is not allowed.
075   *
076   * @param path The name of the file this stream should write to
077   * @param append <code>true</code> to append bytes to the end of the file,
078   * or <code>false</code> to write bytes to the beginning
079   *
080   * @exception SecurityException If write access to the file is not allowed
081   * @exception FileNotFoundException If a non-security error occurs
082   */
083  public FileOutputStream (String path, boolean append)
084    throws SecurityException, FileNotFoundException
085  {
086    this (new File(path), append);
087  }
088
089  /**
090   * This method initializes a <code>FileOutputStream</code> object to write
091   * to the named file.  The file is created if it does not exist, and
092   * the bytes written are written starting at the beginning of the file.
093   * <p>
094   * Before opening a file, a security check is performed by calling the
095   * <code>checkWrite</code> method of the <code>SecurityManager</code> (if
096   * one exists) with the name of the file to be opened.  An exception is
097   * thrown if writing is not allowed.
098   *
099   * @param path The name of the file this stream should write to
100   *
101   * @exception SecurityException If write access to the file is not allowed
102   * @exception FileNotFoundException If a non-security error occurs
103   */
104  public FileOutputStream (String path)
105    throws SecurityException, FileNotFoundException
106  {
107    this (path, false);
108  }
109
110  /**
111   * This method initializes a <code>FileOutputStream</code> object to write
112   * to the specified <code>File</code> object.  The file is created if it
113   * does not exist, and the bytes written are written starting at the
114   * beginning of the file.
115   * <p>
116   * Before opening a file, a security check is performed by calling the
117   * <code>checkWrite</code> method of the <code>SecurityManager</code> (if
118   * one exists) with the name of the file to be opened.  An exception is
119   * thrown if writing is not allowed.
120   *
121   * @param file The <code>File</code> object this stream should write to
122   *
123   * @exception SecurityException If write access to the file is not allowed
124   * @exception FileNotFoundException If a non-security error occurs
125   */
126  public FileOutputStream (File file)
127    throws SecurityException, FileNotFoundException
128  {
129    this (file, false);
130  }
131
132  /**
133   * This method initializes a <code>FileOutputStream</code> object to write
134   * to the specified <code>File</code> object.  The file is created if it
135   * does not exist, and the bytes written are written starting at the
136   * beginning of the file if the <code>append</code> parameter is
137   * <code>false</code>.  Otherwise bytes are written at the end of the
138   * file.
139   * <p>
140   * Before opening a file, a security check is performed by calling the
141   * <code>checkWrite</code> method of the <code>SecurityManager</code> (if
142   * one exists) with the name of the file to be opened.  An exception is
143   * thrown if writing is not allowed.
144   *
145   * @param file The <code>File</code> object this stream should write to
146   * @param append <code>true</code> to append bytes to the end of the file,
147   * or <code>false</code> to write bytes to the beginning
148   *
149   * @exception SecurityException If write access to the file is not allowed
150   * @exception FileNotFoundException If a non-security error occurs
151   */
152  public FileOutputStream (File file, boolean append)
153    throws FileNotFoundException
154  {
155    SecurityManager s = System.getSecurityManager();
156    if (s != null)
157      s.checkWrite(file.getPath());
158
159    try
160      {
161        ch = FileChannelImpl.create(file, (append
162            ? FileChannelImpl.WRITE
163            | FileChannelImpl.APPEND
164            : FileChannelImpl.WRITE));
165      }
166    catch (FileNotFoundException fnfe)
167      {
168        throw fnfe;
169      }
170    catch (IOException ioe)
171      {
172        FileNotFoundException fnfe = new FileNotFoundException(file.getPath());
173        fnfe.initCause(ioe);
174        throw fnfe;
175      }
176  }
177
178  /**
179   * This method initializes a <code>FileOutputStream</code> object to write
180   * to the file represented by the specified <code>FileDescriptor</code>
181   * object.  This method does not create any underlying disk file or
182   * reposition the file pointer of the given descriptor.  It assumes that
183   * this descriptor is ready for writing as is.
184   * <p>
185   * Before opening a file, a security check is performed by calling the
186   * <code>checkWrite</code> method of the <code>SecurityManager</code> (if
187   * one exists) with the specified <code>FileDescriptor</code> as an argument.
188   * An exception is thrown if writing is not allowed.
189   *
190   * @param fdObj The <code>FileDescriptor</code> this stream should write to
191   *
192   * @exception SecurityException If write access to the file is not allowed
193   */
194  public FileOutputStream (FileDescriptor fdObj)
195    throws SecurityException
196  {
197    // Hmm, no other exception but this one to throw, but if the descriptor
198    // isn't valid, we surely don't have "permission" to write to it.
199    if (!fdObj.valid())
200      throw new SecurityException("Invalid FileDescriptor");
201
202    SecurityManager s = System.getSecurityManager();
203    if (s != null)
204      s.checkWrite(fdObj);
205
206    fd = fdObj;
207    ch = (FileChannelImpl) fdObj.channel;
208  }
209
210  FileOutputStream(FileChannelImpl ch)
211  {
212    this.ch = ch;
213  }
214
215  protected void finalize () throws IOException
216  {
217    // We don't actually need this, but we include it because it is
218    // mentioned in the JCL.
219  }
220
221  /**
222   * This method returns a <code>FileDescriptor</code> object representing
223   * the file that is currently being written to
224   *
225   * @return A <code>FileDescriptor</code> object for this stream
226   *
227   * @exception IOException If an error occurs
228   */
229  public final FileDescriptor getFD () throws IOException
230  {
231    synchronized (this)
232      {
233        if (fd == null)
234          fd = new FileDescriptor (ch);
235        return fd;
236      }
237  }
238
239  /**
240   * This method writes a single byte of data to the file.
241   *
242   * @param b The byte of data to write, passed as an <code>int</code>
243   *
244   * @exception IOException If an error occurs
245   */
246  public void write (int b) throws IOException
247  {
248    ch.write (b);
249  }
250
251  /**
252   * This method writes all the bytes in the specified array to the
253   * file.
254   *
255   * @param buf The array of bytes to write to the file
256   *
257   * @exception IOException If an error occurs
258   */
259  public void write (byte[] buf)
260    throws IOException
261  {
262    write (buf, 0, buf.length);
263  }
264
265  /**
266   * This method writes <code>len</code> bytes from the byte array
267   * <code>buf</code> to the file starting at index <code>offset</code>.
268   *
269   * @param buf The array of bytes to write to the file
270   * @param offset The offset into the array to start writing bytes from
271   * @param len The number of bytes to write to the file
272   *
273   * @exception IOException If an error occurs
274   */
275  public void write (byte[] buf, int offset, int len)
276    throws IOException
277  {
278    if (offset < 0
279        || len < 0
280        || offset + len > buf.length)
281      throw new ArrayIndexOutOfBoundsException ();
282
283    ch.write(ByteBuffer.wrap(buf, offset, len));
284  }
285
286  /**
287   * This method closes the underlying file.  Any further attempts to
288   * write to this stream will likely generate an exception since the
289   * file is closed.
290   *
291   * @exception IOException If an error occurs
292   */
293  public void close () throws IOException
294  {
295    ch.close();
296  }
297
298  /**
299   * This method creates a java.nio.channels.FileChannel.
300   * Nio does not allow one to create a file channel directly.
301   * A file channel must be created by first creating an instance of
302   * Input/Output/RandomAccessFile and invoking the getChannel() method on it.
303   */
304  public synchronized FileChannel getChannel()
305  {
306    return ch;
307  }
308
309} // class FileOutputStream