001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2016 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 029package edu.wisc.ssec.mcidasv.jython; 030 031import static java.util.Objects.requireNonNull; 032 033import java.io.ByteArrayOutputStream; 034import java.io.IOException; 035import java.io.OutputStream; 036import java.io.UnsupportedEncodingException; 037import java.util.Map; 038import java.util.concurrent.ConcurrentHashMap; 039 040public 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<>(); 047 private final Map<String, Interpreter> interpreterMap = new ConcurrentHashMap<>(); 048 private final Map<String, Console> consoleMap = new ConcurrentHashMap<>(); 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 requireNonNull(console, "Cannot provide a null Jython console"); 056 requireNonNull(interpreter, "Cannot provide a null Jython interpreter"); 057 this.type = requireNonNull(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}