1. /*
  2. * $Header: /home/cvs/jakarta-commons/fileupload/src/java/org/apache/commons/fileupload/ThresholdingOutputStream.java,v 1.3 2003/05/31 22:31:08 martinc Exp $
  3. * $Revision: 1.3 $
  4. * $Date: 2003/05/31 22:31:08 $
  5. *
  6. * ====================================================================
  7. *
  8. * The Apache Software License, Version 1.1
  9. *
  10. * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
  11. * reserved.
  12. *
  13. * Redistribution and use in source and binary forms, with or without
  14. * modification, are permitted provided that the following conditions
  15. * are met:
  16. *
  17. * 1. Redistributions of source code must retain the above copyright
  18. * notice, this list of conditions and the following disclaimer.
  19. *
  20. * 2. Redistributions in binary form must reproduce the above copyright
  21. * notice, this list of conditions and the following disclaimer in
  22. * the documentation and/or other materials provided with the
  23. * distribution.
  24. *
  25. * 3. The end-user documentation included with the redistribution, if
  26. * any, must include the following acknowlegement:
  27. * "This product includes software developed by the
  28. * Apache Software Foundation (http://www.apache.org/)."
  29. * Alternately, this acknowlegement may appear in the software itself,
  30. * if and wherever such third-party acknowlegements normally appear.
  31. *
  32. * 4. The names "The Jakarta Project", "Commons", and "Apache Software
  33. * Foundation" must not be used to endorse or promote products derived
  34. * from this software without prior written permission. For written
  35. * permission, please contact apache@apache.org.
  36. *
  37. * 5. Products derived from this software may not be called "Apache"
  38. * nor may "Apache" appear in their names without prior written
  39. * permission of the Apache Group.
  40. *
  41. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  42. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  43. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  44. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  45. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  46. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  47. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  48. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  49. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  50. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  51. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  52. * SUCH DAMAGE.
  53. * ====================================================================
  54. *
  55. * This software consists of voluntary contributions made by many
  56. * individuals on behalf of the Apache Software Foundation. For more
  57. * information on the Apache Software Foundation, please see
  58. * <http://www.apache.org/>.
  59. *
  60. */
  61. package org.apache.commons.fileupload;
  62. import java.io.IOException;
  63. import java.io.OutputStream;
  64. /**
  65. * An output stream which triggers an event when a specified number of bytes of
  66. * data have been written to it. The event can be used, for example, to throw
  67. * an exception if a maximum has been reached, or to switch the underlying
  68. * stream type when the threshold is exceeded.
  69. * <p>
  70. * This class overrides all <code>OutputStream</code> methods. However, these
  71. * overrides ultimately call the corresponding methods in the underlying output
  72. * stream implementation.
  73. * <p>
  74. * NOTE: This implementation may trigger the event <em>before</em> the threshold
  75. * is actually reached, since it triggers when a pending write operation would
  76. * cause the threshold to be exceeded.
  77. *
  78. * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
  79. *
  80. * @version $Id: ThresholdingOutputStream.java,v 1.3 2003/05/31 22:31:08 martinc Exp $
  81. */
  82. public abstract class ThresholdingOutputStream
  83. extends OutputStream
  84. {
  85. // ----------------------------------------------------------- Data members
  86. /**
  87. * The threshold at which the event will be triggered.
  88. */
  89. private int threshold;
  90. /**
  91. * The number of bytes written to the output stream.
  92. */
  93. private long written;
  94. /**
  95. * Whether or not the configured threshold has been exceeded.
  96. */
  97. private boolean thresholdExceeded;
  98. // ----------------------------------------------------------- Constructors
  99. /**
  100. * Constructs an instance of this class which will trigger an event at the
  101. * specified threshold.
  102. *
  103. * @param threshold The number of bytes at which to trigger an event.
  104. */
  105. public ThresholdingOutputStream(int threshold)
  106. {
  107. this.threshold = threshold;
  108. }
  109. // --------------------------------------------------- OutputStream methods
  110. /**
  111. * Writes the specified byte to this output stream.
  112. *
  113. * @param b The byte to be written.
  114. *
  115. * @exception IOException if an error occurs.
  116. */
  117. public void write(int b) throws IOException
  118. {
  119. checkThreshold(1);
  120. getStream().write(b);
  121. written++;
  122. }
  123. /**
  124. * Writes <code>b.length</code> bytes from the specified byte array to this
  125. * output stream.
  126. *
  127. * @param b The array of bytes to be written.
  128. *
  129. * @exception IOException if an error occurs.
  130. */
  131. public void write(byte b[]) throws IOException
  132. {
  133. checkThreshold(b.length);
  134. getStream().write(b);
  135. written += b.length;
  136. }
  137. /**
  138. * Writes <code>len</code> bytes from the specified byte array starting at
  139. * offset <code>off</code> to this output stream.
  140. *
  141. * @param b The byte array from which the data will be written.
  142. * @param off The start offset in the byte array.
  143. * @param len The number of bytes to write.
  144. *
  145. * @exception IOException if an error occurs.
  146. */
  147. public void write(byte b[], int off, int len) throws IOException
  148. {
  149. checkThreshold(len);
  150. getStream().write(b, off, len);
  151. written += len;
  152. }
  153. /**
  154. * Flushes this output stream and forces any buffered output bytes to be
  155. * written out.
  156. *
  157. * @exception IOException if an error occurs.
  158. */
  159. public void flush() throws IOException
  160. {
  161. getStream().flush();
  162. }
  163. /**
  164. * Closes this output stream and releases any system resources associated
  165. * with this stream.
  166. *
  167. * @exception IOException if an error occurs.
  168. */
  169. public void close() throws IOException
  170. {
  171. try
  172. {
  173. flush();
  174. }
  175. catch (IOException ignored)
  176. {
  177. // ignore
  178. }
  179. getStream().close();
  180. }
  181. // --------------------------------------------------------- Public methods
  182. /**
  183. * Returns the threshold, in bytes, at which an event will be triggered.
  184. *
  185. * @return The threshold point, in bytes.
  186. */
  187. public int getThreshold()
  188. {
  189. return threshold;
  190. }
  191. /**
  192. * Returns the number of bytes that have been written to this output stream.
  193. *
  194. * @return The number of bytes written.
  195. */
  196. public long getByteCount()
  197. {
  198. return written;
  199. }
  200. /**
  201. * Determines whether or not the configured threshold has been exceeded for
  202. * this output stream.
  203. *
  204. * @return <code>true</code> if the threshold has been reached;
  205. * <code>false</code> otherwise.
  206. */
  207. public boolean isThresholdExceeded()
  208. {
  209. return (written > threshold);
  210. }
  211. // ------------------------------------------------------ Protected methods
  212. /**
  213. * Checks to see if writing the specified number of bytes would cause the
  214. * configured threshold to be exceeded. If so, triggers an event to allow
  215. * a concrete implementation to take action on this.
  216. *
  217. * @param count The number of bytes about to be written to the underlying
  218. * output stream.
  219. *
  220. * @exception IOException if an error occurs.
  221. */
  222. protected void checkThreshold(int count) throws IOException
  223. {
  224. if (!thresholdExceeded && (written + count > threshold))
  225. {
  226. thresholdReached();
  227. thresholdExceeded = true;
  228. }
  229. }
  230. // ------------------------------------------------------- Abstract methods
  231. /**
  232. * Returns the underlying output stream, to which the corresponding
  233. * <code>OutputStream</code> methods in this class will ultimately delegate.
  234. *
  235. * @return The underlying output stream.
  236. *
  237. * @exception IOException if an error occurs.
  238. */
  239. protected abstract OutputStream getStream() throws IOException;
  240. /**
  241. * Indicates that the configured threshold has been reached, and that a
  242. * subclass should take whatever action necessary on this event. This may
  243. * include changing the underlying output stream.
  244. *
  245. * @exception IOException if an error occurs.
  246. */
  247. protected abstract void thresholdReached() throws IOException;
  248. }