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.IOException; 020import java.io.Reader; 021import java.util.ArrayList; 022import java.util.List; 023 024 025/** 026 * An ObservableReader is a wrapper on a Reader that notifies to its listeners when 027 * reading character streams. 028 * 029 * @author Gaston Dombiak 030 */ 031public class ObservableReader extends Reader { 032 033 Reader wrappedReader = null; 034 final List<ReaderListener> listeners = new ArrayList<ReaderListener>(); 035 036 public ObservableReader(Reader wrappedReader) { 037 this.wrappedReader = wrappedReader; 038 } 039 040 @Override 041 public int read(char[] cbuf, int off, int len) throws IOException { 042 int count = wrappedReader.read(cbuf, off, len); 043 if (count > 0) { 044 String str = new String(cbuf, off, count); 045 // Notify that a new string has been read 046 ReaderListener[] readerListeners = null; 047 synchronized (listeners) { 048 readerListeners = new ReaderListener[listeners.size()]; 049 listeners.toArray(readerListeners); 050 } 051 for (int i = 0; i < readerListeners.length; i++) { 052 readerListeners[i].read(str); 053 } 054 } 055 return count; 056 } 057 058 @Override 059 public void close() throws IOException { 060 wrappedReader.close(); 061 } 062 063 @Override 064 public int read() throws IOException { 065 return wrappedReader.read(); 066 } 067 068 @Override 069 public int read(char[] cbuf) throws IOException { 070 return wrappedReader.read(cbuf); 071 } 072 073 @Override 074 public long skip(long n) throws IOException { 075 return wrappedReader.skip(n); 076 } 077 078 @Override 079 public boolean ready() throws IOException { 080 return wrappedReader.ready(); 081 } 082 083 @Override 084 public boolean markSupported() { 085 return wrappedReader.markSupported(); 086 } 087 088 @Override 089 public void mark(int readAheadLimit) throws IOException { 090 wrappedReader.mark(readAheadLimit); 091 } 092 093 @Override 094 public void reset() throws IOException { 095 wrappedReader.reset(); 096 } 097 098 /** 099 * Adds a reader listener to this reader that will be notified when 100 * new strings are read. 101 * 102 * @param readerListener a reader listener. 103 */ 104 public void addReaderListener(ReaderListener readerListener) { 105 if (readerListener == null) { 106 return; 107 } 108 synchronized (listeners) { 109 if (!listeners.contains(readerListener)) { 110 listeners.add(readerListener); 111 } 112 } 113 } 114 115 /** 116 * Removes a reader listener from this reader. 117 * 118 * @param readerListener a reader listener. 119 */ 120 public void removeReaderListener(ReaderListener readerListener) { 121 synchronized (listeners) { 122 listeners.remove(readerListener); 123 } 124 } 125 126}