~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/openjdk/java/io/FileOutputStream.java

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
 
3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
4
 *
 
5
 * This code is free software; you can redistribute it and/or modify it
 
6
 * under the terms of the GNU General Public License version 2 only, as
 
7
 * published by the Free Software Foundation.  Oracle designates this
 
8
 * particular file as subject to the "Classpath" exception as provided
 
9
 * by Oracle in the LICENSE file that accompanied this code.
 
10
 *
 
11
 * This code is distributed in the hope that it will be useful, but WITHOUT
 
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
14
 * version 2 for more details (a copy is included in the LICENSE file that
 
15
 * accompanied this code).
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License version
 
18
 * 2 along with this work; if not, write to the Free Software Foundation,
 
19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 
20
 *
 
21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 
22
 * or visit www.oracle.com if you need additional information or have any
 
23
 * questions.
 
24
 */
 
25
 
 
26
package java.io;
 
27
 
 
28
import java.nio.channels.FileChannel;
 
29
import sun.nio.ch.FileChannelImpl;
 
30
 
 
31
 
 
32
/**
 
33
 * A file output stream is an output stream for writing data to a
 
34
 * <code>File</code> or to a <code>FileDescriptor</code>. Whether or not
 
35
 * a file is available or may be created depends upon the underlying
 
36
 * platform.  Some platforms, in particular, allow a file to be opened
 
37
 * for writing by only one <tt>FileOutputStream</tt> (or other
 
38
 * file-writing object) at a time.  In such situations the constructors in
 
39
 * this class will fail if the file involved is already open.
 
40
 *
 
41
 * <p><code>FileOutputStream</code> is meant for writing streams of raw bytes
 
42
 * such as image data. For writing streams of characters, consider using
 
43
 * <code>FileWriter</code>.
 
44
 *
 
45
 * @author  Arthur van Hoff
 
46
 * @see     java.io.File
 
47
 * @see     java.io.FileDescriptor
 
48
 * @see     java.io.FileInputStream
 
49
 * @see     java.nio.file.Files#newOutputStream
 
50
 * @since   JDK1.0
 
51
 */
 
52
public
 
53
class FileOutputStream extends OutputStream
 
54
{
 
55
    /**
 
56
     * The system dependent file descriptor.
 
57
     */
 
58
    private final FileDescriptor fd;
 
59
 
 
60
    /**
 
61
     * True if the file is opened for append.
 
62
     */
 
63
    private final boolean append;
 
64
 
 
65
    /**
 
66
     * The associated channel, initalized lazily.
 
67
     */
 
68
    private FileChannel channel;
 
69
 
 
70
    private final Object closeLock = new Object();
 
71
    private volatile boolean closed = false;
 
72
    private static final ThreadLocal<Boolean> runningFinalize =
 
73
        new ThreadLocal<>();
 
74
 
 
75
    private static boolean isRunningFinalize() {
 
76
        Boolean val;
 
77
        if ((val = runningFinalize.get()) != null)
 
78
            return val.booleanValue();
 
79
        return false;
 
80
    }
 
81
 
 
82
    /**
 
83
     * Creates a file output stream to write to the file with the
 
84
     * specified name. A new <code>FileDescriptor</code> object is
 
85
     * created to represent this file connection.
 
86
     * <p>
 
87
     * First, if there is a security manager, its <code>checkWrite</code>
 
88
     * method is called with <code>name</code> as its argument.
 
89
     * <p>
 
90
     * If the file exists but is a directory rather than a regular file, does
 
91
     * not exist but cannot be created, or cannot be opened for any other
 
92
     * reason then a <code>FileNotFoundException</code> is thrown.
 
93
     *
 
94
     * @param      name   the system-dependent filename
 
95
     * @exception  FileNotFoundException  if the file exists but is a directory
 
96
     *                   rather than a regular file, does not exist but cannot
 
97
     *                   be created, or cannot be opened for any other reason
 
98
     * @exception  SecurityException  if a security manager exists and its
 
99
     *               <code>checkWrite</code> method denies write access
 
100
     *               to the file.
 
101
     * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
 
102
     */
 
103
    public FileOutputStream(String name) throws FileNotFoundException {
 
104
        this(name != null ? new File(name) : null, false);
 
105
    }
 
106
 
 
107
    /**
 
108
     * Creates a file output stream to write to the file with the specified
 
109
     * name.  If the second argument is <code>true</code>, then
 
110
     * bytes will be written to the end of the file rather than the beginning.
 
111
     * A new <code>FileDescriptor</code> object is created to represent this
 
112
     * file connection.
 
113
     * <p>
 
114
     * First, if there is a security manager, its <code>checkWrite</code>
 
115
     * method is called with <code>name</code> as its argument.
 
116
     * <p>
 
117
     * If the file exists but is a directory rather than a regular file, does
 
118
     * not exist but cannot be created, or cannot be opened for any other
 
119
     * reason then a <code>FileNotFoundException</code> is thrown.
 
120
     *
 
121
     * @param     name        the system-dependent file name
 
122
     * @param     append      if <code>true</code>, then bytes will be written
 
123
     *                   to the end of the file rather than the beginning
 
124
     * @exception  FileNotFoundException  if the file exists but is a directory
 
125
     *                   rather than a regular file, does not exist but cannot
 
126
     *                   be created, or cannot be opened for any other reason.
 
127
     * @exception  SecurityException  if a security manager exists and its
 
128
     *               <code>checkWrite</code> method denies write access
 
129
     *               to the file.
 
130
     * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
 
131
     * @since     JDK1.1
 
132
     */
 
133
    public FileOutputStream(String name, boolean append)
 
134
        throws FileNotFoundException
 
135
    {
 
136
        this(name != null ? new File(name) : null, append);
 
137
    }
 
138
 
 
139
    /**
 
140
     * Creates a file output stream to write to the file represented by
 
141
     * the specified <code>File</code> object. A new
 
142
     * <code>FileDescriptor</code> object is created to represent this
 
143
     * file connection.
 
144
     * <p>
 
145
     * First, if there is a security manager, its <code>checkWrite</code>
 
146
     * method is called with the path represented by the <code>file</code>
 
147
     * argument as its argument.
 
148
     * <p>
 
149
     * If the file exists but is a directory rather than a regular file, does
 
150
     * not exist but cannot be created, or cannot be opened for any other
 
151
     * reason then a <code>FileNotFoundException</code> is thrown.
 
152
     *
 
153
     * @param      file               the file to be opened for writing.
 
154
     * @exception  FileNotFoundException  if the file exists but is a directory
 
155
     *                   rather than a regular file, does not exist but cannot
 
156
     *                   be created, or cannot be opened for any other reason
 
157
     * @exception  SecurityException  if a security manager exists and its
 
158
     *               <code>checkWrite</code> method denies write access
 
159
     *               to the file.
 
160
     * @see        java.io.File#getPath()
 
161
     * @see        java.lang.SecurityException
 
162
     * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
 
163
     */
 
164
    public FileOutputStream(File file) throws FileNotFoundException {
 
165
        this(file, false);
 
166
    }
 
167
 
 
168
    /**
 
169
     * Creates a file output stream to write to the file represented by
 
170
     * the specified <code>File</code> object. If the second argument is
 
171
     * <code>true</code>, then bytes will be written to the end of the file
 
172
     * rather than the beginning. A new <code>FileDescriptor</code> object is
 
173
     * created to represent this file connection.
 
174
     * <p>
 
175
     * First, if there is a security manager, its <code>checkWrite</code>
 
176
     * method is called with the path represented by the <code>file</code>
 
177
     * argument as its argument.
 
178
     * <p>
 
179
     * If the file exists but is a directory rather than a regular file, does
 
180
     * not exist but cannot be created, or cannot be opened for any other
 
181
     * reason then a <code>FileNotFoundException</code> is thrown.
 
182
     *
 
183
     * @param      file               the file to be opened for writing.
 
184
     * @param     append      if <code>true</code>, then bytes will be written
 
185
     *                   to the end of the file rather than the beginning
 
186
     * @exception  FileNotFoundException  if the file exists but is a directory
 
187
     *                   rather than a regular file, does not exist but cannot
 
188
     *                   be created, or cannot be opened for any other reason
 
189
     * @exception  SecurityException  if a security manager exists and its
 
190
     *               <code>checkWrite</code> method denies write access
 
191
     *               to the file.
 
192
     * @see        java.io.File#getPath()
 
193
     * @see        java.lang.SecurityException
 
194
     * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
 
195
     * @since 1.4
 
196
     */
 
197
    public FileOutputStream(File file, boolean append)
 
198
        throws FileNotFoundException
 
199
    {
 
200
        String name = (file != null ? file.getPath() : null);
 
201
        SecurityManager security = System.getSecurityManager();
 
202
        if (security != null) {
 
203
            security.checkWrite(name);
 
204
        }
 
205
        if (name == null) {
 
206
            throw new NullPointerException();
 
207
        }
 
208
        this.fd = new FileDescriptor();
 
209
        this.append = append;
 
210
 
 
211
        fd.incrementAndGetUseCount();
 
212
        open(name, append);
 
213
    }
 
214
 
 
215
    /**
 
216
     * Creates a file output stream to write to the specified file
 
217
     * descriptor, which represents an existing connection to an actual
 
218
     * file in the file system.
 
219
     * <p>
 
220
     * First, if there is a security manager, its <code>checkWrite</code>
 
221
     * method is called with the file descriptor <code>fdObj</code>
 
222
     * argument as its argument.
 
223
     * <p>
 
224
     * If <code>fdObj</code> is null then a <code>NullPointerException</code>
 
225
     * is thrown.
 
226
     * <p>
 
227
     * This constructor does not throw an exception if <code>fdObj</code>
 
228
     * is {@link java.io.FileDescriptor#valid() invalid}.
 
229
     * However, if the methods are invoked on the resulting stream to attempt
 
230
     * I/O on the stream, an <code>IOException</code> is thrown.
 
231
     *
 
232
     * @param      fdObj   the file descriptor to be opened for writing
 
233
     * @exception  SecurityException  if a security manager exists and its
 
234
     *               <code>checkWrite</code> method denies
 
235
     *               write access to the file descriptor
 
236
     * @see        java.lang.SecurityManager#checkWrite(java.io.FileDescriptor)
 
237
     */
 
238
    public FileOutputStream(FileDescriptor fdObj) {
 
239
        SecurityManager security = System.getSecurityManager();
 
240
        if (fdObj == null) {
 
241
            throw new NullPointerException();
 
242
        }
 
243
        if (security != null) {
 
244
            security.checkWrite(fdObj);
 
245
        }
 
246
        this.fd = fdObj;
 
247
        this.append = false;
 
248
 
 
249
        /*
 
250
         * FileDescriptor is being shared by streams.
 
251
         * Ensure that it's GC'ed only when all the streams/channels are done
 
252
         * using it.
 
253
         */
 
254
        fd.incrementAndGetUseCount();
 
255
    }
 
256
 
 
257
    /**
 
258
     * Opens a file, with the specified name, for overwriting or appending.
 
259
     * @param name name of file to be opened
 
260
     * @param append whether the file is to be opened in append mode
 
261
     */
 
262
    private void open(String name, boolean append)
 
263
        throws FileNotFoundException {
 
264
        if (append) {
 
265
            fd.openAppend(name);
 
266
        } else {
 
267
            fd.openWriteOnly(name);
 
268
        }
 
269
    }
 
270
 
 
271
    /**
 
272
     * Writes the specified byte to this file output stream.
 
273
     *
 
274
     * @param   b   the byte to be written.
 
275
     * @param   append   {@code true} if the write operation first
 
276
     *     advances the position to the end of file
 
277
     */
 
278
    private void write(int b, boolean append) throws IOException {
 
279
        fd.write(b);
 
280
    }
 
281
 
 
282
    /**
 
283
     * Writes the specified byte to this file output stream. Implements
 
284
     * the <code>write</code> method of <code>OutputStream</code>.
 
285
     *
 
286
     * @param      b   the byte to be written.
 
287
     * @exception  IOException  if an I/O error occurs.
 
288
     */
 
289
    public void write(int b) throws IOException {
 
290
        write(b, append);
 
291
    }
 
292
 
 
293
    /**
 
294
     * Writes a sub array as a sequence of bytes.
 
295
     * @param b the data to be written
 
296
     * @param off the start offset in the data
 
297
     * @param len the number of bytes that are written
 
298
     * @param append {@code true} to first advance the position to the
 
299
     *     end of file
 
300
     * @exception IOException If an I/O error has occurred.
 
301
     */
 
302
    private void writeBytes(byte b[], int off, int len, boolean append)
 
303
        throws IOException {
 
304
        fd.writeBytes(b, off, len);
 
305
    }
 
306
 
 
307
    /**
 
308
     * Writes <code>b.length</code> bytes from the specified byte array
 
309
     * to this file output stream.
 
310
     *
 
311
     * @param      b   the data.
 
312
     * @exception  IOException  if an I/O error occurs.
 
313
     */
 
314
    public void write(byte b[]) throws IOException {
 
315
        writeBytes(b, 0, b.length, append);
 
316
    }
 
317
 
 
318
    /**
 
319
     * Writes <code>len</code> bytes from the specified byte array
 
320
     * starting at offset <code>off</code> to this file output stream.
 
321
     *
 
322
     * @param      b     the data.
 
323
     * @param      off   the start offset in the data.
 
324
     * @param      len   the number of bytes to write.
 
325
     * @exception  IOException  if an I/O error occurs.
 
326
     */
 
327
    public void write(byte b[], int off, int len) throws IOException {
 
328
        writeBytes(b, off, len, append);
 
329
    }
 
330
 
 
331
    /**
 
332
     * Closes this file output stream and releases any system resources
 
333
     * associated with this stream. This file output stream may no longer
 
334
     * be used for writing bytes.
 
335
     *
 
336
     * <p> If this stream has an associated channel then the channel is closed
 
337
     * as well.
 
338
     *
 
339
     * @exception  IOException  if an I/O error occurs.
 
340
     *
 
341
     * @revised 1.4
 
342
     * @spec JSR-51
 
343
     */
 
344
    public void close() throws IOException {
 
345
        synchronized (closeLock) {
 
346
            if (closed) {
 
347
                return;
 
348
            }
 
349
            closed = true;
 
350
        }
 
351
 
 
352
        if (channel != null) {
 
353
            /*
 
354
             * Decrement FD use count associated with the channel
 
355
             * The use count is incremented whenever a new channel
 
356
             * is obtained from this stream.
 
357
             */
 
358
            fd.decrementAndGetUseCount();
 
359
            channel.close();
 
360
        }
 
361
 
 
362
        /*
 
363
         * Decrement FD use count associated with this stream
 
364
         */
 
365
        int useCount = fd.decrementAndGetUseCount();
 
366
 
 
367
        /*
 
368
         * If FileDescriptor is still in use by another stream, the finalizer
 
369
         * will not close it.
 
370
         */
 
371
        if ((useCount <= 0) || !isRunningFinalize()) {
 
372
            close0();
 
373
        }
 
374
    }
 
375
 
 
376
    /**
 
377
     * Returns the file descriptor associated with this stream.
 
378
     *
 
379
     * @return  the <code>FileDescriptor</code> object that represents
 
380
     *          the connection to the file in the file system being used
 
381
     *          by this <code>FileOutputStream</code> object.
 
382
     *
 
383
     * @exception  IOException  if an I/O error occurs.
 
384
     * @see        java.io.FileDescriptor
 
385
     */
 
386
     public final FileDescriptor getFD()  throws IOException {
 
387
        if (fd != null) return fd;
 
388
        throw new IOException();
 
389
     }
 
390
 
 
391
    /**
 
392
     * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
 
393
     * object associated with this file output stream. </p>
 
394
     *
 
395
     * <p> The initial {@link java.nio.channels.FileChannel#position()
 
396
     * </code>position<code>} of the returned channel will be equal to the
 
397
     * number of bytes written to the file so far unless this stream is in
 
398
     * append mode, in which case it will be equal to the size of the file.
 
399
     * Writing bytes to this stream will increment the channel's position
 
400
     * accordingly.  Changing the channel's position, either explicitly or by
 
401
     * writing, will change this stream's file position.
 
402
     *
 
403
     * @return  the file channel associated with this file output stream
 
404
     *
 
405
     * @since 1.4
 
406
     * @spec JSR-51
 
407
     */
 
408
    public FileChannel getChannel() {
 
409
        synchronized (this) {
 
410
            if (channel == null) {
 
411
                channel = FileChannelImpl.open(fd, false, true, append, this);
 
412
 
 
413
                /*
 
414
                 * Increment fd's use count. Invoking the channel's close()
 
415
                 * method will result in decrementing the use count set for
 
416
                 * the channel.
 
417
                 */
 
418
                fd.incrementAndGetUseCount();
 
419
            }
 
420
            return channel;
 
421
        }
 
422
    }
 
423
 
 
424
    /**
 
425
     * Cleans up the connection to the file, and ensures that the
 
426
     * <code>close</code> method of this file output stream is
 
427
     * called when there are no more references to this stream.
 
428
     *
 
429
     * @exception  IOException  if an I/O error occurs.
 
430
     * @see        java.io.FileInputStream#close()
 
431
     */
 
432
    protected void finalize() throws IOException {
 
433
        if (fd != null) {
 
434
            if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
 
435
                flush();
 
436
            } else {
 
437
 
 
438
                /*
 
439
                 * Finalizer should not release the FileDescriptor if another
 
440
                 * stream is still using it. If the user directly invokes
 
441
                 * close() then the FileDescriptor is also released.
 
442
                 */
 
443
                runningFinalize.set(Boolean.TRUE);
 
444
                try {
 
445
                    close();
 
446
                } finally {
 
447
                    runningFinalize.set(Boolean.FALSE);
 
448
                }
 
449
            }
 
450
        }
 
451
    }
 
452
 
 
453
    private void close0() throws IOException
 
454
    {
 
455
        fd.close();
 
456
    }
 
457
 
 
458
}