// Copyright (c) 2014 Tom Zhou<iwebpp@gmail.com> package com.iwebpp.node.stream; import java.nio.ByteBuffer; import com.iwebpp.node.EventEmitter; import com.iwebpp.node.NodeContext; import com.iwebpp.node.Util; public final class WrapReadable2 extends Readable2 { private final static String TAG = "WrapReadable2"; private Readable stream; private State state; boolean paused; public WrapReadable2(NodeContext context, Options options, Readable oldstream) throws Exception { super(context, options); // TODO Auto-generated constructor stub stream = oldstream; state = get_readableState(); paused = false; final Readable2 self = this; stream.on("end", new EventEmitter.Listener() { @Override public void onEvent(Object data) throws Exception { debug(TAG, "wrapped end"); if (state.getDecoder()!=null && !state.isEnded()) { /*var chunk = state.decoder.end(); if (chunk && chunk.length) self.push(chunk); */ // Reset decoder anyway /* CharBuffer cbuf = CharBuffer.allocate(1024 * 1024); state.getDecoder().flush(cbuf); String chunk = cbuf.toString(); if (chunk!=null && Util.chunkLength(chunk)>0) { self.push(chunk, null); }*/ state.getDecoder().reset(); } self.push(null, null); } }); stream.on("data", new EventEmitter.Listener() { @Override public void onEvent(Object chunk) throws Exception { debug(TAG, "wrapped data"); if (state.getDecoder() != null) ///chunk = state.decoder.write(chunk); chunk = state.getDecoder().decode((ByteBuffer) chunk).toString(); if (chunk==null || !state.isObjectMode() && Util.chunkLength(chunk)==0) return; boolean ret = self.push(chunk, null); if (!ret) { paused = true; stream.pause(); } } }); // proxy all the other methods. // important when wrapping filters and duplexes. /*for (var i in stream) { if (util.isFunction(stream[i]) && util.isUndefined(this[i])) { this[i] = function(method) { return function() { return stream[method].apply(stream, arguments); }}(i); } }*/ // proxy certain important events. /*var events = ["error", "close", "destroy", "pause", "resume"]; events.forEach(function(ev) { stream.on(ev, self.emit.bind(self, ev)); });*/ stream.on("error", new EventEmitter.Listener() { @Override public void onEvent(Object data) throws Exception { self.emit("error", data); } }); stream.on("close", new EventEmitter.Listener() { @Override public void onEvent(Object data) throws Exception { self.emit("close", data); } }); stream.on("destroy", new EventEmitter.Listener() { @Override public void onEvent(Object data) throws Exception { self.emit("destroy", data); } }); stream.on("pause", new EventEmitter.Listener() { @Override public void onEvent(Object data) throws Exception { self.emit("pause", data); } }); stream.on("resume", new EventEmitter.Listener() { @Override public void onEvent(Object data) throws Exception { self.emit("resume", data); } }); } // when we try to consume some more bytes, simply unpause the // underlying stream. @Override protected void _read(int n) throws Exception { debug(TAG, "wrapped _read "+n); if (paused) { paused = false; stream.resume(); } } }