001/** 002 * 003 * Copyright 2003-2007 Jive Software. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smack.util; 018 019import java.io.*; 020import java.util.*; 021 022/** 023 * An ObservableReader is a wrapper on a Reader that notifies to its listeners when 024 * reading character streams. 025 * 026 * @author Gaston Dombiak 027 */ 028public class ObservableReader extends Reader { 029 030 Reader wrappedReader = null; 031 List<ReaderListener> listeners = new ArrayList<ReaderListener>(); 032 033 public ObservableReader(Reader wrappedReader) { 034 this.wrappedReader = wrappedReader; 035 } 036 037 public int read(char[] cbuf, int off, int len) throws IOException { 038 int count = wrappedReader.read(cbuf, off, len); 039 if (count > 0) { 040 String str = new String(cbuf, off, count); 041 // Notify that a new string has been read 042 ReaderListener[] readerListeners = null; 043 synchronized (listeners) { 044 readerListeners = new ReaderListener[listeners.size()]; 045 listeners.toArray(readerListeners); 046 } 047 for (int i = 0; i < readerListeners.length; i++) { 048 readerListeners[i].read(str); 049 } 050 } 051 return count; 052 } 053 054 public void close() throws IOException { 055 wrappedReader.close(); 056 } 057 058 public int read() throws IOException { 059 return wrappedReader.read(); 060 } 061 062 public int read(char cbuf[]) throws IOException { 063 return wrappedReader.read(cbuf); 064 } 065 066 public long skip(long n) throws IOException { 067 return wrappedReader.skip(n); 068 } 069 070 public boolean ready() throws IOException { 071 return wrappedReader.ready(); 072 } 073 074 public boolean markSupported() { 075 return wrappedReader.markSupported(); 076 } 077 078 public void mark(int readAheadLimit) throws IOException { 079 wrappedReader.mark(readAheadLimit); 080 } 081 082 public void reset() throws IOException { 083 wrappedReader.reset(); 084 } 085 086 /** 087 * Adds a reader listener to this reader that will be notified when 088 * new strings are read. 089 * 090 * @param readerListener a reader listener. 091 */ 092 public void addReaderListener(ReaderListener readerListener) { 093 if (readerListener == null) { 094 return; 095 } 096 synchronized (listeners) { 097 if (!listeners.contains(readerListener)) { 098 listeners.add(readerListener); 099 } 100 } 101 } 102 103 /** 104 * Removes a reader listener from this reader. 105 * 106 * @param readerListener a reader listener. 107 */ 108 public void removeReaderListener(ReaderListener readerListener) { 109 synchronized (listeners) { 110 listeners.remove(readerListener); 111 } 112 } 113 114}