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.command;
021    
022    import org.crsh.command.CommandContext;
023    import org.crsh.shell.impl.command.spi.CommandException;
024    import org.crsh.text.Screenable;
025    import org.crsh.text.ScreenContext;
026    import org.crsh.shell.ShellProcessContext;
027    import org.crsh.text.ScreenBuffer;
028    import org.crsh.text.ScreenContextConsumer;
029    import org.crsh.text.Style;
030    
031    import java.io.Closeable;
032    import java.io.IOException;
033    import java.util.Map;
034    
035    class 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    }