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