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 */
019package org.crsh.lang.impl.groovy;
020
021import groovy.lang.Binding;
022import org.crsh.command.CommandContext;
023import org.crsh.command.InvocationContext;
024import org.crsh.shell.impl.command.AbstractInvocationContext;
025import org.crsh.shell.impl.command.spi.CommandInvoker;
026import org.crsh.text.RenderPrintWriter;
027import org.crsh.text.Screenable;
028import org.crsh.shell.impl.command.ShellSession;
029import org.crsh.shell.impl.command.spi.CommandException;
030import org.crsh.shell.impl.command.InvocationContextImpl;
031import org.crsh.shell.impl.command.spi.Command;
032import org.crsh.lang.impl.groovy.closure.PipeLineClosure;
033import org.crsh.text.Style;
034
035import java.io.IOException;
036import java.util.Map;
037
038/** @author Julien Viet */
039class 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}