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.processor.term; 021 022 import org.crsh.shell.ShellProcess; 023 import org.crsh.shell.ShellProcessContext; 024 import org.crsh.shell.ShellResponse; 025 import org.crsh.text.Chunk; 026 import org.crsh.term.TermEvent; 027 import org.crsh.text.Text; 028 import org.crsh.util.Safe; 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.provide(Text.create(msg)); 073 } 074 catch (IOException e) { 075 return null; 076 } 077 boolean done = false; 078 while (true) { 079 synchronized (processor.lock) { 080 switch (processor.status) { 081 case CLOSED: 082 case CANCELLING: 083 return null; 084 case PROCESSING: 085 if (processor.queue.size() > 0) { 086 TermEvent event = processor.queue.removeFirst(); 087 if (event instanceof TermEvent.ReadLine) { 088 return ((TermEvent.ReadLine)event).getLine().toString(); 089 } 090 } 091 break; 092 default: 093 throw new AssertionError("Does not make sense " + processor.status); 094 } 095 } 096 if (done) { 097 return null; 098 } else { 099 done = true; 100 processor.waitingEvent = true; 101 try { 102 processor.term.setEcho(echo); 103 processor.readTerm(); 104 processor.term.provide(Text.create("\r\n")); 105 } 106 catch (IOException e) { 107 processor.log.log(Level.SEVERE, "Error when readline line"); 108 } 109 finally { 110 processor.waitingEvent = false; 111 processor.term.setEcho(true); 112 } 113 } 114 } 115 } 116 117 public Class<Chunk> getConsumedType() { 118 return Chunk.class; 119 } 120 121 public void provide(Chunk element) throws IOException { 122 processor.term.provide(element); 123 } 124 125 public void flush() throws IOException { 126 processor.term.flush(); 127 } 128 129 public void end(ShellResponse response) { 130 Runnable runnable; 131 ProcessContext context; 132 Status status; 133 synchronized (processor.lock) { 134 135 // 136 processor.current = null; 137 switch (processor.status) { 138 case PROCESSING: 139 if (response instanceof ShellResponse.Close) { 140 runnable = processor.CLOSE; 141 processor.status = Status.CLOSED; 142 } else if (response instanceof ShellResponse.Cancelled) { 143 runnable = Processor.NOOP; 144 processor.status = Status.AVAILABLE; 145 } else { 146 final String message = response.getMessage(); 147 runnable = new Runnable() { 148 public void run() { 149 try { 150 processor.provide(Text.create(message)); 151 } 152 catch (IOException e) { 153 // todo ??? 154 e.printStackTrace(); 155 } 156 finally { 157 // Be sure to flush 158 Safe.flush(processor.term); 159 } 160 } 161 }; 162 processor.status = Status.AVAILABLE; 163 } 164 break; 165 case CANCELLING: 166 runnable = Processor.NOOP; 167 processor.status = Status.AVAILABLE; 168 break; 169 default: 170 throw new AssertionError("Does not make sense " + processor.status); 171 } 172 173 // Do we have a next process to execute ? 174 context = processor.peekProcess(); 175 status = processor.status; 176 } 177 178 // 179 runnable.run(); 180 181 // 182 if (context != null) { 183 context.run(); 184 } else if (status == Status.AVAILABLE) { 185 processor.writePromptFlush(); 186 } 187 } 188 }