001 /*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2013
005 * Space Science and Engineering Center (SSEC)
006 * University of Wisconsin - Madison
007 * 1225 W. Dayton Street, Madison, WI 53706, USA
008 * https://www.ssec.wisc.edu/mcidas
009 *
010 * All Rights Reserved
011 *
012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013 * some McIDAS-V source code is based on IDV and VisAD source code.
014 *
015 * McIDAS-V is free software; you can redistribute it and/or modify
016 * it under the terms of the GNU Lesser Public License as published by
017 * the Free Software Foundation; either version 3 of the License, or
018 * (at your option) any later version.
019 *
020 * McIDAS-V is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023 * GNU Lesser Public License for more details.
024 *
025 * You should have received a copy of the GNU Lesser Public License
026 * along with this program. If not, see http://www.gnu.org/licenses.
027 */
028
029 package edu.wisc.ssec.mcidasv.jython;
030
031 import static edu.wisc.ssec.mcidasv.util.Contract.notNull;
032
033 import java.io.ByteArrayOutputStream;
034 import java.io.IOException;
035 import java.io.OutputStream;
036 import java.io.UnsupportedEncodingException;
037 import java.util.Map;
038 import java.util.concurrent.ConcurrentHashMap;
039
040 public class OutputStreamDemux extends ByteArrayOutputStream {
041
042 protected enum OutputType { NORMAL, ERROR };
043
044 private OutputType type;
045
046 private final Map<String, ByteArrayOutputStream> streamMap = new ConcurrentHashMap<String, ByteArrayOutputStream>();
047 private final Map<String, Interpreter> interpreterMap = new ConcurrentHashMap<String, Interpreter>();
048 private final Map<String, Console> consoleMap = new ConcurrentHashMap<String, Console>();
049
050 private static String id() {
051 return Thread.currentThread().getName();
052 }
053
054 public synchronized void addStream(final Console console, final Interpreter interpreter, final OutputType type) {
055 notNull(console, "Cannot provide a null Jython console");
056 notNull(interpreter, "Cannot provide a null Jython interpreter");
057 this.type = notNull(type, "Cannot provide a null output type");
058 String threadId = id();
059 streamMap.put(threadId, new ByteArrayOutputStream());
060 interpreterMap.put(threadId, interpreter);
061 consoleMap.put(threadId, console);
062 }
063
064 @Override public void close() throws IOException {
065 streamMap.get(id()).close();
066 }
067
068 @Override public synchronized void flush() throws IOException {
069 streamMap.get(id()).flush();
070 Console console = consoleMap.get(id());
071 Interpreter interpreter = interpreterMap.get(id());
072 interpreter.handleStreams(console, null);
073 }
074
075 @Override public void write(byte[] b) throws IOException {
076 streamMap.get(id()).write(b);
077 }
078
079 @Override public void write(byte[] b, int off, int len) {
080 streamMap.get(id()).write(b, off, len);
081 }
082
083 @Override public void write(int b) {
084 streamMap.get(id()).write(b);
085 }
086
087 @Override public void reset() {
088 streamMap.get(id()).reset();
089 }
090
091 @Override public int size() {
092 return streamMap.get(id()).size();
093 }
094
095 @Override public byte[] toByteArray() {
096 return streamMap.get(id()).toByteArray();
097 }
098
099 @Deprecated @Override public String toString(int hibyte) {
100 return streamMap.get(id()).toString();
101 }
102
103 @Override public String toString(String charsetName) throws UnsupportedEncodingException {
104 return streamMap.get(id()).toString(charsetName);
105 }
106
107 @Override public void writeTo(OutputStream out) throws IOException {
108 streamMap.get(id()).writeTo(out);
109 }
110
111 @Override public String toString() {
112 ByteArrayOutputStream stream = streamMap.get(id());
113 if (stream == null) {
114 return "null";
115 } else {
116 return stream.toString();
117 }
118 }
119 }