KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > runtime > adaptor > StreamManager


1 /*******************************************************************************
2  * Copyright (c) 2004, 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.core.runtime.adaptor;
12
13 import java.io.*;
14 import org.eclipse.osgi.framework.internal.reliablefile.*;
15
16 /**
17  * This class manages streams for a FileManager.
18  * <p>
19  * Clients may not extend this class.
20  * </p>
21  * @since 3.1
22  */

23 public class StreamManager {
24     /**
25      * Open mask. Obtain the best data stream available. If the primary data
26      * contents are invalid (corrupt, missing, etc.), the data for a prior
27      * version may be used.
28      * An IOException will be thrown if a valid data content can not be
29      * determined.
30      * This is mutually exclusive with <code>OPEN_FAIL_ON_PRIMARY</code>.
31      */

32     public static final int OPEN_BEST_AVAILABLE = ReliableFile.OPEN_BEST_AVAILABLE;
33     /**
34      * Open mask. Obtain only the data stream for the primary file where any other
35      * version will not be valid. This should be used for data streams that are
36      * managed as a group as a prior contents may not match the other group data.
37      * If the primary data is not invalid, a IOException will be thrown.
38      * This is mutually exclusive with <code>OPEN_BEST_AVAILABLE</code>.
39      */

40     public static final int OPEN_FAIL_ON_PRIMARY = ReliableFile.OPEN_FAIL_ON_PRIMARY;
41
42     private static boolean useReliableFilesDefault = Boolean.valueOf(System.getProperty("osgi.useReliableFiles")).booleanValue(); //$NON-NLS-1$ //$NON-NLS-2$
43
private FileManager manager;
44     private boolean useReliableFiles;
45
46     private static final int ST_OPEN = 0;
47     private static final int ST_CLOSED = 1;
48
49     /**
50      * Constructor creates a new StreamManager using passed FileManager for storage.
51      *
52      * @param manager FileManager that manages the files
53      */

54     public StreamManager(FileManager manager) {
55         this.manager = manager;
56         useReliableFiles = useReliableFilesDefault;
57     }
58
59     /**
60      * Override the default useage of reliable files by this manager.
61      * @param state Whether to use reliable files for Input/Output streams
62      */

63     public void setUseReliableFiles(boolean state) {
64         useReliableFiles = state;
65     }
66
67     /**
68      * Returns a managed <code>InputStream</code> for a filemanager managed file.
69      * <code>null</code> can be returned if the given target is not managed.
70      * This call is equivalent to calling <code>getInputStream(target, OPEN_MASK_BEST_AVAILABLE).</code>
71      *
72      * @param target the base file name of the reliable file to open.
73      * @return an <code>InputStream</code> from the managed target file or
74      * <code>null</code> if the given target is not managed.
75      * @throws IOException if the file is missing, corrupt or an error occurs.
76      * @see StreamManager#getInputStream(String, int)
77      */

78     public InputStream getInputStream(String JavaDoc target) throws IOException {
79         return getInputStream(target, OPEN_BEST_AVAILABLE);
80     }
81
82     /**
83      * Returns a managed <code>InputStream</code> for a filemanager managed file.
84      * <code>null</code> can be returned if the given target is not managed.
85      * The <code>openMask<code> modifies the behavior of obtaining the data stream
86      * and can be ORed together.
87      *
88      * @param target the base file name of the reliable file to open.
89      * a backup version is not acceptable.
90      * @param openMask mask used to open the input target.
91      * @return an <code>InputStream</code> from the managed target file or
92      * <code>null</code> if the given target is not managed.
93      * @throws IOException if the file is missing, corrupt or an error occurs.
94      * @see #OPEN_BEST_AVAILABLE
95      * @see #OPEN_FAIL_ON_PRIMARY
96      */

97     public InputStream getInputStream(String JavaDoc target, int openMask) throws IOException {
98
99         if (useReliableFiles) {
100             int id = manager.getId(target);
101             return new ReliableFileInputStream(new File(manager.getBase(), target), id, openMask);
102         }
103         File lookup = manager.lookup(target, false);
104         if (lookup == null)
105             return null;
106         return new FileInputStream(lookup);
107     }
108
109     /**
110      * Returns an <code>OutputStream</code> for a filemanager managed file from a
111      * given base name. If enabled, the output stream will represent an OutputStream that
112      * will be validated before reading. Closing the ouput stream will update filemanager
113      * with the new target file.
114      *
115      * @param target the base file name of the file to write.
116      * @return <code>OutputStream</code> of a managed file with name of target.
117      * @throws IOException if an error occurs opening the file.
118      */

119     public StreamManagerOutputStream getOutputStream(String JavaDoc target) throws IOException {
120         if (useReliableFiles) {
121             ReliableFileOutputStream out = new ReliableFileOutputStream(new File(manager.getBase(), target));
122             return new StreamManagerOutputStream(out, this, target, null, ST_OPEN);
123         }
124         File tmpFile = manager.createTempFile(target);
125         return new StreamManagerOutputStream(new FileOutputStream(tmpFile), this, target, tmpFile, ST_OPEN);
126     }
127
128     /**
129      * Returns an array of <code>OutputStream</code> for a set of managed file names.
130      * If enabled, the output streams will represent OutputStreams that can be
131      * validated before reading. When all OutputStreams have been closed, filemanager
132      * will be updated with the new target files. Aborting any one of the streams will
133      * cause the entire set to abort and be discarded.
134      *
135      * @param targets list of base file names to write.
136      * @return an array of managed output streams respectively of targets.
137      * @throws IOException if an error occurs opening the files.
138      * @see StreamManagerOutputStream#close()
139      * @see StreamManagerOutputStream#abort()
140      */

141     public StreamManagerOutputStream[] getOutputStreamSet(String JavaDoc[] targets) throws IOException {
142         int count = targets.length;
143         StreamManagerOutputStream[] streams = new StreamManagerOutputStream[count];
144         int idx = 0;
145         try {
146             for (; idx < count; idx++) {
147                 StreamManagerOutputStream newStream = getOutputStream(targets[idx]);
148                 newStream.setStreamSet(streams);
149                 streams[idx] = newStream;
150             }
151         } catch (IOException e) {
152             // cleanup
153
for (int jdx = 0; jdx < idx; jdx++)
154                 streams[jdx].abort();
155             throw e;
156         }
157         return streams;
158     }
159
160     /**
161      * Instructs this manager to abort and discard a stream manager provided output stream(s).
162      * This method should be used if any errors occur after opening a filemanager
163      * output stream where the contents should not be saved. This method should
164      * be used instead of closing the <code>OutputStream</code>.
165      * If this output stream is part of a set, all other output streams in this set
166      * will also be closed and aborted.
167      * @param out the filemanager provided <code>OutputStream</code>.
168      * @see #getOutputStream(String)
169      * @see #getOutputStreamSet(String[])
170      */

171     void abortOutputStream(StreamManagerOutputStream out) {
172         StreamManagerOutputStream[] set = out.getStreamSet();
173         if (set == null) {
174             set = new StreamManagerOutputStream[] {out};
175         }
176         synchronized (set) {
177             for (int idx = 0; idx < set.length; idx++) {
178                 out = set[idx];
179                 if (out.getOutputFile() == null) {
180                     // this is a ReliableFileOutpuStream
181
ReliableFileOutputStream rfos = (ReliableFileOutputStream) out.getOutputStream();
182                     rfos.abort();
183                 } else {
184                     // plain FileOutputStream();
185
if (out.getState() == ST_OPEN) {
186                         try {
187                             out.getOutputStream().close();
188                         } catch (IOException e) {/*do nothing*/
189                         }
190                     }
191                     out.getOutputFile().delete();
192                 }
193                 out.setState(ST_CLOSED);
194             }
195         }
196     }
197
198     /**
199      * Close the filemanager <code>OutputStream</code> and update the new file to
200      * filemanager. If this output stream is part of a set, only after closing
201      * all output streams will filemanager be updated.
202      *
203      * @param smos the output stream.
204      * @throws IOException if an errors occur.
205      * @see #getOutputStream(String)
206      * @see #getOutputStreamSet(String[])
207      */

208     void closeOutputStream(StreamManagerOutputStream smos) throws IOException {
209         if (smos.getState() != ST_OPEN)
210             return;
211         StreamManagerOutputStream[] streamSet = smos.getStreamSet();
212         if (smos.getOutputFile() == null) {
213             // this is a ReliableFileOutputStream
214
ReliableFileOutputStream rfos = (ReliableFileOutputStream) smos.getOutputStream();
215             // FileManager manage file deletes
216
File file = rfos.closeIntermediateFile();
217             smos.setState(ST_CLOSED);
218             String JavaDoc target = smos.getTarget();
219             if (streamSet == null) {
220                 manager.add(target, FileManager.FILETYPE_RELIABLEFILE);
221                 manager.update(new String JavaDoc[] {smos.getTarget()}, new String JavaDoc[] {file.getName()});
222                 ReliableFile.fileUpdated(new File(manager.getBase(), smos.getTarget()));
223             }
224         } else {
225             // this is a plain old file output steam
226
OutputStream out = smos.getOutputStream();
227             out.flush();
228             try {
229                 ((FileOutputStream) out).getFD().sync();
230             } catch (SyncFailedException e) {/*ignore*/
231             }
232             out.close();
233             smos.setState(ST_CLOSED);
234             String JavaDoc target = smos.getTarget();
235             if (streamSet == null) {
236                 manager.add(target, FileManager.FILETYPE_STANDARD);
237                 manager.update(new String JavaDoc[] {target}, new String JavaDoc[] {smos.getOutputFile().getName()});
238             }
239         }
240
241         if (streamSet != null) {
242             synchronized (streamSet) {
243                 //check all the streams to see if there are any left open....
244
for (int idx = 0; idx < streamSet.length; idx++) {
245                     if (streamSet[idx].getState() == ST_OPEN)
246                         return; //done
247
}
248                 //all streams are closed, we need to update fileManager
249
String JavaDoc[] targets = new String JavaDoc[streamSet.length];
250                 String JavaDoc[] sources = new String JavaDoc[streamSet.length];
251                 for (int idx = 0; idx < streamSet.length; idx++) {
252                     smos = streamSet[idx];
253                     targets[idx] = smos.getTarget();
254                     File outputFile = smos.getOutputFile();
255                     if (outputFile == null) {
256                         // this is a ReliableFile
257
manager.add(smos.getTarget(), FileManager.FILETYPE_RELIABLEFILE);
258                         ReliableFileOutputStream rfos = (ReliableFileOutputStream) smos.getOutputStream();
259                         File file = rfos.closeIntermediateFile(); //multiple calls to close() ok
260
sources[idx] = file.getName();
261                         ReliableFile.fileUpdated(new File(manager.getBase(), smos.getTarget()));
262                     } else {
263                         manager.add(smos.getTarget(), FileManager.FILETYPE_STANDARD);
264                         sources[idx] = outputFile.getName();
265                     }
266                 }
267                 manager.update(targets, sources);
268             }
269         }
270     }
271
272     /**
273      * Get the FileManager used by this stream manager.
274      * @return the file manager being used by this stream manager.
275      * @see FileManager
276      */

277     public FileManager getFileManager() {
278         return manager;
279     }
280 }
281
Popular Tags