KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > vfs > provider > DefaultFileContent


1 /*
2  * Copyright 2002-2005 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.commons.vfs.provider;
17
18 import org.apache.commons.vfs.FileContent;
19 import org.apache.commons.vfs.FileContentInfo;
20 import org.apache.commons.vfs.FileContentInfoFactory;
21 import org.apache.commons.vfs.FileObject;
22 import org.apache.commons.vfs.FileSystemException;
23 import org.apache.commons.vfs.RandomAccessContent;
24 import org.apache.commons.vfs.util.MonitorInputStream;
25 import org.apache.commons.vfs.util.MonitorOutputStream;
26 import org.apache.commons.vfs.util.MonitorRandomAccessContent;
27 import org.apache.commons.vfs.util.RandomAccessMode;
28
29 import java.io.IOException JavaDoc;
30 import java.io.InputStream JavaDoc;
31 import java.io.OutputStream JavaDoc;
32 import java.security.cert.Certificate JavaDoc;
33 import java.util.Collections JavaDoc;
34 import java.util.Map JavaDoc;
35 import java.util.Set JavaDoc;
36
37 /**
38  * The content of a file.
39  *
40  * @author <a HREF="mailto:adammurdoch@apache.org">Adam Murdoch</a>
41  */

42 public final class DefaultFileContent implements FileContent
43 {
44     /*
45     static final int STATE_NONE = 0;
46     static final int STATE_READING = 1;
47     static final int STATE_WRITING = 2;
48     static final int STATE_RANDOM_ACCESS = 3;
49     */

50
51     static final int STATE_CLOSED = 0;
52     static final int STATE_OPENED = 1;
53
54     private final AbstractFileObject file;
55     private Map JavaDoc attrs;
56     private Map JavaDoc roAttrs;
57     private FileContentInfo fileContentInfo;
58     private final FileContentInfoFactory fileContentInfoFactory;
59
60     private final ThreadLocal JavaDoc threadData = new ThreadLocal JavaDoc();
61
62     /**
63      * open streams counter for this file
64      */

65     private int openStreams = 0;
66
67     public DefaultFileContent(final AbstractFileObject file, final FileContentInfoFactory fileContentInfoFactory)
68     {
69         this.file = file;
70         this.fileContentInfoFactory = fileContentInfoFactory;
71     }
72
73     private FileContentThreadData getThreadData()
74     {
75         FileContentThreadData data = (FileContentThreadData) this.threadData.get();
76         if (data == null)
77         {
78             data = new FileContentThreadData();
79             this.threadData.set(data);
80         }
81         return data;
82     }
83
84     void streamOpened()
85     {
86         synchronized (this)
87         {
88             openStreams++;
89         }
90         ((AbstractFileSystem) file.getFileSystem()).streamOpened();
91     }
92
93     void streamClosed()
94     {
95         synchronized (this)
96         {
97             if (openStreams > 0)
98             {
99                 openStreams--;
100                 if (openStreams < 1)
101                 {
102                     file.notifyAllStreamsClosed();
103                 }
104             }
105         }
106         ((AbstractFileSystem) file.getFileSystem()).streamClosed();
107     }
108
109     /**
110      * Returns the file that this is the content of.
111      */

112     public FileObject getFile()
113     {
114         return file;
115     }
116
117     /**
118      * Returns the size of the content (in bytes).
119      */

120     public long getSize() throws FileSystemException
121     {
122         // Do some checking
123
if (!file.getType().hasContent())
124         {
125             throw new FileSystemException("vfs.provider/get-size-not-file.error", file);
126         }
127         /*
128         if (getThreadData().getState() == STATE_WRITING || getThreadData().getState() == STATE_RANDOM_ACCESS)
129         {
130             throw new FileSystemException("vfs.provider/get-size-write.error", file);
131         }
132         */

133
134         try
135         {
136             // Get the size
137
return file.doGetContentSize();
138         }
139         catch (final Exception JavaDoc exc)
140         {
141             throw new FileSystemException("vfs.provider/get-size.error", new Object JavaDoc[]{file}, exc);
142         }
143     }
144
145     /**
146      * Returns the last-modified timestamp.
147      */

148     public long getLastModifiedTime() throws FileSystemException
149     {
150         /*
151         if (getThreadData().getState() == STATE_WRITING || getThreadData().getState() == STATE_RANDOM_ACCESS)
152         {
153             throw new FileSystemException("vfs.provider/get-last-modified-writing.error", file);
154         }
155         */

156         if (!file.getType().hasAttributes())
157         {
158             throw new FileSystemException("vfs.provider/get-last-modified-no-exist.error", file);
159         }
160         try
161         {
162             return file.doGetLastModifiedTime();
163         }
164         catch (final Exception JavaDoc e)
165         {
166             throw new FileSystemException("vfs.provider/get-last-modified.error", file, e);
167         }
168     }
169
170     /**
171      * Sets the last-modified timestamp.
172      */

173     public void setLastModifiedTime(final long modTime) throws FileSystemException
174     {
175         /*
176         if (getThreadData().getState() == STATE_WRITING || getThreadData().getState() == STATE_RANDOM_ACCESS)
177         {
178             throw new FileSystemException("vfs.provider/set-last-modified-writing.error", file);
179         }
180         */

181         if (!file.getType().hasAttributes())
182         {
183             throw new FileSystemException("vfs.provider/set-last-modified-no-exist.error", file);
184         }
185         try
186         {
187             file.doSetLastModifiedTime(modTime);
188         }
189         catch (final Exception JavaDoc e)
190         {
191             throw new FileSystemException("vfs.provider/set-last-modified.error", file, e);
192         }
193     }
194
195     /**
196      * Returns a read-only map of this file's attributes.
197      */

198     public Map JavaDoc getAttributes() throws FileSystemException
199     {
200         if (!file.getType().hasAttributes())
201         {
202             throw new FileSystemException("vfs.provider/get-attributes-no-exist.error", file);
203         }
204         if (roAttrs == null)
205         {
206             try
207             {
208                 attrs = file.doGetAttributes();
209                 roAttrs = Collections.unmodifiableMap(attrs);
210             }
211             catch (final Exception JavaDoc e)
212             {
213                 throw new FileSystemException("vfs.provider/get-attributes.error", file, e);
214             }
215         }
216         return roAttrs;
217     }
218
219     /**
220      * Lists the attributes of this file.
221      */

222     public String JavaDoc[] getAttributeNames() throws FileSystemException
223     {
224         getAttributes();
225         final Set JavaDoc names = attrs.keySet();
226         return (String JavaDoc[]) names.toArray(new String JavaDoc[names.size()]);
227     }
228
229     /**
230      * Gets the value of an attribute.
231      */

232     public Object JavaDoc getAttribute(final String JavaDoc attrName)
233         throws FileSystemException
234     {
235         getAttributes();
236         return attrs.get(attrName.toLowerCase());
237     }
238
239     /**
240      * Sets the value of an attribute.
241      */

242     public void setAttribute(final String JavaDoc attrName, final Object JavaDoc value)
243         throws FileSystemException
244     {
245         if (!file.getType().hasAttributes())
246         {
247             throw new FileSystemException("vfs.provider/set-attribute-no-exist.error", new Object JavaDoc[]{attrName, file});
248         }
249         try
250         {
251             file.doSetAttribute(attrName, value);
252         }
253         catch (final Exception JavaDoc e)
254         {
255             throw new FileSystemException("vfs.provider/set-attribute.error", new Object JavaDoc[]{attrName, file}, e);
256         }
257
258         if (attrs != null)
259         {
260             attrs.put(attrName, value);
261         }
262     }
263
264     /**
265      * Returns the certificates used to sign this file.
266      */

267     public Certificate JavaDoc[] getCertificates() throws FileSystemException
268     {
269         if (!file.exists())
270         {
271             throw new FileSystemException("vfs.provider/get-certificates-no-exist.error", file);
272         }
273         /*
274         if (getThreadData().getState() == STATE_WRITING || getThreadData().getState() == STATE_RANDOM_ACCESS)
275         {
276             throw new FileSystemException("vfs.provider/get-certificates-writing.error", file);
277         }
278         */

279
280         try
281         {
282             final Certificate JavaDoc[] certs = file.doGetCertificates();
283             if (certs != null)
284             {
285                 return certs;
286             }
287             else
288             {
289                 return new Certificate JavaDoc[0];
290             }
291         }
292         catch (final Exception JavaDoc e)
293         {
294             throw new FileSystemException("vfs.provider/get-certificates.error", file, e);
295         }
296     }
297
298     /**
299      * Returns an input stream for reading the content.
300      */

301     public InputStream getInputStream() throws FileSystemException
302     {
303         /*
304         if (getThreadData().getState() == STATE_WRITING || getThreadData().getState() == STATE_RANDOM_ACCESS)
305         {
306             throw new FileSystemException("vfs.provider/read-in-use.error", file);
307         }
308         */

309
310         // Get the raw input stream
311
final InputStream instr = file.getInputStream();
312         final InputStream wrappedInstr = new FileContentInputStream(file, instr);
313
314         this.getThreadData().addInstr(wrappedInstr);
315         streamOpened();
316
317         // setState(STATE_OPENED);
318
return wrappedInstr;
319     }
320
321     /**
322      * Returns an input/output stream to use to read and write the content of the file in an
323      * random manner.
324      */

325     public RandomAccessContent getRandomAccessContent(final RandomAccessMode mode) throws FileSystemException
326     {
327         /*
328         if (getThreadData().getState() != STATE_NONE)
329         {
330             throw new FileSystemException("vfs.provider/read-in-use.error", file);
331         }
332         */

333
334         // Get the content
335
final RandomAccessContent rastr = file.getRandomAccessContent(mode);
336
337         this.getThreadData().setRastr(new FileRandomAccessContent(file, rastr));
338         streamOpened();
339
340         // setState(STATE_OPENED);
341
return this.getThreadData().getRastr();
342     }
343
344     /**
345      * Returns an output stream for writing the content.
346      */

347     public OutputStream getOutputStream() throws FileSystemException
348     {
349         return getOutputStream(false);
350     }
351
352     /**
353      * Returns an output stream for writing the content in append mode.
354      */

355     public OutputStream getOutputStream(boolean bAppend) throws FileSystemException
356     {
357         /*
358         if (getThreadData().getState() != STATE_NONE)
359         */

360         if (this.getThreadData().getOutstr() != null)
361         {
362             throw new FileSystemException("vfs.provider/write-in-use.error", file);
363         }
364
365         // Get the raw output stream
366
final OutputStream outstr = file.getOutputStream(bAppend);
367
368         // Create wrapper
369
this.getThreadData().setOutstr(new FileContentOutputStream(file, outstr));
370         streamOpened();
371
372         // setState(STATE_OPENED);
373
return this.getThreadData().getOutstr();
374     }
375
376     /**
377      * Closes all resources used by the content, including all streams, readers
378      * and writers.
379      */

380     public void close() throws FileSystemException
381     {
382         try
383         {
384             // Close the input stream
385
while (getThreadData().getInstrsSize() > 0)
386             {
387                 final FileContentInputStream instr = (FileContentInputStream) getThreadData().removeInstr(0);
388                 instr.close();
389             }
390
391             // Close the output stream
392
if (this.getThreadData().getOutstr() != null)
393             {
394                 this.getThreadData().closeOutstr();
395             }
396
397             // Close the random access stream
398
if (this.getThreadData().getRastr() != null)
399             {
400                 try
401                 {
402                     this.getThreadData().closeRastr();
403                 }
404                 catch (IOException JavaDoc e)
405                 {
406                     throw new FileSystemException(e);
407                 }
408             }
409         }
410         finally
411         {
412             threadData.set(null);
413         }
414     }
415
416     /**
417      * Handles the end of input stream.
418      */

419     private void endInput(final FileContentInputStream instr)
420     {
421         getThreadData().removeInstr(instr);
422         streamClosed();
423         /*
424         if (!getThreadData().hasStreams())
425         {
426             setState(STATE_CLOSED);
427         }
428         */

429     }
430
431     /**
432      * Handles the end of random access.
433      */

434     private void endRandomAccess()
435     {
436         streamClosed();
437         // setState(STATE_CLOSED);
438
}
439
440     /**
441      * Handles the end of output stream.
442      */

443     private void endOutput() throws Exception JavaDoc
444     {
445         streamClosed();
446
447         this.getThreadData().setOutstr(null);
448         // setState(STATE_CLOSED);
449

450         file.endOutput();
451     }
452
453     /*
454     private void setState(int state)
455     {
456         getThreadData().setState(state);
457     }
458     */

459
460     /**
461      * check if a input and/or output stream is open.<br />
462      * This checks only the scope of the current thread.
463      *
464      * @return true if this is the case
465      */

466     public boolean isOpen()
467     {
468         // return getThreadData().getState() == STATE_OPENED;
469
return getThreadData().hasStreams();
470     }
471
472     /**
473      * check if a input and/or output stream is open.<br />
474      * This checks all threads.
475      *
476      * @return true if this is the case
477      */

478     public boolean isOpenGlobal()
479     {
480         synchronized (this)
481         {
482             return openStreams > 0;
483         }
484     }
485
486     /**
487      * An input stream for reading content. Provides buffering, and
488      * end-of-stream monitoring.
489      */

490     private final class FileContentInputStream
491         extends MonitorInputStream
492     {
493         // avoid gc
494
private final FileObject file;
495
496         FileContentInputStream(final FileObject file, final InputStream instr)
497         {
498             super(instr);
499             this.file = file;
500         }
501
502         /**
503          * Closes this input stream.
504          */

505         public void close() throws FileSystemException
506         {
507             try
508             {
509                 super.close();
510             }
511             catch (final IOException JavaDoc e)
512             {
513                 throw new FileSystemException("vfs.provider/close-instr.error", file, e);
514             }
515         }
516
517         /**
518          * Called after the stream has been closed.
519          */

520         protected void onClose() throws IOException JavaDoc
521         {
522             try
523             {
524                 super.onClose();
525             }
526             finally
527             {
528                 endInput(this);
529             }
530         }
531     }
532
533     /**
534      * An input/output stream for reading/writing content on random positions
535      */

536     private final class FileRandomAccessContent extends MonitorRandomAccessContent
537     {
538         // avoid gc
539
private final FileObject file;
540
541         FileRandomAccessContent(final FileObject file, final RandomAccessContent content)
542         {
543             super(content);
544             this.file = file;
545         }
546
547         /**
548          * Called after the stream has been closed.
549          */

550         protected void onClose() throws IOException JavaDoc
551         {
552             try
553             {
554                 super.onClose();
555             }
556             finally
557             {
558                 endRandomAccess();
559             }
560         }
561     }
562
563     /**
564      * An output stream for writing content.
565      */

566     final class FileContentOutputStream extends MonitorOutputStream
567     {
568         // avoid gc
569
private final FileObject file;
570
571         FileContentOutputStream(final FileObject file, final OutputStream outstr)
572         {
573             super(outstr);
574             this.file = file;
575         }
576
577         /**
578          * Closes this output stream.
579          */

580         public void close() throws FileSystemException
581         {
582             try
583             {
584                 super.close();
585             }
586             catch (final IOException JavaDoc e)
587             {
588                 throw new FileSystemException("vfs.provider/close-outstr.error", file, e);
589             }
590         }
591
592         /**
593          * Called after this stream is closed.
594          */

595         protected void onClose() throws IOException JavaDoc
596         {
597             try
598             {
599                 super.onClose();
600             }
601             finally
602             {
603                 try
604                 {
605                     endOutput();
606                 }
607                 catch (Exception JavaDoc e)
608                 {
609                     throw new FileSystemException("vfs.provider/close-outstr.error", file, e);
610                 }
611             }
612         }
613     }
614
615     /**
616      * get the content info. e.g. content-type, content-encoding
617      */

618     public FileContentInfo getContentInfo() throws FileSystemException
619     {
620         if (fileContentInfo == null)
621         {
622             fileContentInfo = fileContentInfoFactory.create(this);
623         }
624
625         return fileContentInfo;
626     }
627 }
628
Popular Tags