1/** 2 * $RCSfile$ 3 * $Revision$ 4 * $Date$ 5 * 6 * Copyright 2003-2007 Jive Software. 7 * 8 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21package org.jivesoftware.smack.util; 22 23import java.io.*; 24import java.util.*; 25 26/** 27 * An ObservableReader is a wrapper on a Reader that notifies to its listeners when 28 * reading character streams. 29 * 30 * @author Gaston Dombiak 31 */ 32public class ObservableReader extends Reader { 33 34 Reader wrappedReader = null; 35 List<ReaderListener> listeners = new ArrayList<ReaderListener>(); 36 37 public ObservableReader(Reader wrappedReader) { 38 this.wrappedReader = wrappedReader; 39 } 40 41 public int read(char[] cbuf, int off, int len) throws IOException { 42 int count = wrappedReader.read(cbuf, off, len); 43 if (count > 0) { 44 String str = new String(cbuf, off, count); 45 // Notify that a new string has been read 46 ReaderListener[] readerListeners = null; 47 synchronized (listeners) { 48 readerListeners = new ReaderListener[listeners.size()]; 49 listeners.toArray(readerListeners); 50 } 51 for (int i = 0; i < readerListeners.length; i++) { 52 readerListeners[i].read(str); 53 } 54 } 55 return count; 56 } 57 58 public void close() throws IOException { 59 wrappedReader.close(); 60 } 61 62 public int read() throws IOException { 63 return wrappedReader.read(); 64 } 65 66 public int read(char cbuf[]) throws IOException { 67 return wrappedReader.read(cbuf); 68 } 69 70 public long skip(long n) throws IOException { 71 return wrappedReader.skip(n); 72 } 73 74 public boolean ready() throws IOException { 75 return wrappedReader.ready(); 76 } 77 78 public boolean markSupported() { 79 return wrappedReader.markSupported(); 80 } 81 82 public void mark(int readAheadLimit) throws IOException { 83 wrappedReader.mark(readAheadLimit); 84 } 85 86 public void reset() throws IOException { 87 wrappedReader.reset(); 88 } 89 90 /** 91 * Adds a reader listener to this reader that will be notified when 92 * new strings are read. 93 * 94 * @param readerListener a reader listener. 95 */ 96 public void addReaderListener(ReaderListener readerListener) { 97 if (readerListener == null) { 98 return; 99 } 100 synchronized (listeners) { 101 if (!listeners.contains(readerListener)) { 102 listeners.add(readerListener); 103 } 104 } 105 } 106 107 /** 108 * Removes a reader listener from this reader. 109 * 110 * @param readerListener a reader listener. 111 */ 112 public void removeReaderListener(ReaderListener readerListener) { 113 synchronized (listeners) { 114 listeners.remove(readerListener); 115 } 116 } 117 118} 119