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.shell.impl.remoting;
021
022 import org.crsh.shell.ErrorType;
023 import org.crsh.shell.ShellProcess;
024 import org.crsh.shell.ShellProcessContext;
025 import org.crsh.shell.ShellResponse;
026 import org.crsh.text.Chunk;
027 import org.crsh.util.Statement;
028
029 import java.io.IOException;
030 import java.util.ArrayList;
031
032 class ClientProcessContext implements ShellProcessContext {
033
034 /** . */
035 final ClientAutomaton client;
036
037 /** . */
038 final ShellProcess process;
039
040 /** . */
041 final ArrayList<Chunk> buffer;
042
043 ClientProcessContext(ClientAutomaton client, ShellProcess process) {
044 this.client = client;
045 this.process = process;
046 this.buffer = new ArrayList<Chunk>(1000);
047 }
048
049 /**
050 * Ensure we have a recent size, the size is considered as recent if it's younger than 2 second, otherwise
051 * send a get size message.
052 */
053 private void ensureSize() {
054 if (System.currentTimeMillis() - client.last > 2000) {
055 synchronized (this) {
056 try {
057 client.out.writeObject(new ServerMessage.GetSize());
058 client.out.flush();
059 }
060 catch (Exception e) {
061 //
062 }
063 }
064 }
065 }
066
067 void execute() {
068 try {
069 process.execute(this);
070 }
071 catch(final Throwable t) {
072 new Statement() {
073 @Override
074 protected void run() throws Throwable {
075 // If it's not executing then we attempt to end it
076 end(ShellResponse.error(ErrorType.INTERNAL, "Unexpected process execution error", t));
077 }
078 }.all();
079 }
080 }
081
082 public int getWidth() {
083 ensureSize();
084 return client.getWidth();
085 }
086
087 public int getHeight() {
088 ensureSize();
089 return client.getHeight();
090 }
091
092 public boolean takeAlternateBuffer() {
093 try {
094 client.out.writeObject(new ServerMessage.UseAlternateBuffer());
095 client.out.flush();
096 }
097 catch (Exception e) {
098 //
099 }
100
101 // For now we suppose any impl return true;
102 return true;
103 }
104
105 public boolean releaseAlternateBuffer() {
106 try {
107 client.out.writeObject(new ServerMessage.UseMainBuffer());
108 client.out.flush();
109 }
110 catch (Exception e) {
111 //
112 }
113
114 // For now we suppose any impl return true;
115 return true;
116 }
117
118 public String getProperty(String name) {
119 return null;
120 }
121
122 public String readLine(String msg, boolean echo) {
123 // try {
124 // client.out.writeObject(ServerMessage.READLINE);
125 // client.out.writeObject(msg);
126 // client.out.writeObject(echo);
127 // client.out.flush();
128 // return (String)client.in.readObject();
129 // }
130 // catch (Exception e) {
131 // return null;
132 // }
133 return null;
134 }
135
136 public void provide(Chunk element) throws IOException {
137 buffer.add(element);
138 }
139
140 public synchronized void flush() {
141 if (buffer.size() > 0) {
142 try {
143 for (Chunk chunk : buffer) {
144 client.out.writeObject(new ServerMessage.Chunk(chunk));
145 }
146 client.out.writeObject(new ServerMessage.Flush());
147 client.out.flush();
148 }
149 catch (IOException ignore) {
150 //
151 }
152 finally {
153 buffer.clear();
154 }
155 }
156 }
157
158 public synchronized void end(ShellResponse response) {
159
160 // It may have been cancelled concurrently
161 if (client.current == this) {
162
163 // Flush what we have in buffer first
164 flush();
165
166 // Send end message
167 try {
168 client.current = null;
169 client.out.writeObject(new ServerMessage.End(response));
170 client.out.flush();
171 }
172 catch (IOException ignore) {
173 //
174 }
175 finally {
176 if (response instanceof ShellResponse.Close) {
177 client.close();
178 }
179 }
180 }
181 }
182 }