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 020 package org.crsh.telnet.term.processor; 021 022 import org.crsh.shell.ShellProcess; 023 import org.crsh.shell.ShellProcessContext; 024 import org.crsh.shell.ShellResponse; 025 import org.crsh.telnet.term.TermEvent; 026 import org.crsh.text.Screenable; 027 import org.crsh.text.Style; 028 import org.crsh.util.Utils; 029 030 import java.io.IOException; 031 import java.util.logging.Level; 032 033 class ProcessContext implements ShellProcessContext, Runnable { 034 035 /** . */ 036 final Processor processor; 037 038 /** . */ 039 final ShellProcess process; 040 041 ProcessContext(Processor processor, ShellProcess process) { 042 this.process = process; 043 this.processor = processor; 044 } 045 046 public boolean takeAlternateBuffer() throws IOException { 047 return processor.term.takeAlternateBuffer(); 048 } 049 050 public boolean releaseAlternateBuffer() throws IOException { 051 return processor.term.releaseAlternateBuffer(); 052 } 053 054 public void run() { 055 process.execute(this); 056 } 057 058 public int getWidth() { 059 return processor.term.getWidth(); 060 } 061 062 public int getHeight() { 063 return processor.term.getHeight(); 064 } 065 066 public String getProperty(String name) { 067 return processor.term.getProperty(name); 068 } 069 070 public String readLine(String msg, boolean echo) { 071 try { 072 processor.term.append(msg); 073 processor.term.flush(); 074 } 075 catch (IOException e) { 076 return null; 077 } 078 boolean done = false; 079 while (true) { 080 synchronized (processor.lock) { 081 switch (processor.status) { 082 case CLOSED: 083 case CANCELLING: 084 return null; 085 case PROCESSING: 086 if (processor.queue.size() > 0) { 087 TermEvent event = processor.queue.removeFirst(); 088 if (event instanceof TermEvent.ReadLine) { 089 return ((TermEvent.ReadLine)event).getLine().toString(); 090 } 091 } 092 break; 093 default: 094 throw new AssertionError("Does not make sense " + processor.status); 095 } 096 } 097 if (done) { 098 return null; 099 } else { 100 done = true; 101 processor.waitingEvent = true; 102 try { 103 processor.term.setEcho(echo); 104 processor.readTerm(); 105 processor.term.append("\r\n"); 106 } 107 catch (IOException e) { 108 processor.log.log(Level.SEVERE, "Error when readline line"); 109 } 110 finally { 111 processor.waitingEvent = false; 112 processor.term.setEcho(true); 113 } 114 } 115 } 116 } 117 118 @Override 119 public Appendable append(char c) throws IOException { 120 processor.append(c); 121 return this; 122 } 123 124 @Override 125 public Appendable append(CharSequence s) throws IOException { 126 processor.append(s); 127 return this; 128 } 129 130 @Override 131 public Appendable append(CharSequence csq, int start, int end) throws IOException { 132 processor.append(csq, start, end); 133 return this; 134 } 135 136 @Override 137 public Screenable append(Style style) throws IOException { 138 processor.append(style); 139 return this; 140 } 141 142 @Override 143 public Screenable cls() throws IOException { 144 processor.cls(); 145 return this; 146 } 147 148 public void flush() throws IOException { 149 processor.term.flush(); 150 } 151 152 public void end(ShellResponse response) { 153 Runnable runnable; 154 ProcessContext context; 155 Status status; 156 synchronized (processor.lock) { 157 158 // 159 processor.current = null; 160 switch (processor.status) { 161 case PROCESSING: 162 if (response instanceof ShellResponse.Close) { 163 runnable = processor.CLOSE_TASK; 164 processor.status = Status.CLOSED; 165 } else if (response instanceof ShellResponse.Cancelled) { 166 runnable = Processor.NOOP; 167 processor.status = Status.AVAILABLE; 168 } else { 169 final String message = response.getMessage(); 170 runnable = new Runnable() { 171 public void run() { 172 try { 173 processor.append(message); 174 } 175 catch (IOException e) { 176 // todo ??? 177 e.printStackTrace(); 178 } 179 finally { 180 // Be sure to flush 181 try { 182 processor.term.flush(); 183 } 184 catch (IOException e) { 185 } 186 } 187 } 188 }; 189 processor.status = Status.AVAILABLE; 190 } 191 break; 192 case CANCELLING: 193 runnable = Processor.NOOP; 194 processor.status = Status.AVAILABLE; 195 break; 196 default: 197 throw new AssertionError("Does not make sense " + processor.status); 198 } 199 200 // Do we have a next process to execute ? 201 context = processor.peekProcess(); 202 status = processor.status; 203 } 204 205 // 206 runnable.run(); 207 208 // 209 if (context != null) { 210 context.run(); 211 } else if (status == Status.AVAILABLE) { 212 processor.writePromptFlush(); 213 } 214 } 215 }