1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/rt/emul/compact/src/main/java/java/io/FileOutputStream.java Thu Oct 03 15:40:35 2013 +0200
1.3 @@ -0,0 +1,451 @@
1.4 +/*
1.5 + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 + *
1.8 + * This code is free software; you can redistribute it and/or modify it
1.9 + * under the terms of the GNU General Public License version 2 only, as
1.10 + * published by the Free Software Foundation. Oracle designates this
1.11 + * particular file as subject to the "Classpath" exception as provided
1.12 + * by Oracle in the LICENSE file that accompanied this code.
1.13 + *
1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 + * version 2 for more details (a copy is included in the LICENSE file that
1.18 + * accompanied this code).
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License version
1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 + *
1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 + * or visit www.oracle.com if you need additional information or have any
1.26 + * questions.
1.27 + */
1.28 +
1.29 +package java.io;
1.30 +
1.31 +import java.nio.channels.FileChannel;
1.32 +import sun.nio.ch.FileChannelImpl;
1.33 +
1.34 +
1.35 +/**
1.36 + * A file output stream is an output stream for writing data to a
1.37 + * <code>File</code> or to a <code>FileDescriptor</code>. Whether or not
1.38 + * a file is available or may be created depends upon the underlying
1.39 + * platform. Some platforms, in particular, allow a file to be opened
1.40 + * for writing by only one <tt>FileOutputStream</tt> (or other
1.41 + * file-writing object) at a time. In such situations the constructors in
1.42 + * this class will fail if the file involved is already open.
1.43 + *
1.44 + * <p><code>FileOutputStream</code> is meant for writing streams of raw bytes
1.45 + * such as image data. For writing streams of characters, consider using
1.46 + * <code>FileWriter</code>.
1.47 + *
1.48 + * @author Arthur van Hoff
1.49 + * @see java.io.File
1.50 + * @see java.io.FileDescriptor
1.51 + * @see java.io.FileInputStream
1.52 + * @see java.nio.file.Files#newOutputStream
1.53 + * @since JDK1.0
1.54 + */
1.55 +public
1.56 +class FileOutputStream extends OutputStream
1.57 +{
1.58 + /**
1.59 + * The system dependent file descriptor.
1.60 + */
1.61 + private final FileDescriptor fd;
1.62 +
1.63 + /**
1.64 + * True if the file is opened for append.
1.65 + */
1.66 + private final boolean append;
1.67 +
1.68 + /**
1.69 + * The associated channel, initalized lazily.
1.70 + */
1.71 + private FileChannel channel;
1.72 +
1.73 + private final Object closeLock = new Object();
1.74 + private volatile boolean closed = false;
1.75 + private static final ThreadLocal<Boolean> runningFinalize =
1.76 + new ThreadLocal<>();
1.77 +
1.78 + private static boolean isRunningFinalize() {
1.79 + Boolean val;
1.80 + if ((val = runningFinalize.get()) != null)
1.81 + return val.booleanValue();
1.82 + return false;
1.83 + }
1.84 +
1.85 + /**
1.86 + * Creates a file output stream to write to the file with the
1.87 + * specified name. A new <code>FileDescriptor</code> object is
1.88 + * created to represent this file connection.
1.89 + * <p>
1.90 + * First, if there is a security manager, its <code>checkWrite</code>
1.91 + * method is called with <code>name</code> as its argument.
1.92 + * <p>
1.93 + * If the file exists but is a directory rather than a regular file, does
1.94 + * not exist but cannot be created, or cannot be opened for any other
1.95 + * reason then a <code>FileNotFoundException</code> is thrown.
1.96 + *
1.97 + * @param name the system-dependent filename
1.98 + * @exception FileNotFoundException if the file exists but is a directory
1.99 + * rather than a regular file, does not exist but cannot
1.100 + * be created, or cannot be opened for any other reason
1.101 + * @exception SecurityException if a security manager exists and its
1.102 + * <code>checkWrite</code> method denies write access
1.103 + * to the file.
1.104 + * @see java.lang.SecurityManager#checkWrite(java.lang.String)
1.105 + */
1.106 + public FileOutputStream(String name) throws FileNotFoundException {
1.107 + this(name != null ? new File(name) : null, false);
1.108 + }
1.109 +
1.110 + /**
1.111 + * Creates a file output stream to write to the file with the specified
1.112 + * name. If the second argument is <code>true</code>, then
1.113 + * bytes will be written to the end of the file rather than the beginning.
1.114 + * A new <code>FileDescriptor</code> object is created to represent this
1.115 + * file connection.
1.116 + * <p>
1.117 + * First, if there is a security manager, its <code>checkWrite</code>
1.118 + * method is called with <code>name</code> as its argument.
1.119 + * <p>
1.120 + * If the file exists but is a directory rather than a regular file, does
1.121 + * not exist but cannot be created, or cannot be opened for any other
1.122 + * reason then a <code>FileNotFoundException</code> is thrown.
1.123 + *
1.124 + * @param name the system-dependent file name
1.125 + * @param append if <code>true</code>, then bytes will be written
1.126 + * to the end of the file rather than the beginning
1.127 + * @exception FileNotFoundException if the file exists but is a directory
1.128 + * rather than a regular file, does not exist but cannot
1.129 + * be created, or cannot be opened for any other reason.
1.130 + * @exception SecurityException if a security manager exists and its
1.131 + * <code>checkWrite</code> method denies write access
1.132 + * to the file.
1.133 + * @see java.lang.SecurityManager#checkWrite(java.lang.String)
1.134 + * @since JDK1.1
1.135 + */
1.136 + public FileOutputStream(String name, boolean append)
1.137 + throws FileNotFoundException
1.138 + {
1.139 + this(name != null ? new File(name) : null, append);
1.140 + }
1.141 +
1.142 + /**
1.143 + * Creates a file output stream to write to the file represented by
1.144 + * the specified <code>File</code> object. A new
1.145 + * <code>FileDescriptor</code> object is created to represent this
1.146 + * file connection.
1.147 + * <p>
1.148 + * First, if there is a security manager, its <code>checkWrite</code>
1.149 + * method is called with the path represented by the <code>file</code>
1.150 + * argument as its argument.
1.151 + * <p>
1.152 + * If the file exists but is a directory rather than a regular file, does
1.153 + * not exist but cannot be created, or cannot be opened for any other
1.154 + * reason then a <code>FileNotFoundException</code> is thrown.
1.155 + *
1.156 + * @param file the file to be opened for writing.
1.157 + * @exception FileNotFoundException if the file exists but is a directory
1.158 + * rather than a regular file, does not exist but cannot
1.159 + * be created, or cannot be opened for any other reason
1.160 + * @exception SecurityException if a security manager exists and its
1.161 + * <code>checkWrite</code> method denies write access
1.162 + * to the file.
1.163 + * @see java.io.File#getPath()
1.164 + * @see java.lang.SecurityException
1.165 + * @see java.lang.SecurityManager#checkWrite(java.lang.String)
1.166 + */
1.167 + public FileOutputStream(File file) throws FileNotFoundException {
1.168 + this(file, false);
1.169 + }
1.170 +
1.171 + /**
1.172 + * Creates a file output stream to write to the file represented by
1.173 + * the specified <code>File</code> object. If the second argument is
1.174 + * <code>true</code>, then bytes will be written to the end of the file
1.175 + * rather than the beginning. A new <code>FileDescriptor</code> object is
1.176 + * created to represent this file connection.
1.177 + * <p>
1.178 + * First, if there is a security manager, its <code>checkWrite</code>
1.179 + * method is called with the path represented by the <code>file</code>
1.180 + * argument as its argument.
1.181 + * <p>
1.182 + * If the file exists but is a directory rather than a regular file, does
1.183 + * not exist but cannot be created, or cannot be opened for any other
1.184 + * reason then a <code>FileNotFoundException</code> is thrown.
1.185 + *
1.186 + * @param file the file to be opened for writing.
1.187 + * @param append if <code>true</code>, then bytes will be written
1.188 + * to the end of the file rather than the beginning
1.189 + * @exception FileNotFoundException if the file exists but is a directory
1.190 + * rather than a regular file, does not exist but cannot
1.191 + * be created, or cannot be opened for any other reason
1.192 + * @exception SecurityException if a security manager exists and its
1.193 + * <code>checkWrite</code> method denies write access
1.194 + * to the file.
1.195 + * @see java.io.File#getPath()
1.196 + * @see java.lang.SecurityException
1.197 + * @see java.lang.SecurityManager#checkWrite(java.lang.String)
1.198 + * @since 1.4
1.199 + */
1.200 + public FileOutputStream(File file, boolean append)
1.201 + throws FileNotFoundException
1.202 + {
1.203 + String name = (file != null ? file.getPath() : null);
1.204 + SecurityManager security = System.getSecurityManager();
1.205 + if (security != null) {
1.206 + security.checkWrite(name);
1.207 + }
1.208 + if (name == null) {
1.209 + throw new NullPointerException();
1.210 + }
1.211 + this.fd = new FileDescriptor();
1.212 + this.append = append;
1.213 +
1.214 + fd.incrementAndGetUseCount();
1.215 + open(name, append);
1.216 + }
1.217 +
1.218 + /**
1.219 + * Creates a file output stream to write to the specified file
1.220 + * descriptor, which represents an existing connection to an actual
1.221 + * file in the file system.
1.222 + * <p>
1.223 + * First, if there is a security manager, its <code>checkWrite</code>
1.224 + * method is called with the file descriptor <code>fdObj</code>
1.225 + * argument as its argument.
1.226 + * <p>
1.227 + * If <code>fdObj</code> is null then a <code>NullPointerException</code>
1.228 + * is thrown.
1.229 + * <p>
1.230 + * This constructor does not throw an exception if <code>fdObj</code>
1.231 + * is {@link java.io.FileDescriptor#valid() invalid}.
1.232 + * However, if the methods are invoked on the resulting stream to attempt
1.233 + * I/O on the stream, an <code>IOException</code> is thrown.
1.234 + *
1.235 + * @param fdObj the file descriptor to be opened for writing
1.236 + * @exception SecurityException if a security manager exists and its
1.237 + * <code>checkWrite</code> method denies
1.238 + * write access to the file descriptor
1.239 + * @see java.lang.SecurityManager#checkWrite(java.io.FileDescriptor)
1.240 + */
1.241 + public FileOutputStream(FileDescriptor fdObj) {
1.242 + SecurityManager security = System.getSecurityManager();
1.243 + if (fdObj == null) {
1.244 + throw new NullPointerException();
1.245 + }
1.246 + if (security != null) {
1.247 + security.checkWrite(fdObj);
1.248 + }
1.249 + this.fd = fdObj;
1.250 + this.append = false;
1.251 +
1.252 + /*
1.253 + * FileDescriptor is being shared by streams.
1.254 + * Ensure that it's GC'ed only when all the streams/channels are done
1.255 + * using it.
1.256 + */
1.257 + fd.incrementAndGetUseCount();
1.258 + }
1.259 +
1.260 + /**
1.261 + * Opens a file, with the specified name, for overwriting or appending.
1.262 + * @param name name of file to be opened
1.263 + * @param append whether the file is to be opened in append mode
1.264 + */
1.265 + private native void open(String name, boolean append)
1.266 + throws FileNotFoundException;
1.267 +
1.268 + /**
1.269 + * Writes the specified byte to this file output stream.
1.270 + *
1.271 + * @param b the byte to be written.
1.272 + * @param append {@code true} if the write operation first
1.273 + * advances the position to the end of file
1.274 + */
1.275 + private native void write(int b, boolean append) throws IOException;
1.276 +
1.277 + /**
1.278 + * Writes the specified byte to this file output stream. Implements
1.279 + * the <code>write</code> method of <code>OutputStream</code>.
1.280 + *
1.281 + * @param b the byte to be written.
1.282 + * @exception IOException if an I/O error occurs.
1.283 + */
1.284 + public void write(int b) throws IOException {
1.285 + write(b, append);
1.286 + }
1.287 +
1.288 + /**
1.289 + * Writes a sub array as a sequence of bytes.
1.290 + * @param b the data to be written
1.291 + * @param off the start offset in the data
1.292 + * @param len the number of bytes that are written
1.293 + * @param append {@code true} to first advance the position to the
1.294 + * end of file
1.295 + * @exception IOException If an I/O error has occurred.
1.296 + */
1.297 + private native void writeBytes(byte b[], int off, int len, boolean append)
1.298 + throws IOException;
1.299 +
1.300 + /**
1.301 + * Writes <code>b.length</code> bytes from the specified byte array
1.302 + * to this file output stream.
1.303 + *
1.304 + * @param b the data.
1.305 + * @exception IOException if an I/O error occurs.
1.306 + */
1.307 + public void write(byte b[]) throws IOException {
1.308 + writeBytes(b, 0, b.length, append);
1.309 + }
1.310 +
1.311 + /**
1.312 + * Writes <code>len</code> bytes from the specified byte array
1.313 + * starting at offset <code>off</code> to this file output stream.
1.314 + *
1.315 + * @param b the data.
1.316 + * @param off the start offset in the data.
1.317 + * @param len the number of bytes to write.
1.318 + * @exception IOException if an I/O error occurs.
1.319 + */
1.320 + public void write(byte b[], int off, int len) throws IOException {
1.321 + writeBytes(b, off, len, append);
1.322 + }
1.323 +
1.324 + /**
1.325 + * Closes this file output stream and releases any system resources
1.326 + * associated with this stream. This file output stream may no longer
1.327 + * be used for writing bytes.
1.328 + *
1.329 + * <p> If this stream has an associated channel then the channel is closed
1.330 + * as well.
1.331 + *
1.332 + * @exception IOException if an I/O error occurs.
1.333 + *
1.334 + * @revised 1.4
1.335 + * @spec JSR-51
1.336 + */
1.337 + public void close() throws IOException {
1.338 + synchronized (closeLock) {
1.339 + if (closed) {
1.340 + return;
1.341 + }
1.342 + closed = true;
1.343 + }
1.344 +
1.345 + if (channel != null) {
1.346 + /*
1.347 + * Decrement FD use count associated with the channel
1.348 + * The use count is incremented whenever a new channel
1.349 + * is obtained from this stream.
1.350 + */
1.351 + fd.decrementAndGetUseCount();
1.352 + channel.close();
1.353 + }
1.354 +
1.355 + /*
1.356 + * Decrement FD use count associated with this stream
1.357 + */
1.358 + int useCount = fd.decrementAndGetUseCount();
1.359 +
1.360 + /*
1.361 + * If FileDescriptor is still in use by another stream, the finalizer
1.362 + * will not close it.
1.363 + */
1.364 + if ((useCount <= 0) || !isRunningFinalize()) {
1.365 + close0();
1.366 + }
1.367 + }
1.368 +
1.369 + /**
1.370 + * Returns the file descriptor associated with this stream.
1.371 + *
1.372 + * @return the <code>FileDescriptor</code> object that represents
1.373 + * the connection to the file in the file system being used
1.374 + * by this <code>FileOutputStream</code> object.
1.375 + *
1.376 + * @exception IOException if an I/O error occurs.
1.377 + * @see java.io.FileDescriptor
1.378 + */
1.379 + public final FileDescriptor getFD() throws IOException {
1.380 + if (fd != null) return fd;
1.381 + throw new IOException();
1.382 + }
1.383 +
1.384 + /**
1.385 + * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
1.386 + * object associated with this file output stream. </p>
1.387 + *
1.388 + * <p> The initial {@link java.nio.channels.FileChannel#position()
1.389 + * </code>position<code>} of the returned channel will be equal to the
1.390 + * number of bytes written to the file so far unless this stream is in
1.391 + * append mode, in which case it will be equal to the size of the file.
1.392 + * Writing bytes to this stream will increment the channel's position
1.393 + * accordingly. Changing the channel's position, either explicitly or by
1.394 + * writing, will change this stream's file position.
1.395 + *
1.396 + * @return the file channel associated with this file output stream
1.397 + *
1.398 + * @since 1.4
1.399 + * @spec JSR-51
1.400 + */
1.401 + public FileChannel getChannel() {
1.402 + synchronized (this) {
1.403 + if (channel == null) {
1.404 + channel = FileChannelImpl.open(fd, false, true, append, this);
1.405 +
1.406 + /*
1.407 + * Increment fd's use count. Invoking the channel's close()
1.408 + * method will result in decrementing the use count set for
1.409 + * the channel.
1.410 + */
1.411 + fd.incrementAndGetUseCount();
1.412 + }
1.413 + return channel;
1.414 + }
1.415 + }
1.416 +
1.417 + /**
1.418 + * Cleans up the connection to the file, and ensures that the
1.419 + * <code>close</code> method of this file output stream is
1.420 + * called when there are no more references to this stream.
1.421 + *
1.422 + * @exception IOException if an I/O error occurs.
1.423 + * @see java.io.FileInputStream#close()
1.424 + */
1.425 + protected void finalize() throws IOException {
1.426 + if (fd != null) {
1.427 + if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
1.428 + flush();
1.429 + } else {
1.430 +
1.431 + /*
1.432 + * Finalizer should not release the FileDescriptor if another
1.433 + * stream is still using it. If the user directly invokes
1.434 + * close() then the FileDescriptor is also released.
1.435 + */
1.436 + runningFinalize.set(Boolean.TRUE);
1.437 + try {
1.438 + close();
1.439 + } finally {
1.440 + runningFinalize.set(Boolean.FALSE);
1.441 + }
1.442 + }
1.443 + }
1.444 + }
1.445 +
1.446 + private native void close0() throws IOException;
1.447 +
1.448 + private static native void initIDs();
1.449 +
1.450 + static {
1.451 + initIDs();
1.452 + }
1.453 +
1.454 +}