001 /* 002 * Copyright (C) 2012 eXo Platform SAS. 003 * 004 * This is free software; you can redistribute it and/or modify it 005 * under the terms of the GNU Lesser General Public License as 006 * published by the Free Software Foundation; either version 2.1 of 007 * the License, or (at your option) any later version. 008 * 009 * This software is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * You should have received a copy of the GNU Lesser General Public 015 * License along with this software; if not, write to the Free 016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 018 */ 019 package org.crsh.console; 020 021 import org.crsh.text.Screenable; 022 import org.crsh.shell.ShellProcess; 023 import org.crsh.shell.ShellProcessContext; 024 import org.crsh.shell.ShellResponse; 025 import org.crsh.text.Style; 026 027 import java.io.IOException; 028 import java.util.concurrent.ArrayBlockingQueue; 029 import java.util.concurrent.atomic.AtomicReference; 030 031 /** 032 * A process execution state machine. 033 * 034 * @author Julien Viet 035 */ 036 class ProcessHandler extends Plugin implements ShellProcessContext { 037 038 /** 039 * A thread reading a line. 040 */ 041 class Reader { 042 final Thread thread; 043 final Editor editor; 044 final ArrayBlockingQueue<String> line; 045 Reader(Thread thread, boolean echo) { 046 this.thread = thread; 047 this.editor = new Editor(console, echo); 048 this.line = new ArrayBlockingQueue<String>(1); 049 } 050 } 051 052 /** . */ 053 final Console console; 054 055 /** . */ 056 final ShellProcess process; 057 058 /** Weather or not a thread is reading a line callback. */ 059 final AtomicReference<Reader> editor; 060 061 ProcessHandler(Console console, ShellProcess process) { 062 this.console = console; 063 this.process = process; 064 this.editor = new AtomicReference<Reader>(); 065 } 066 067 @Override 068 public boolean takeAlternateBuffer() throws IOException { 069 return console.driver.takeAlternateBuffer(); 070 } 071 072 @Override 073 public boolean releaseAlternateBuffer() throws IOException { 074 return console.driver.releaseAlternateBuffer(); 075 } 076 077 @Override 078 public String getProperty(String propertyName) { 079 return null; 080 } 081 082 @Override 083 public String readLine(String msg, boolean echo) throws IOException, InterruptedException { 084 Reader waiter = new Reader(Thread.currentThread(), echo); 085 if (editor.compareAndSet(null, waiter)) { 086 if (msg != null && msg.length() > 0) { 087 console.driver.write(msg); 088 console.driver.flush(); 089 } 090 console.iterate(); 091 try { 092 return waiter.line.take(); 093 } finally { 094 editor.set(null); 095 } 096 } else { 097 throw new IllegalStateException("A thread is already reading the line"); 098 } 099 } 100 101 @Override 102 public int getWidth() { 103 return console.driver.getWidth(); 104 } 105 106 @Override 107 public int getHeight() { 108 return console.driver.getHeight(); 109 } 110 111 @Override 112 public Screenable append(CharSequence s) throws IOException { 113 console.driver.write(s); 114 return this; 115 } 116 117 @Override 118 public Screenable append(char c) throws IOException { 119 console.driver.write(c); 120 return this; 121 } 122 123 @Override 124 public Screenable append(CharSequence csq, int start, int end) throws IOException { 125 console.driver.write(csq, start, end); 126 return this; 127 } 128 129 @Override 130 public Screenable append(Style style) throws IOException { 131 console.driver.write(style); 132 return this; 133 } 134 135 @Override 136 public Screenable cls() throws IOException { 137 console.driver.cls(); 138 return this; 139 } 140 141 @Override 142 public void flush() throws IOException { 143 console.driver.flush(); 144 } 145 146 147 @Override 148 public void end(ShellResponse response) { 149 150 // Interrupt reader 151 Reader reader = editor.get(); 152 if (reader != null) { 153 reader.thread.interrupt(); 154 } 155 156 // 157 if (response instanceof ShellResponse.Close) { 158 159 } else { 160 161 } 162 163 // Write message 164 try { 165 String msg = response.getMessage(); 166 if (msg.length() > 0) { 167 console.driver.write(msg); 168 } 169 console.driver.writeCRLF(); 170 console.driver.flush(); 171 } 172 catch (IOException e) { 173 // Log it 174 } 175 176 // 177 if (response instanceof ShellResponse.Close) { 178 console.close(); 179 } else { 180 // Put back editor and redraw prompt 181 console.edit(); 182 console.iterate(); 183 } 184 } 185 }