KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > de > schlichtherle > io > FileOutputStream


1 /*
2  * FileOutputStream.java
3  *
4  * Created on 23. Oktober 2004, 01:08
5  */

6 /*
7  * Copyright 2005 Schlichtherle IT Services
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */

21
22 package de.schlichtherle.io;
23
24 import java.io.FileDescriptor JavaDoc;
25 import java.io.FilterOutputStream JavaDoc;
26 import java.io.InputStream JavaDoc;
27 import java.io.OutputStream JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.io.FileNotFoundException JavaDoc;
30
31 /**
32  * A <em>drop-in-replacement</em> for <code>java.io.FileOutputStream</code>
33  * which provides transparent access to archive files as if they were just
34  * directories in a path name.
35  * To write an entry in an archive file, simply create an instance of
36  * this class with a path name that contains the archive file as one
37  * of the parent directories.
38  * The remainder of the path name will then be used as the relative path
39  * of the entry in the archive file to be created or overwritten.
40  * <p>
41  * For example on UNIX like systems using the pathname
42  * <tt>/home/user/archive.zip/directory/readme</tt> will create or overwrite
43  * the relative path <tt>directory/readme</tt> in the ZIP file
44  * <tt>/home/user/archive.zip</tt>.
45  * <p>
46  * To prevent an exception to be thrown subsequently, client applications
47  * must make sure to close their streams using the following idiom:
48  * <code>
49  * <pre>
50  * FileOutputStream fos = new FileOutputStream(file);
51  * try {
52  * // access fos here
53  * } finally {
54  * fos.close();
55  * }
56  * </pre>
57  * </code>
58  * Client applications should <em>always</em> use this idiom for any streams
59  * to ensure that subsequent operations like {@link File#umount} may succeed.
60  * <p>
61  * Note that this issue is not at all specific to this class:
62  * File descriptors are limited resources on any operating system and some
63  * operating systems even restrict a process from using certain file
64  * operations if the file is busy on I/O by another process.
65  * E.g. on Windows, a process cannot delete a file that is open for I/O
66  * by any other process.
67  *
68  * <h3>Important</h3>
69  * <ol>
70  * <li>The classes in this package access and manipulate archive files as
71  * external resources and may cache some of their state in memory and
72  * temporary files. Third parties must not concurrently access these
73  * archive files unless some precautions have been taken!
74  * For more information please refer to the
75  * <a HREF="package-summary.html#third_party_access">Third Party Access</a>
76  * section in the package description.
77  * <li>Client applications cannot write to an entry in an archive file if an
78  * automatic update is required but cannot be performed because the
79  * application is still using other <code>FileInputStream</code> or
80  * <code>FileOutputStream</code> instances which haven't been closed or
81  * discarded yet.
82  * Failure to comply to this restriction will result in a
83  * <code>FileBusyException</code> to be thrown by the constructors of this
84  * class.
85  * Client applications may call {@link File#umount} or {@link File#update}
86  * to force the other streams to be closed and recreate this stream again
87  * to resolve the issue.
88  * <li>Whether or not a client application can write to more than one entry
89  * in the same archive archive file concurrently is an implementation
90  * detail of the respective archive driver.
91  * TrueZIP's implementation of the ZIP32 driver family does not support
92  * to write more than one entry to the same archive concurrently, whereas
93  * the implementation of the TAR driver family supports writing to as
94  * many archive entries concurrently as desired.
95  * Other driver implementations may behave differently.
96  * <p>
97  * If a client application tries to exceed the number of entry streams
98  * supported to operate on the same archive file concurrently, a
99  * {@link FileBusyException} is thrown by the constructors of this class.
100  * In this case, the client application may close (or discard and rely
101  * on the finalizer thread) the previously created stream objects or
102  * call {@link File#umount()} or {@link File#update()} to force these
103  * streams to be closed and then recreate this stream object again to
104  * resolve the issue.
105 * </ol>
106  *
107  * <h3>Miscellaneous</h3>
108  * <ol>
109  * <li>If you would like to use this class in order to copy files,
110  * please consider using the <tt>*copy*</tt> methods in the {@link File}
111  * class instead. These offer advanced fail-safety and performance features.
112  * <li>If {@link File#isLenient()} returns <tt>true</tt> (which is the default)
113  * this class will create any missing parent directories and archive
114  * files up to the top level archive file in its path.
115  * Parent directories which are not located in an archive file need to
116  * exist, however!
117  * <li>When using characters in file names which have no representation in
118  * the character set encoding of an archive file, then the constructors
119  * of this class will fail gracefully with an IOException.
120  * This is to protect client applications from creating archive entries
121  * which cannot get encoded and decoded again correctly. An example is
122  * the Euro sign which does not have a representation in the IBM437
123  * character set used by ordinary ZIP files.
124  * <li>Please refer to the {@link java.io.FileOutputStream super class
125  * documentation} for any undocumented methods.
126  * </ol>
127  *
128  * @see FileBusyException
129  * @see File#update
130  * @see File#umount
131  * @see File#setLenient
132  * @see java.io.FileOutputStream java.io.FileOutputStream
133  * @see <a HREF="package-summary.html#package_description">Package Description</a>
134  * @author Christian Schlichtherle
135  * @version @version@
136  */

137 public class FileOutputStream extends FilterOutputStream JavaDoc {
138
139     private static OutputStream JavaDoc createOutputStream(
140             final java.io.File JavaDoc file,
141             final boolean append)
142             throws FileNotFoundException JavaDoc {
143         if (file instanceof File) {
144             final File smartFile = (File) file;
145             smartFile.ensureNotVirtualDirectory("cannot write");
146             final String JavaDoc entryName = smartFile.getEnclEntryName();
147             if (entryName != null) {
148                 return createOutputStream(
149                         smartFile.getEnclArchive().getArchiveController(),
150                         entryName, smartFile, append);
151             }
152         }
153         return new java.io.FileOutputStream JavaDoc(file, append);
154     }
155
156     private static OutputStream JavaDoc createOutputStream(
157             final ArchiveController controller,
158             final String JavaDoc entryName,
159             final File file,
160             final boolean append)
161             throws FileNotFoundException JavaDoc {
162         try {
163             return controller.getOutputStream(entryName, append);
164         } catch (ArchiveController.FalsePositiveNativeException failure) {
165             final java.io.File JavaDoc delegate = file.getDelegate();
166             final java.io.File JavaDoc parent = delegate.getParentFile();
167             if (parent.isDirectory()) // parent is always != null in this context!
168
return new java.io.FileOutputStream JavaDoc(file);
169             else
170                 throw failure;
171         }
172     }
173
174     /**
175      * Behaves like the super class, but also supports archive entry files.
176      *
177      * @see java.io.FileOutputStream java.io.FileOutputStream
178      */

179     public FileOutputStream(String JavaDoc name)
180     throws FileNotFoundException JavaDoc {
181         super(createOutputStream(
182                 File.getDefaultArchiveDetector().createFile(name), false));
183     }
184
185     /**
186      * Behaves like the super class, but also supports archive entry files.
187      *
188      * @see java.io.FileOutputStream java.io.FileOutputStream
189      */

190     public FileOutputStream(String JavaDoc name, boolean append)
191     throws FileNotFoundException JavaDoc {
192         super(createOutputStream(
193                 File.getDefaultArchiveDetector().createFile(name), append));
194     }
195
196     /**
197      * Behaves like the super class, but also supports archive entry files.
198      *
199      * @see java.io.FileOutputStream java.io.FileOutputStream
200      */

201     public FileOutputStream(java.io.File JavaDoc file)
202     throws FileNotFoundException JavaDoc {
203         super(createOutputStream(file, false));
204     }
205
206     /**
207      * Behaves like the super class, but also supports archive entry files.
208      *
209      * @see java.io.FileOutputStream java.io.FileOutputStream
210      */

211     public FileOutputStream(java.io.File JavaDoc file, boolean append)
212     throws FileNotFoundException JavaDoc {
213         super(createOutputStream(file, append));
214     }
215
216     /**
217      * @see java.io.FileOutputStream java.io.FileOutputStream
218      * @since TrueZIP 6.4
219      */

220     public FileOutputStream(FileDescriptor JavaDoc fd) {
221         super(new java.io.FileOutputStream JavaDoc(fd));
222     }
223
224     public void write(byte[] buf, int off, int len) throws IOException JavaDoc {
225         out.write(buf, off, len);
226     }
227 }
228
Popular Tags