package net.sf.beanlib.util; import java.io.Closeable; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import net.jcip.annotations.ThreadSafe; /** * @author Hanson Char */ @ThreadSafe public class TextIterable implements Iterable<String>, Closeable { private final URL url; private final List<LineIterator> openedIterators = new ArrayList<LineIterator>(); private volatile boolean returnNullUponEof; private String charsetname; private Charset charset; private CharsetDecoder charsetDecoder; public TextIterable(File file) throws MalformedURLException { this(file.toURI().toURL()); } public TextIterable(URL url) { this.url = url; } public TextIterable(String resourcePath) { this(Thread.currentThread().getContextClassLoader().getResource(resourcePath)); } @Override public LineIterator iterator() { LineIterator ret; final String charsetname; final Charset charset; final CharsetDecoder charsetDecoder; synchronized (this) { charsetname = this.charsetname; charset = this.charset; charsetDecoder = this.charsetDecoder; } try { if (charsetDecoder != null) ret = new LineIterator(this, url.openStream(), returnNullUponEof, charsetDecoder); else if (charset != null) ret = new LineIterator(this, url.openStream(), returnNullUponEof, charset); else if (charsetname != null) ret = new LineIterator(this, url.openStream(), returnNullUponEof, Charset.forName(charsetname)); else ret = new LineIterator(this, url.openStream(), returnNullUponEof, (Charset) null); synchronized (openedIterators) { openedIterators.add(ret); } return ret; } catch (IOException e) { throw new IllegalStateException(e); } } @Override public void close() { final LineIterator[] lineIterators; synchronized (openedIterators) { lineIterators = openedIterators.toArray(new LineIterator[openedIterators.size()]); for (Iterator<LineIterator> itr = openedIterators.iterator(); itr.hasNext();) { itr.next(); itr.remove(); } } for (LineIterator li : lineIterators) li.closeInPrivate(); } public int numberOfopenedIterators() { return openedIterators.size(); } void removeLineIterator(LineIterator li) { synchronized (openedIterators) { openedIterators.remove(li); } } public boolean isReturnNullUponEof() { return returnNullUponEof; } public void setReturnNullUponEof(boolean returnNullUponEof) { this.returnNullUponEof = returnNullUponEof; } public TextIterable withReturnNullUponEof(boolean returnNullUponEof) { setReturnNullUponEof(returnNullUponEof); return this; } public synchronized Charset getCharset() { return charset; } public synchronized void setCharset(Charset charset) { this.charset = charset; this.charsetname = null; this.charsetDecoder = null; } public TextIterable withCharset(Charset charset) { setCharset(charset); return this; } public synchronized CharsetDecoder getCharsetDecoder() { return charsetDecoder; } public synchronized void setCharsetDecoder(CharsetDecoder charsetDecoder) { this.charsetDecoder = charsetDecoder; this.charsetname = null; this.charset = null; } public TextIterable withCharsetDecoder(CharsetDecoder charsetDecoder) { setCharsetDecoder(charsetDecoder); return this; } public synchronized String getCharsetname() { return charsetname; } public synchronized void setCharsetname(String charsetname) { this.charsetname = charsetname; this.charset = null; this.charsetDecoder = null; } public TextIterable withCharsetname(String charsetname) { setCharsetname(charsetname); return this; } }