/* * $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.PrintStream; 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.out,err. If the current * thread is a member thread of a ProcletContext, operations are dispatched to * the ProcletContext-specific 'standard output' or 'standard error'. Otherwise, * they go to the global 'standard' PrintStreams. * * @author crawley@jnode.org */ public class ProcletProxyPrintStream extends AbstractProxyPrintStream implements ProcletProxyStream<PrintStream> { private Map<Integer, PrintStream> streamMap; private final int fd; /** * Construct a proxy print stream with 'out' as the initial global stream. * * @param ps the global stream * @param fd the 'file descriptor' label for the stream. */ @SuppressWarnings("unchecked") public ProcletProxyPrintStream(PrintStream ps, int fd) { super(); if (ps == null) { throw new IllegalArgumentException("null stream"); } this.fd = fd; if (ps instanceof ProxyStream<?>) { ps = ((ProxyStream<PrintStream>) ps).getProxiedStream(); } streamMap = new HashMap<Integer, PrintStream>(); streamMap.put(ProcletIOContext.GLOBAL_STREAM_ID, ps); } /** * Construct a proxy print 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 the proxy stream that supplies the base settings. * @param ps the new stream that we want to use. * @param pid the pid of the proclet that the stream to be used in. */ @SuppressWarnings("unchecked") public ProcletProxyPrintStream(ProcletProxyPrintStream proxy, PrintStream ps, int pid) { if (ps == null) { throw new IllegalArgumentException("null stream"); } if (ps instanceof ProxyStream<?>) { ps = ((ProxyStream<PrintStream>) ps).getProxiedStream(); } streamMap = new HashMap<Integer, PrintStream>(proxy.streamMap); streamMap.put(pid, ps); fd = proxy.fd; } /** * This method does the work of deciding which printstream to delegate to. * * @return the PrintStream we are currently delegating to. */ private PrintStream proxiedPrintStream() throws ProxyStreamException { Proclet procletContext = Proclet.currentProcletContext(); int pid = (procletContext == null) ? ProcletIOContext.GLOBAL_STREAM_ID : procletContext.getPid(); PrintStream ps = getProxiedStream(pid); if (ps == null) { throw new ProxyStreamException( "Proclet stream not set (fd = " + fd + ")"); } else if (ps instanceof ProcletProxyStream) { throw new ProxyStreamException( "Proclet stream points to another proclet stream (fd = " + fd + ")"); } return ps; } @SuppressWarnings("unchecked") public PrintStream getRealStream() throws ProxyStreamException { PrintStream ps = proxiedPrintStream(); if (ps instanceof ProxyStream) { return ((ProxyStream<PrintStream>) ps).getRealStream(); } else { return ps; } } protected PrintStream effectiveOutput() { return getRealStream(); } public PrintStream getProxiedStream() throws ProxyStreamException { return proxiedPrintStream(); } PrintStream getProxiedStream(int pid) { PrintStream ps = streamMap.get(pid); if (ps == null && pid != ProcletIOContext.GLOBAL_STREAM_ID) { ps = streamMap.get(ProcletIOContext.GLOBAL_STREAM_ID); } return ps; } }