001 package org.crsh.util; 002 003 import java.io.IOException; 004 import java.io.InterruptedIOException; 005 import java.util.LinkedList; 006 007 /** 008 * A combination of an {@link InputStream} and an {@link OutputStream}, simpler than what java provides 009 * and more suitable for unit testing. This class is not optimized for performance. 010 * 011 * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> 012 */ 013 public class PipedChannel { 014 015 /** . */ 016 private final LinkedList<Integer> queue; 017 018 /** . */ 019 private final Object lock; 020 021 /** . */ 022 private boolean closed; 023 024 /** . */ 025 private InputStream in; 026 027 /** . */ 028 private OutputStream out; 029 030 public PipedChannel() { 031 this.queue = new LinkedList<Integer>(); 032 this.lock = new Object(); 033 this.closed = false; 034 in = new InputStream(); 035 out = new OutputStream(); 036 } 037 038 public InputStream getIn() { 039 return in; 040 } 041 042 public OutputStream getOut() { 043 return out; 044 } 045 046 class InputStream extends java.io.InputStream { 047 @Override 048 public int read() throws IOException { 049 synchronized (lock) { 050 while (true) { 051 if (queue.size() > 0) { 052 return queue.removeFirst(); 053 } else { 054 if (closed) { 055 throw new IOException("closed"); 056 } else { 057 try { 058 lock.wait(); 059 } 060 catch (InterruptedException e) { 061 InterruptedIOException iioe = new InterruptedIOException(); 062 iioe.initCause(e); 063 throw iioe; 064 } 065 } 066 } 067 } 068 } 069 } 070 071 @Override 072 public void close() throws IOException { 073 synchronized (lock) { 074 if (!closed) { 075 closed = true; 076 lock.notifyAll(); 077 } 078 } 079 } 080 } 081 082 class OutputStream extends java.io.OutputStream { 083 @Override 084 public void write(int b) throws IOException { 085 synchronized (lock) { 086 if (closed) { 087 throw new IOException("closed"); 088 } 089 queue.add(b); 090 } 091 } 092 093 @Override 094 public void flush() throws IOException { 095 synchronized (lock) { 096 if (closed) { 097 throw new IOException("closed"); 098 } 099 lock.notifyAll(); 100 } 101 } 102 103 @Override 104 public void close() throws IOException { 105 synchronized (lock) { 106 if (!closed) { 107 closed = true; 108 lock.notifyAll(); 109 } 110 } 111 } 112 } 113 }