/*
* $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.InputStream;
import java.io.PrintStream;
import java.util.Map;
import java.util.Properties;
import org.jnode.vm.IOContext;
import org.jnode.vm.VmIOContext;
import org.jnode.vm.VmSystem;
/**
* The ProcletIOContext is an IOContext implementation that uses Proxy streams to
* direct System.in/out/err traffic to different places depending on the current
* proclet. The System properties and 'env' are also 'procletized' in this
* implementation.
* <p>
* A JNode isolate is switched to 'proclet mode" by calling
* {@link VmSystem#switchToExternalIOContext(IOContext)}.
* In theory, calling {@link VmSystem#resetIOContext()} will return the isolate
* to "normal mode". However, doing this abruptly cause any remaining
* proclets' procletized state to abruptly revert to the isolate-global version
* of that state.
*
* @author Levente S\u00e1ntha
* @author crawley@jnode.org
*/
public class ProcletIOContext implements IOContext {
public static final int GLOBAL_STREAM_ID = Proclet.NO_SUCH_PID;
public ProcletIOContext() {
}
public synchronized void setSystemIn(InputStream is) {
int pid = getCurrentPid();
if (is instanceof ProcletProxyInputStream) {
is = ((ProcletProxyInputStream) is).getProxiedStream(pid);
}
ProcletProxyInputStream newProxyStream = new ProcletProxyInputStream(
(ProcletProxyInputStream) System.in, is, pid);
VmSystem.setStaticField(System.class, "in", newProxyStream);
}
public synchronized void setSystemOut(PrintStream ps) {
int pid = getCurrentPid();
if (ps instanceof ProcletProxyPrintStream) {
ps = ((ProcletProxyPrintStream) ps).getProxiedStream(pid);
}
ProcletProxyPrintStream newProxyStream = new ProcletProxyPrintStream(
(ProcletProxyPrintStream) System.out, ps, pid);
VmSystem.setStaticField(System.class, "out", newProxyStream);
}
public synchronized void setSystemErr(PrintStream ps) {
int pid = getCurrentPid();
if (ps instanceof ProcletProxyPrintStream) {
ps = ((ProcletProxyPrintStream) ps).getProxiedStream(pid);
}
ProcletProxyPrintStream newProxyStream = new ProcletProxyPrintStream(
(ProcletProxyPrintStream) System.err, ps, pid);
VmSystem.setStaticField(System.class, "err", newProxyStream);
}
public Map<String, String> getEnv() {
Proclet proclet = Proclet.currentProcletContext();
if (proclet != null) {
return proclet.getEnvironment();
} else {
return VmIOContext.getGlobalEnv();
}
}
public Properties getProperties() {
Proclet proclet = Proclet.currentProcletContext();
if (proclet != null) {
return proclet.getProperties();
} else {
return VmIOContext.getGlobalProperties();
}
}
public void setEnv(Map<String, String> env) {
Proclet proclet = Proclet.currentProcletContext();
if (proclet != null) {
proclet.setEnvironment(env);
} else {
VmIOContext.setGlobalEnv(env);
}
}
public void setProperties(Properties props) {
Proclet proclet = Proclet.currentProcletContext();
if (proclet != null) {
proclet.setProperties(props);
} else {
VmIOContext.setGlobalProperties(props);
}
}
private int getCurrentPid() {
Proclet procletContext = Proclet.currentProcletContext();
return (procletContext == null) ? GLOBAL_STREAM_ID : procletContext.getPid();
}
public synchronized void enterContext() {
VmSystem.setStaticField(System.class, "in",
new ProcletProxyInputStream(System.in, 0));
VmSystem.setStaticField(System.class, "out",
new ProcletProxyPrintStream(System.out, 1));
VmSystem.setStaticField(System.class, "err",
new ProcletProxyPrintStream(System.err, 2));
}
public synchronized void exitContext() {
InputStream in = VmIOContext.getGlobalInStream();
PrintStream out = VmIOContext.getGlobalOutStream();
PrintStream err = VmIOContext.getGlobalErrStream();
if (in instanceof ProcletProxyStream) {
throw new ProcletException(
"Cannot reset in to a proclet proxy stream");
}
if (out instanceof ProcletProxyStream) {
throw new ProcletException(
"Cannot reset out to a proclet proxy stream");
}
if (err instanceof ProcletProxyStream) {
throw new ProcletException(
"Cannot reset err to a proclet proxy stream");
}
VmSystem.setStaticField(System.class, "in", in);
VmSystem.setStaticField(System.class, "out", out);
VmSystem.setStaticField(System.class, "err", err);
}
public synchronized PrintStream getRealSystemErr() {
return ((ProcletProxyPrintStream) System.err).getProxiedStream(getCurrentPid());
}
public synchronized InputStream getRealSystemIn() {
return ((ProcletProxyInputStream) System.in).getProxiedStream(getCurrentPid());
}
public synchronized PrintStream getRealSystemOut() {
return ((ProcletProxyPrintStream) System.out).getProxiedStream(getCurrentPid());
}
synchronized void setStreamsForNewProclet(int pid, Object[] streams) {
ProcletProxyInputStream in = new ProcletProxyInputStream(
(ProcletProxyInputStream) System.in, (InputStream) streams[0], pid);
ProcletProxyPrintStream out = new ProcletProxyPrintStream(
(ProcletProxyPrintStream) System.out, (PrintStream) streams[1], pid);
ProcletProxyPrintStream err = new ProcletProxyPrintStream(
(ProcletProxyPrintStream) System.err, (PrintStream) streams[2], pid);
VmSystem.setStaticField(System.class, "in", in);
VmSystem.setStaticField(System.class, "out", out);
VmSystem.setStaticField(System.class, "err", err);
}
}