/*
* $Id$
*
* Copyright (C) 2003-2015 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.shell.proclet;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import org.jnode.util.ProxyStream;
import org.jnode.util.ProxyStreamException;
/**
* This class provides a proxy mechanism for System.in. If the current thread is
* a member thread of a ProcletContext, operations are dispatched to the
* ProcletContext-specific 'standard input'. Otherwise, they go to the global
* standard input.
*
* @author crawley@jnode.org
*/
public class ProcletProxyInputStream extends InputStream implements
ProcletProxyStream<InputStream> {
private Map<Integer, InputStream> streamMap;
private int fd;
/**
* Construct a proxy input stream for a designated fd. Note that if the fd
* is non-zero, the proxy will not work in a non-ProcletContext context, and
* not work in the ProcletContext context if the fd doesn't correspond to an
* InputStream.
*
* @param is the initial value for globalInput.
* @param fd
*/
@SuppressWarnings("unchecked")
public ProcletProxyInputStream(InputStream is, int fd) {
this.fd = fd;
streamMap = new HashMap<Integer, InputStream>();
if (is == null) {
throw new IllegalArgumentException("null stream");
}
if (is instanceof ProxyStream<?>) {
is = ((ProxyStream<InputStream>) is).getProxiedStream();
}
streamMap.put(ProcletIOContext.GLOBAL_STREAM_ID, is);
}
/**
* Construct a proxy input stream based on the state of the supplied proxy.
* The new proxy has all entries of the existing one except that the entry
* for pid is set / reset to in.
*
* @param proxy
* @param is
* @param pid
*/
@SuppressWarnings("unchecked")
public ProcletProxyInputStream(ProcletProxyInputStream proxy, InputStream is,
int pid) {
if (is == null) {
throw new IllegalArgumentException("null stream");
}
if (is instanceof ProxyStream<?>) {
is = ((ProxyStream<InputStream>) is).getProxiedStream();
}
streamMap = new HashMap<Integer, InputStream>(proxy.streamMap);
streamMap.put(pid, is);
fd = proxy.fd;
}
@Override
public int read() throws IOException {
return getRealStream().read();
}
@Override
public int available() throws IOException {
return getRealStream().available();
}
@Override
public void close() throws IOException {
// TODO - should we intercept attempts to close the global stdin?
getRealStream().close();
}
@Override
public void mark(int readLimit) {
getRealStream().mark(readLimit);
}
@Override
public boolean markSupported() {
return getRealStream().markSupported();
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return getRealStream().read(b, off, len);
}
@Override
public int read(byte[] b) throws IOException {
return getRealStream().read(b);
}
@Override
public void reset() throws IOException {
getRealStream().reset();
}
@Override
public long skip(long n) throws IOException {
return getRealStream().skip(n);
}
public InputStream getRealStream() throws ProxyStreamException {
InputStream is = getProxiedStream();
if (is instanceof ProxyStream) {
return (InputStream) ((ProxyStream<?>) is).getRealStream();
} else {
return is;
}
}
public InputStream getProxiedStream() throws ProxyStreamException {
Proclet procletContext = Proclet.currentProcletContext();
int pid = (procletContext == null) ?
ProcletIOContext.GLOBAL_STREAM_ID : procletContext.getPid();
InputStream is = streamMap.get(pid);
if (is == null) {
throw new ProxyStreamException(
"Proclet stream not set (fd = " + fd + ")");
} else if (is instanceof ProcletProxyStream) {
throw new ProxyStreamException(
"Proclet stream points to another proclet stream (fd = " + fd + ")");
}
return is;
}
InputStream getProxiedStream(int pid) {
InputStream is = streamMap.get(pid);
if (is == null && pid != ProcletIOContext.GLOBAL_STREAM_ID) {
is = streamMap.get(ProcletIOContext.GLOBAL_STREAM_ID);
}
return is;
}
}