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 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.provide(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 provide(Chunk element) throws IOException { 123 processor.term.provide(element); 124 } 125 126 public void flush() throws IOException { 127 processor.term.flush(); 128 } 129 130 public void end(ShellResponse response) { 131 Runnable runnable; 132 ProcessContext context; 133 Status status; 134 synchronized (processor.lock) { 135 136 // 137 processor.current = null; 138 switch (processor.status) { 139 case PROCESSING: 140 if (response instanceof ShellResponse.Close) { 141 runnable = processor.CLOSE_TASK; 142 processor.status = Status.CLOSED; 143 } else if (response instanceof ShellResponse.Cancelled) { 144 runnable = Processor.NOOP; 145 processor.status = Status.AVAILABLE; 146 } else { 147 final String message = response.getMessage(); 148 runnable = new Runnable() { 149 public void run() { 150 try { 151 processor.provide(Text.create(message)); 152 } 153 catch (IOException e) { 154 // todo ??? 155 e.printStackTrace(); 156 } 157 finally { 158 // Be sure to flush 159 Safe.flush(processor.term); 160 } 161 } 162 }; 163 processor.status = Status.AVAILABLE; 164 } 165 break; 166 case CANCELLING: 167 runnable = Processor.NOOP; 168 processor.status = Status.AVAILABLE; 169 break; 170 default: 171 throw new AssertionError("Does not make sense " + processor.status); 172 } 173 174 // Do we have a next process to execute ? 175 context = processor.peekProcess(); 176 status = processor.status; 177 } 178 179 // 180 runnable.run(); 181 182 // 183 if (context != null) { 184 context.run(); 185 } else if (status == Status.AVAILABLE) { 186 processor.writePromptFlush(); 187 } 188 } 189 }