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.InputStream;
051: import java.io.FilterInputStream;
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 FilterInputStream which will keep track of the number of bytes
060: read from the underlying stream. Callers who want to know how many
061: bytes have been read 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 ByteCountInputStream extends FilterInputStream {
072:
073: private long count = 0;
074: private ArrayList changeListeners;
075:
076: // events won't be fired if there are no listeners
077: // this should speed up throughput when there are no
078: // listeners
079:
080: private boolean fireEventRequired = false;
081:
082: /** Construct a new ByteCountInputStream.
083:
084: @param in The input stream to count
085: */
086:
087: public ByteCountInputStream(InputStream in) {
088: super (in);
089: }
090:
091: /** Add a ChangeListener.
092:
093: @param l The ChangeListener
094: */
095:
096: public void addChangeListener(ChangeListener l) {
097: getChangeListeners().add(l);
098: fireEventRequired = true;
099: }
100:
101: /** Remove the ChangeListener.
102:
103: @param l The ChangeListener
104: */
105:
106: public void removeChangeListener(ChangeListener l) {
107: ArrayList changeListeners = getChangeListeners();
108: changeListeners.remove(l);
109: if (changeListeners.size() == 0) {
110: fireEventRequired = false;
111: }
112: }
113:
114: /** Fill the buffer with bytes until the buffer is full, the stream
115: blocks, or until the end of the stream.
116:
117: @param buffer The buffer to fill
118: @return The number of bytes read
119: @throws IOException
120: */
121:
122: public int read(byte[] buffer) throws IOException {
123: int bytesRead = in.read(buffer);
124: count += bytesRead;
125: if (fireEventRequired)
126: fireStateChanged();
127: return bytesRead;
128: }
129:
130: /** Fill the buffer with bytes starting at the given offset of the buffer
131: and reading for <code>length</code> number of bytes.
132:
133: @param buffer The buffer
134: @param offset The buffer offset
135: @param length The number of bytes to read
136: @return The number of bytes read
137: @throws IOException
138: */
139:
140: public int read(byte[] buffer, int offset, int length)
141: throws IOException {
142: int bytesRead = in.read(buffer, offset, length);
143: count += bytesRead;
144: if (fireEventRequired)
145: fireStateChanged();
146: return bytesRead;
147: }
148:
149: /** Read one byte.
150:
151: @return The byte
152: @throws IOException
153: */
154:
155: public int read() throws IOException {
156: int b = in.read();
157: count++;
158: if (fireEventRequired)
159: fireStateChanged();
160: return b;
161: }
162:
163: /** Get the number of bytes read so far.
164:
165: @return The byte count
166: */
167:
168: public long getCount() {
169: return count;
170: }
171:
172: /** Get a List of attached ChangeListeners.
173:
174: @return The List of ChangeListeners
175: */
176:
177: protected synchronized ArrayList getChangeListeners() {
178: if (changeListeners == null) {
179: changeListeners = new ArrayList();
180: }
181: return changeListeners;
182: }
183:
184: /** Fire a ChangeEvent. */
185:
186: protected void fireStateChanged() {
187: ChangeEvent evt = new ChangeEvent(this );
188: ArrayList l;
189:
190: synchronized (this ) {
191: l = (ArrayList) (getChangeListeners().clone());
192: }
193:
194: Iterator i = l.iterator();
195: while (i.hasNext()) {
196: ((ChangeListener) i.next()).stateChanged(evt);
197: }
198: }
199:
200: }
|