Project Report: fawkez

Packagesummary org.jcoderz.commons.util

org.jcoderz.commons.util.LazyFileOutputStream

LineHitsNoteSource
1  /*
2   * $Id: LazyFileOutputStream.java 1068 2008-07-08 19:14:40Z amandel $
3   *
4   * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5   *
6   * Redistribution and use in source and binary forms, with or without
7   * modification, are permitted provided that the following conditions are
8   * met:
9   *
10   *    * Redistributions of source code must retain the above copyright
11   *      notice, this list of conditions and the following disclaimer.
12   *    * Redistributions in binary form must reproduce the above
13   *      copyright notice, this list of conditions and the following
14   *      disclaimer in the documentation and/or other materials
15   *      provided with the distribution.
16   *    * Neither the name of the jCoderZ.org Project nor the names of
17   *      its contributors may be used to endorse or promote products
18   *      derived from this software without specific prior written
19   *      permission.
20   *
21   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32   */
33  package org.jcoderz.commons.util;
34  
35  import java.io.BufferedInputStream;
36  import java.io.ByteArrayOutputStream;
37  import java.io.File;
38  import java.io.FileInputStream;
39  import java.io.FileNotFoundException;
40  import java.io.FileOutputStream;
41  import java.io.IOException;
42  import java.io.InputStream;
43  import java.io.OutputStream;
44  import java.util.logging.Logger;
45  
46  /**
47   * Purpose of this class is to avoid writing a File if it already
48   * exists and hold the same content.
49   *
50   * <p>This class in not about saving time for faster processing nor
51   * does is perform anything quicker. It sole checks if the target
52   * file exists, and if its content is already the same than
53   * the content that should be written. If this is the case no
54   * write operation is done at all. Therefore also the file content
55   * to be written is held in memory until the file is closed OR
56   * it is detected that the content did change.</p>
57   *
58   * <p>Instances of this class are NOT multi thread save.</p>
59   *
60   * @author Andreas Mandel
61   */
62  public class LazyFileOutputStream
63      extends OutputStream
64  {
6575     private static final String CLASSNAME
66          = LazyFileOutputStream.class.getName();
67100     private static final Logger logger = Logger.getLogger(CLASSNAME);
68      private boolean mBuffering;
69      private OutputStream mOutput;
70      private File mFile;
71      private InputStream mInputStream;
72  
73  
74      /** @see FileOutputStream#FileOutputStream(String, boolean) */
75 (1)(2)    public LazyFileOutputStream (File file, boolean append)
76 (3)        throws FileNotFoundException
77100     {
78100         mFile = file;
79100         if (append)
80          {
810             mBuffering = false;
820             mOutput = new FileOutputStream(file, append);
83          }
84          else
85          {
86100             if (file.exists() && file.canRead())
87              { // Should be OK to let a possible exception fall through
88100                 mInputStream =
89                      new BufferedInputStream(new FileInputStream(file));
90100                 mOutput = new ByteArrayOutputStream();
91100                 mBuffering = true;
92              }
93              else
94              {
950                 mOutput = new FileOutputStream(file, append);
960                 mBuffering = false;
97              }
98          }
99100     }
100  
101      /** @see FileOutputStream#FileOutputStream(File) */
102 (4)    public LazyFileOutputStream (File file)
103 (5)        throws FileNotFoundException
104      {
105100         this(file, false);
106100     }
107  
108      /** @see FileOutputStream#FileOutputStream(String, boolean) */
109 (6)(7)    public LazyFileOutputStream (String name, boolean append)
110 (8)        throws FileNotFoundException
111      {
1120         this(new File(name), append);
1130     }
114  
115      /** @see FileOutputStream#FileOutputStream(String) */
116 (9)    public LazyFileOutputStream (String name)
117 (10)        throws FileNotFoundException
118      {
1190         this(new File(name));
1200     }
121  
122      /**
123       * Returns true if the file is still buffered.
124       * The value might change from true to false until
125       * the stream is closed. After this the returned value will not
126       * change any more.
127       * @return true if the actual out file was not touched (yet).
128       */
129      public boolean isBuffered ()
130      {
131100         return mBuffering;
132      }
133  
134      /** {@inheritDoc} */
135      public void write (int b)
136          throws IOException
137      {
138100         ensureOpen();
139100         if (mBuffering && mInputStream.read() != b)
140          {
141100             stopBuffering();
142          }
143100         mOutput.write(b);
144100     }
145  
146 (11)    // TODO: For better performance implement the other write methods!
147  
148      /** {@inheritDoc} */
149      public void close ()
150          throws IOException
151      {
152100         if (mBuffering && mInputStream.read() != -1)
153          { // new output is shorter...
154100             stopBuffering();
155          }
156100         IoUtil.close(mInputStream);
157100         if (mOutput != null)
158          {
159100             mOutput.close();
160100             mOutput = null;
161100             if (mBuffering)
162              {
163100                 logger.fine("Avoided to touch " + mFile);
164              }
165          }
166100     }
167  
168      /**
169       * Cleans up the connection to the file, and ensures that the
170       * <code>close</code> method of this file output stream is
171       * called when there are no more references to this stream.
172       *
173       * @exception IOException if an I/O error occurs.
174       * @see java.io.FileInputStream#close()
175       */
176      protected void finalize ()
177          throws IOException, Throwable
178      {
179100         if (mOutput != null)
180          {
1810             close();
182          }
183100         super.finalize();
184100     }
185  
186  
187      /**
188       * Check to make sure that output stream has not been nulled
189       * out due to close
190       */
191      private void ensureOpen ()
192          throws IOException
193      {
194100         if (mOutput == null)
195          {
1960             throw new IOException("Stream closed");
197          }
198100     }
199  
200      private void stopBuffering ()
201          throws IOException
202      {
203100         IoUtil.close(mInputStream);
204100         IoUtil.close(mOutput);
205          // sanity
206100         if (!(mOutput instanceof ByteArrayOutputStream))
207          {
2080             throw new RuntimeException("Internal inconsistency");
209          }
210100         final byte[] data
211              = ((ByteArrayOutputStream) mOutput).toByteArray();
212100         mOutput = new FileOutputStream(mFile);
213100         mOutput.write(data);
214100         mBuffering = false;
215100     }
216  }

Findings in this File

c (1) 75 : 39 Expected @param tag for 'file'.
c (2) 75 : 53 Expected @param tag for 'append'.
c (3) 76 : 16 Expected @throws tag for 'FileNotFoundException'.
c (4) 102 : 39 Expected @param tag for 'file'.
c (5) 103 : 16 Expected @throws tag for 'FileNotFoundException'.
c (6) 109 : 41 Expected @param tag for 'name'.
c (7) 109 : 55 Expected @param tag for 'append'.
c (8) 110 : 16 Expected @throws tag for 'FileNotFoundException'.
c (9) 116 : 41 Expected @param tag for 'name'.
c (10) 117 : 16 Expected @throws tag for 'FileNotFoundException'.
i (11) 146 : 0 Comment matches to-do format '(TODO|FIXME|CHECKME)'.