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    package org.crsh.lang.impl.groovy;
020    
021    import groovy.lang.Binding;
022    import org.crsh.command.CommandContext;
023    import org.crsh.command.InvocationContext;
024    import org.crsh.shell.impl.command.AbstractInvocationContext;
025    import org.crsh.shell.impl.command.spi.CommandInvoker;
026    import org.crsh.text.RenderPrintWriter;
027    import org.crsh.text.Screenable;
028    import org.crsh.shell.impl.command.ShellSession;
029    import org.crsh.shell.impl.command.spi.CommandException;
030    import org.crsh.shell.impl.command.InvocationContextImpl;
031    import org.crsh.shell.impl.command.spi.Command;
032    import org.crsh.lang.impl.groovy.closure.PipeLineClosure;
033    import org.crsh.text.Style;
034    
035    import java.io.IOException;
036    import java.util.Map;
037    
038    /** @author Julien Viet */
039    class ShellBinding extends Binding {
040    
041      /** . */
042      private final ShellSession session;
043    
044      /** . */
045      private InvocationContext<Object> current;
046    
047      public ShellBinding(Map variables, ShellSession session) {
048        super(variables);
049    
050        //
051        this.session = session;
052      }
053    
054      private InvocationContext<Object> proxy = new AbstractInvocationContext<Object>() {
055        public RenderPrintWriter getWriter() {
056          if (current == null) {
057            throw new IllegalStateException("Not under context");
058          } else {
059            // Warning we don't proxy the writer, should we ?
060            return current.getWriter();
061          }
062        }
063        public CommandInvoker<?, ?> resolve(String s) throws CommandException {
064          if (current == null) {
065            throw new IllegalStateException("Not under context");
066          } else {
067            return current.resolve(s);
068          }
069        }
070        public void close() throws Exception {
071          if (current == null) {
072            throw new IllegalStateException("Not under context");
073          } else {
074            current.close();
075          }
076        }
077        public boolean takeAlternateBuffer() throws IOException {
078          if (current == null) {
079            throw new IllegalStateException("Not under context");
080          } else {
081            return current.takeAlternateBuffer();
082          }
083        }
084        public boolean releaseAlternateBuffer() throws IOException {
085          if (current == null) {
086            throw new IllegalStateException("Not under context");
087          } else {
088            return current.releaseAlternateBuffer();
089          }
090        }
091        public String readLine(String msg, boolean echo) throws IOException, InterruptedException {
092          if (current == null) {
093            throw new IllegalStateException("Not under context");
094          } else {
095            return current.readLine(msg, echo);
096          }
097        }
098        public int getWidth() {
099          if (current == null) {
100            throw new IllegalStateException("Not under context");
101          } else {
102            return current.getWidth();
103          }
104        }
105        public int getHeight() {
106          if (current == null) {
107            throw new IllegalStateException("Not under context");
108          } else {
109            return current.getWidth();
110          }
111        }
112        public void provide(Object element) throws Exception {
113          if (current == null) {
114            throw new IllegalStateException("Not under context");
115          } else {
116            current.provide(element);
117          }
118        }
119        public Class<Object> getConsumedType() {
120          if (current == null) {
121            throw new IllegalStateException("Not under context");
122          } else {
123            return current.getConsumedType();
124          }
125        }
126        public void flush() throws IOException {
127          if (current == null) {
128            throw new IllegalStateException("Not under context");
129          } else {
130            current.flush();
131          }
132        }
133        public String getProperty(String propertyName) {
134          if (current == null) {
135            throw new IllegalStateException("Not under context");
136          } else {
137            return current.getProperty(propertyName);
138          }
139        }
140        public Map<String, Object> getSession() {
141          if (current == null) {
142            throw new IllegalStateException("Not under context");
143          } else {
144            return current.getSession();
145          }
146        }
147        public Map<String, Object> getAttributes() {
148          if (current == null) {
149            throw new IllegalStateException("Not under context");
150          } else {
151            return current.getAttributes();
152          }
153        }
154        public Screenable append(CharSequence s) throws IOException {
155          if (current == null) {
156            throw new IllegalStateException("Not under context");
157          } else {
158            current.append(s);
159          }
160          return this;
161        }
162        public Appendable append(char c) throws IOException {
163          if (current == null) {
164            throw new IllegalStateException("Not under context");
165          } else {
166            current.append(c);
167          }
168          return this;
169        }
170        public Appendable append(CharSequence csq, int start, int end) throws IOException {
171          if (current == null) {
172            throw new IllegalStateException("Not under context");
173          } else {
174            current.append(csq, start, end);
175          }
176          return this;
177        }
178        public Screenable append(Style style) throws IOException {
179          if (current == null) {
180            throw new IllegalStateException("Not under context");
181          } else {
182            current.append(style);
183          }
184          return this;
185        }
186        public Screenable cls() throws IOException {
187          if (current == null) {
188            throw new IllegalStateException("Not under context");
189          } else {
190            current.cls();
191          }
192          return this;
193        }
194      };
195    
196      public InvocationContext<Object> getCurrent() {
197        return current;
198      }
199    
200      public void setCurrent(InvocationContext<Object> current) {
201        this.current = current;
202      }
203    
204      @Override
205      public Object getVariable(String name) {
206        if (name.equals("context")) {
207          return proxy;
208        } else {
209          if (session != null) {
210            try {
211              Command<?> cmd = session.getCommand(name);
212              if (cmd != null) {
213                return new PipeLineClosure(new InvocationContextImpl<Object>(proxy), name, cmd);
214              }
215            } catch (CommandException ignore) {
216              // Really ?
217            }
218            return super.getVariable(name);
219          } else {
220            return super.getVariable(name);
221          }
222        }
223      }
224    }