KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > source > FileSource


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

16 package org.apache.cocoon.components.source;
17
18 import java.io.File JavaDoc;
19 import java.io.FileInputStream JavaDoc;
20 import java.io.FileNotFoundException JavaDoc;
21 import java.io.FileOutputStream JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.io.OutputStream JavaDoc;
25 import java.net.MalformedURLException JavaDoc;
26 import java.util.ConcurrentModificationException JavaDoc;
27
28 import org.apache.avalon.framework.component.ComponentManager;
29 import org.apache.cocoon.ProcessingException;
30 import org.apache.cocoon.ResourceNotFoundException;
31
32 /**
33  * A <code>org.apache.cocoon.environment.WriteableSource</code> for 'file:/' system IDs.
34  *
35  * @author <a HREF="mailto:sylvain@apache.org">Sylvain Wallez</a>
36  * @version CVS $Id: FileSource.java 30932 2004-07-29 17:35:38Z vgritsenko $
37  * @deprecated Use the new avalon source resolving instead
38  */

39 public class FileSource extends AbstractStreamWriteableSource
40     implements org.apache.cocoon.environment.WriteableSource {
41
42     /** The underlying file. */
43     protected File JavaDoc file;
44
45     /** The system ID for this source (lazily created by getSystemId()) */
46     private String JavaDoc systemId;
47
48     /** Is this an html file ? */
49     private boolean isHTMLContent;
50
51     /**
52      * Create a file source from a 'file:' url and a component manager.
53      */

54     public FileSource(String JavaDoc url, ComponentManager manager) {
55
56         super(manager);
57
58         if (!url.startsWith("file:")) {
59             throw new IllegalArgumentException JavaDoc("Malformed url for a file source : " + url);
60         }
61
62         if (url.endsWith(".htm") || url.endsWith(".html")) {
63             this.isHTMLContent = true;
64         }
65
66         this.file = new File JavaDoc(url.substring(5)); // 5 == "file:".length()
67
}
68
69     public boolean exists() {
70         return this.file.exists();
71     }
72
73     /**
74      * Returns <code>true</code> if the file name ends with ".htm" or ".html".
75      */

76     protected boolean isHTMLContent() {
77         return this.isHTMLContent;
78     }
79
80     /**
81      * Return the unique identifer for this source
82      */

83     public String JavaDoc getSystemId() {
84         if (this.systemId == null) {
85             try {
86                 this.systemId = this.file.toURL().toExternalForm();
87             } catch(MalformedURLException JavaDoc mue) {
88                 // Can this really happen ?
89
this.systemId = "file:" + this.file.getPath();
90             }
91         }
92         return this.systemId;
93     }
94
95     /**
96      * Get the input stream for this source.
97      */

98     public InputStream JavaDoc getInputStream() throws IOException JavaDoc, ProcessingException {
99         try {
100             return new FileInputStream JavaDoc(this.file);
101         } catch (FileNotFoundException JavaDoc e) {
102             throw new ResourceNotFoundException("Resource not found "
103                                                 + getSystemId(), e);
104         }
105     }
106
107     public long getLastModified() {
108         return this.file.lastModified();
109     }
110
111     public long getContentLength() {
112         return this.file.length();
113     }
114
115     /**
116      * Get an output stream to write to this source. The output stream returned
117      * actually writes to a temp file that replaces the real one on close. This
118      * temp file is used as lock to forbid multiple simultaneous writes. The
119      * real file is updated atomically when the output stream is closed.
120      *
121      * @throws ConcurrentModificationException if another thread is currently
122      * writing to this file.
123      */

124     public OutputStream JavaDoc getOutputStream() throws IOException JavaDoc, ProcessingException {
125
126         // Create a temp file. It will replace the right one when writing terminates,
127
// and serve as a lock to prevent concurrent writes.
128
File JavaDoc tmpFile = new File JavaDoc(this.file.getPath() + ".tmp");
129
130         // Ensure the directory exists
131
tmpFile.getParentFile().mkdirs();
132
133         // Can we write the file ?
134
if (this.file.exists() && !this.file.canWrite()) {
135             throw new IOException JavaDoc("Cannot write to file " + this.file.getPath());
136         }
137
138         // Check if it temp file already exists, meaning someone else currently writing
139
if (!tmpFile.createNewFile()) {
140             throw new ConcurrentModificationException JavaDoc("File " + this.file.getPath() +
141               " is already being written by another thread");
142         }
143
144         // Return a stream that will rename the temp file on close.
145
return new FileSourceOutputStream(tmpFile);
146     }
147
148     /**
149      * Always return <code>false</code>. To be redefined by implementations that support
150      * <code>cancel()</code>.
151      */

152     public boolean canCancel(OutputStream JavaDoc stream) {
153         if (stream instanceof FileSourceOutputStream) {
154             FileSourceOutputStream fsos = (FileSourceOutputStream)stream;
155             if (fsos.getSource() == this) {
156                 return fsos.canCancel();
157             }
158         }
159
160         // Not a valid stream for this source
161
throw new IllegalArgumentException JavaDoc("The stream is not associated to this source");
162     }
163
164     /**
165      * Cancels the output stream.
166      */

167     public void cancel(OutputStream JavaDoc stream) throws Exception JavaDoc {
168         if (stream instanceof FileSourceOutputStream) {
169             FileSourceOutputStream fsos = (FileSourceOutputStream)stream;
170             if (fsos.getSource() == this) {
171                 fsos.cancel();
172                 return;
173             }
174         }
175
176         // Not a valid stream for this source
177
throw new IllegalArgumentException JavaDoc("The stream is not associated to this source");
178     }
179
180     /**
181      * A file outputStream that will rename the temp file to the destination file upon close()
182      * and discard the temp file upon cancel().
183      */

184     private class FileSourceOutputStream extends FileOutputStream JavaDoc {
185
186         private File JavaDoc tmpFile;
187         private boolean isClosed = false;
188
189         public FileSourceOutputStream(File JavaDoc tmpFile) throws IOException JavaDoc {
190             super(tmpFile);
191             this.tmpFile = tmpFile;
192         }
193
194         public FileSource getSource() {
195             return FileSource.this;
196         }
197
198         public void close() throws IOException JavaDoc {
199             super.close();
200
201             try {
202                 // Delete destination file
203
if (FileSource.this.file.exists()) {
204                     FileSource.this.file.delete();
205                 }
206                 // Rename temp file to destination file
207
tmpFile.renameTo(FileSource.this.file);
208
209             } finally {
210                 // Ensure temp file is deleted, ie lock is released.
211
// If there was a failure above, written data is lost.
212
if (tmpFile.exists()) {
213                     tmpFile.delete();
214                 }
215                 this.isClosed = true;
216             }
217         }
218
219         public boolean canCancel() {
220             return !this.isClosed;
221         }
222
223         public void cancel() throws Exception JavaDoc {
224             if (this.isClosed) {
225                 throw new IllegalStateException JavaDoc("Cannot cancel : outputstrem is already closed");
226             }
227
228             this.isClosed = true;
229             super.close();
230             this.tmpFile.delete();
231         }
232
233         public void finalize() {
234             if (!this.isClosed && tmpFile.exists()) {
235                 // Something wrong happened while writing : delete temp file
236
tmpFile.delete();
237             }
238         }
239     }
240 }
241
Popular Tags