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 020package org.crsh.telnet.term.processor; 021 022import org.crsh.shell.ShellProcess; 023import org.crsh.shell.ShellProcessContext; 024import org.crsh.shell.ShellResponse; 025import org.crsh.telnet.term.TermEvent; 026import org.crsh.text.Chunk; 027import org.crsh.text.Text; 028import org.crsh.util.Utils; 029 030import java.io.IOException; 031import java.util.logging.Level; 032 033class 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.write(Text.create(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.write(Text.create("\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 public Class<Chunk> getConsumedType() { 119 return Chunk.class; 120 } 121 122 public void write(Chunk chunk) throws IOException { 123 provide(chunk); 124 } 125 126 public void provide(Chunk element) throws IOException { 127 processor.term.write(element); 128 } 129 130 public void flush() throws IOException { 131 processor.term.flush(); 132 } 133 134 public void end(ShellResponse response) { 135 Runnable runnable; 136 ProcessContext context; 137 Status status; 138 synchronized (processor.lock) { 139 140 // 141 processor.current = null; 142 switch (processor.status) { 143 case PROCESSING: 144 if (response instanceof ShellResponse.Close) { 145 runnable = processor.CLOSE_TASK; 146 processor.status = Status.CLOSED; 147 } else if (response instanceof ShellResponse.Cancelled) { 148 runnable = Processor.NOOP; 149 processor.status = Status.AVAILABLE; 150 } else { 151 final String message = response.getMessage(); 152 runnable = new Runnable() { 153 public void run() { 154 try { 155 processor.provide(Text.create(message)); 156 } 157 catch (IOException e) { 158 // todo ??? 159 e.printStackTrace(); 160 } 161 finally { 162 // Be sure to flush 163 Utils.flush(processor.term); 164 } 165 } 166 }; 167 processor.status = Status.AVAILABLE; 168 } 169 break; 170 case CANCELLING: 171 runnable = Processor.NOOP; 172 processor.status = Status.AVAILABLE; 173 break; 174 default: 175 throw new AssertionError("Does not make sense " + processor.status); 176 } 177 178 // Do we have a next process to execute ? 179 context = processor.peekProcess(); 180 status = processor.status; 181 } 182 183 // 184 runnable.run(); 185 186 // 187 if (context != null) { 188 context.run(); 189 } else if (status == Status.AVAILABLE) { 190 processor.writePromptFlush(); 191 } 192 } 193}