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.shell.impl.command;
021
022import org.crsh.command.CommandContext;
023import org.crsh.shell.impl.command.spi.CommandException;
024import org.crsh.text.Screenable;
025import org.crsh.text.ScreenContext;
026import org.crsh.shell.ShellProcessContext;
027import org.crsh.text.ScreenBuffer;
028import org.crsh.text.ScreenContextConsumer;
029import org.crsh.text.Style;
030
031import java.io.Closeable;
032import java.io.IOException;
033import java.util.Map;
034
035class CRaSHProcessContext implements CommandContext<Object>, Closeable {
036
037  /** . */
038  private final CRaSHSession session;
039
040  /** . */
041  private final ShellProcessContext processContext;
042
043  /** . */
044  private final ScreenContextConsumer adapter;
045
046  /** . */
047  private final ScreenBuffer buffer;
048
049  /** . */
050  private boolean useAlternateBuffer;
051
052  CRaSHProcessContext(CRaSHSession session, final ShellProcessContext processContext) {
053
054    // We use this chunk buffer to buffer stuff
055    // but also because it optimises the chunks
056    // which provides better perormances on the client
057    final ScreenBuffer buffer = new ScreenBuffer(processContext);
058
059    //
060    final ScreenContextConsumer adapter = new ScreenContextConsumer(new ScreenContext() {
061      public int getWidth() {
062        return processContext.getWidth();
063      }
064
065      public int getHeight() {
066        return processContext.getHeight();
067      }
068
069      @Override
070      public Screenable append(CharSequence s) throws IOException {
071        buffer.append(s);
072        return this;
073      }
074
075      @Override
076      public Appendable append(char c) throws IOException {
077        buffer.append(c);
078        return this;
079      }
080
081      @Override
082      public Screenable append(CharSequence csq, int start, int end) throws IOException {
083        buffer.append(csq, start, end);
084        return this;
085      }
086
087      @Override
088      public Screenable append(Style style) throws IOException {
089        buffer.append(style);
090        return this;
091      }
092
093      @Override
094      public Screenable cls() throws IOException {
095        buffer.cls();
096        return this;
097      }
098
099      public void flush() throws IOException {
100        buffer.flush();
101      }
102    });
103
104    //
105    this.session = session;
106    this.processContext = processContext;
107    this.adapter = adapter;
108    this.useAlternateBuffer = false;
109    this.buffer = buffer;
110  }
111
112  public boolean takeAlternateBuffer() throws IOException {
113    return useAlternateBuffer = processContext.takeAlternateBuffer();
114  }
115
116  public boolean releaseAlternateBuffer() throws IOException {
117    return useAlternateBuffer = processContext.releaseAlternateBuffer();
118  }
119
120  public String getProperty(String propertyName) {
121    return processContext.getProperty(propertyName);
122  }
123
124  public String readLine(String msg, boolean echo) throws IOException, InterruptedException {
125    return processContext.readLine(msg, echo);
126  }
127
128  public int getWidth() {
129    return processContext.getWidth();
130  }
131
132  public int getHeight() {
133    return processContext.getHeight();
134  }
135
136  public Class<Object> getConsumedType() {
137    return Object.class;
138  }
139
140  @Override
141  public Screenable append(CharSequence s) throws IOException {
142    return append(s, 0, s.length());
143  }
144
145  @Override
146  public Screenable append(char c) throws IOException {
147    adapter.send();
148    buffer.append(c);
149    return this;
150  }
151
152  @Override
153  public Screenable append(CharSequence csq, int start, int end) throws IOException {
154    if (start < end) {
155      adapter.send();
156      buffer.append(csq, start, end);
157    }
158    return this;
159  }
160
161  @Override
162  public Screenable append(Style style) throws IOException {
163    adapter.provide(style);
164    return this;
165  }
166
167  @Override
168  public Screenable cls() throws IOException {
169    buffer.cls();
170    return this;
171  }
172
173  public void provide(Object element) throws IOException {
174    adapter.provide(element);
175  }
176
177  public void flush() throws IOException {
178    adapter.flush();
179  }
180
181  public Map<String, Object> getSession() {
182    return session;
183  }
184
185  public Map<String, Object> getAttributes() {
186    return session.crash.getContext().getAttributes();
187  }
188
189  public void close() throws IOException {
190    if (useAlternateBuffer) {
191      releaseAlternateBuffer();
192    }
193  }
194}