1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package jdk.jshell.execution; 26 27 import java.io.IOException; 28 import java.io.InputStream; 29 import java.io.OutputStream; 30 31 /** 32 * 33 * @author Jan Lahoda 34 */ 35 class PipeInputStream extends InputStream { 36 37 private static final int INITIAL_SIZE = 128; 38 private int[] buffer = new int[INITIAL_SIZE]; 39 private int start; 40 private int end; 41 private boolean closed; 42 43 @Override 44 public synchronized int read() throws IOException { 45 if (start == end) { 46 inputNeeded(); 47 } 48 while (start == end) { 49 if (closed) { 50 return -1; 51 } 52 try { 53 wait(); 54 } catch (InterruptedException ex) { 55 //ignore 56 } 57 } 58 try { 59 return buffer[start]; 60 } finally { 61 start = (start + 1) % buffer.length; 62 } 63 } 64 65 protected void inputNeeded() throws IOException {} 66 67 private synchronized void write(int b) { 68 if (closed) { 69 throw new IllegalStateException("Already closed."); 70 } 71 int newEnd = (end + 1) % buffer.length; 72 if (newEnd == start) { 73 //overflow: 74 int[] newBuffer = new int[buffer.length * 2]; 75 int rightPart = (end > start ? end : buffer.length) - start; 76 int leftPart = end > start ? 0 : start - 1; 77 System.arraycopy(buffer, start, newBuffer, 0, rightPart); 78 System.arraycopy(buffer, 0, newBuffer, rightPart, leftPart); 79 buffer = newBuffer; 80 start = 0; 81 end = rightPart + leftPart; 82 newEnd = end + 1; 83 } 84 buffer[end] = b; 85 end = newEnd; 86 notifyAll(); 87 } 88 89 @Override 90 public synchronized void close() { 91 closed = true; 92 notifyAll(); 93 } 94 95 public OutputStream createOutput() { 96 return new OutputStream() { 97 @Override public void write(int b) throws IOException { 98 PipeInputStream.this.write(b); 99 } 100 @Override 101 public void write(byte[] b, int off, int len) throws IOException { 102 for (int i = 0 ; i < len ; i++) { 103 write(Byte.toUnsignedInt(b[off + i])); 104 } 105 } 106 @Override 107 public void close() throws IOException { 108 PipeInputStream.this.close(); 109 } 110 }; 111 } 112 113 }