001: /*--
002:
003: Copyright (C) 2000-2003 Anthony Eden.
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009:
010: 1. Redistributions of source code must retain the above copyright
011: notice, this list of conditions, and the following disclaimer.
012:
013: 2. Redistributions in binary form must reproduce the above copyright
014: notice, this list of conditions, and the disclaimer that follows
015: these conditions in the documentation and/or other materials
016: provided with the distribution.
017:
018: 3. The name "EdenLib" must not be used to endorse or promote products
019: derived from this software without prior written permission. For
020: written permission, please contact me@anthonyeden.com.
021:
022: 4. Products derived from this software may not be called "EdenLib", nor
023: may "EdenLib" appear in their name, without prior written permission
024: from Anthony Eden (me@anthonyeden.com).
025:
026: In addition, I request (but do not require) that you include in the
027: end-user documentation provided with the redistribution and/or in the
028: software itself an acknowledgement equivalent to the following:
029: "This product includes software developed by
030: Anthony Eden (http://www.anthonyeden.com/)."
031:
032: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
033: WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
034: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
035: DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
036: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
037: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
038: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
039: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
040: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
041: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
042: POSSIBILITY OF SUCH DAMAGE.
043:
044: For more information on EdenLib, please see <http://edenlib.sf.net/>.
045:
046: */
047:
048: package com.anthonyeden.lib.io;
049:
050: import java.io.OutputStream;
051: import java.io.FilterOutputStream;
052: import java.io.IOException;
053: import java.util.ArrayList;
054: import java.util.Iterator;
055:
056: import javax.swing.event.ChangeListener;
057: import javax.swing.event.ChangeEvent;
058:
059: /** A FilterOutputStream which will keep track of the number of bytes
060: written to the underlying stream. Callers who want to know how many
061: bytes have been written should attach a ChangeListener and call getCount()
062: whenever a change event is fired.
063:
064: <p>If no ChangeListeners are attached then this stream will not fire
065: events. This improves performance by only firing events when at least
066: one object is expecting them.
067:
068: @author Anthony Eden
069: */
070:
071: public class ByteCountOutputStream extends FilterOutputStream {
072:
073: private long count = 0;
074: private ArrayList changeListeners;
075: private boolean fireEventRequired = false;
076:
077: public ByteCountOutputStream(OutputStream out) {
078: super (out);
079: }
080:
081: /** Add a changeListeners.
082:
083: @param l The ChangeListener
084: */
085:
086: public void addChangeListener(ChangeListener l) {
087: getChangeListeners().add(l);
088: fireEventRequired = true;
089: }
090:
091: /** Remove a ChangeListener.
092:
093: @param l The ChangeListener
094: */
095:
096: public void removeChangeListener(ChangeListener l) {
097: ArrayList changeListeners = getChangeListeners();
098: changeListeners.remove(l);
099: if (changeListeners.size() == 0) {
100: fireEventRequired = false;
101: }
102: }
103:
104: /** Write the buffer to the stream.
105:
106: @param buffer The buffer to write
107: @return The number of bytes written
108: @throws IOException
109: */
110:
111: public void write(byte[] buffer) throws IOException {
112: out.write(buffer);
113: count += buffer.length;
114: if (fireEventRequired)
115: fireStateChanged();
116: }
117:
118: /** Write the buffer to the stream with bytes starting at the given offset
119: of the buffer and reading for <code>length</code> number of bytes.
120:
121: @param buffer The buffer
122: @param offset The buffer offset
123: @param length The number of bytes to write
124: @return The number of bytes written
125: @throws IOException
126: */
127:
128: public void write(byte[] buffer, int offset, int length)
129: throws IOException {
130: out.write(buffer, offset, length);
131: count += length;
132: if (fireEventRequired)
133: fireStateChanged();
134: }
135:
136: /** Write one byte.
137:
138: @return The byte
139: @throws IOException
140: */
141:
142: public void write(int b) throws IOException {
143: out.write(b);
144: count++;
145: if (fireEventRequired)
146: fireStateChanged();
147: }
148:
149: /** Get the number of bytes written so far.
150:
151: @return The byte count
152: */
153:
154: public long getCount() {
155: return count;
156: }
157:
158: /** Get a List of attached ChangeListeners.
159:
160: @return The List of ChangeListeners
161: */
162:
163: protected synchronized ArrayList getChangeListeners() {
164: if (changeListeners == null) {
165: changeListeners = new ArrayList();
166: }
167: return changeListeners;
168: }
169:
170: /** Fire a ChangeEvent. */
171:
172: protected void fireStateChanged() {
173: ChangeEvent evt = new ChangeEvent(this );
174: ArrayList l;
175:
176: synchronized (this ) {
177: l = (ArrayList) (getChangeListeners().clone());
178: }
179:
180: Iterator i = l.iterator();
181: while (i.hasNext()) {
182: ((ChangeListener) i.next()).stateChanged(evt);
183: }
184: }
185:
186: }
|