/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.truffle.tools.chromeinspector;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Reader;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
public final class OutputHandler {
final ListeneableOutputStream out = new ListeneableOutputStream();
final ListeneableOutputStream err = new ListeneableOutputStream();
public OutputStream getOut() {
return out;
}
public OutputStream getErr() {
return err;
}
void setOutListener(Listener l) {
out.l = l;
}
void setErrListener(Listener l) {
err.l = l;
}
private static class ListeneableOutputStream extends OutputStream {
private final CharBuffer cb = CharBuffer.allocate(8192);
private final RBCH rbch = new RBCH();
private final Reader r = Channels.newReader(rbch, "UTF-8");
volatile Listener l;
@Override
public void write(int b) throws IOException {
rbch.put((byte) b);
wl();
}
@Override
public void write(byte[] b) throws IOException {
rbch.put(b);
wl();
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
rbch.put(b, off, len);
wl();
}
private void wl() throws IOException {
if (l == null) {
return;
}
while (!rbch.isEmpty()) {
int n = r.read(cb);
if (n == 0) {
break;
}
cb.flip();
String str = cb.toString();
l.outputText(str);
cb.clear();
}
}
private class RBCH implements ReadableByteChannel {
private byte[] b;
private int off;
private int len;
@SuppressWarnings("hiding")
void put(int b) {
this.b = new byte[]{(byte) b};
this.off = 0;
this.len = 1;
}
@SuppressWarnings("hiding")
void put(byte[] b) {
put(b, 0, b.length);
}
@SuppressWarnings("hiding")
void put(byte[] b, int off, int len) {
this.b = b;
this.off = off;
this.len = len;
}
boolean isEmpty() {
return len == 0;
}
@Override
public int read(ByteBuffer dst) throws IOException {
if (len == 0) {
return 0;
}
int n = dst.remaining();
n = Math.min(n, len);
dst.put(b, off, n);
off += n;
len -= n;
return n;
}
@Override
public boolean isOpen() {
return true;
}
@Override
public void close() throws IOException {
}
}
}
interface Listener {
void outputText(String str);
}
public interface Provider {
OutputHandler getOutputHandler();
}
}