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.GroovyShell;
022import org.crsh.cli.impl.Delimiter;
023import org.crsh.cli.impl.completion.CompletionMatch;
024import org.crsh.cli.spi.Completion;
025import org.crsh.command.CommandContext;
026import org.crsh.lang.spi.Language;
027import org.crsh.lang.spi.ReplResponse;
028import org.crsh.shell.ErrorKind;
029import org.crsh.shell.impl.command.InvocationContextImpl;
030import org.crsh.shell.impl.command.ShellSession;
031import org.crsh.shell.impl.command.spi.CommandException;
032import org.crsh.shell.impl.command.spi.CommandInvoker;
033import org.crsh.lang.spi.Repl;
034import org.crsh.cli.impl.line.LineParser;
035
036import java.io.IOException;
037
038/**
039 * Groovy REPL implementation.
040 *
041 * @author Julien Viet
042 */
043public class GroovyRepl implements Repl {
044
045  /** . */
046  final GroovyLanguage lang;
047
048  public GroovyRepl(GroovyLanguage lang) {
049    // Force to load Groovy here or fail
050    Object o = GroovyShell.class;
051    this.lang = lang;
052  }
053
054  @Override
055  public Language getLanguage() {
056    return lang;
057  }
058
059  @Override
060  public String getDescription() {
061    return "The Groovy repl provides a Groovy interpreter able to interact with shell commands";
062  }
063
064  public ReplResponse eval(final ShellSession session, final String r2) {
065
066
067    GroovyLineEscaper foo = new GroovyLineEscaper();
068    LineParser parser = new LineParser(foo);
069    parser.append(r2);
070    final String request = foo.buffer.toString();
071
072
073    //
074    CommandInvoker<Void, Object> invoker = new CommandInvoker<Void, Object>() {
075      public void provide(Void element) throws IOException {
076        throw new UnsupportedOperationException("Should not be invoked");
077      }
078      public Class<Void> getConsumedType() {
079        return Void.class;
080      }
081      public void flush() throws IOException {
082      }
083      public Class<Object> getProducedType() {
084        return Object.class;
085      }
086      CommandContext<Object> consumer;
087      public void open(CommandContext<? super Object> consumer) throws IOException, CommandException {
088        this.consumer = (CommandContext<Object>)consumer;
089        GroovyShell shell = GroovyCompiler.getGroovyShell(session);
090        ShellBinding binding = (ShellBinding)shell.getContext();
091        binding.setCurrent(new InvocationContextImpl<Object>(this.consumer));
092        Object o;
093        try {
094          o = shell.evaluate(request);
095        }
096        finally {
097          binding.setCurrent(null);
098        }
099        if (o != null) {
100          try {
101            consumer.provide(o);
102          }
103          catch (IOException e) {
104            throw e;
105          }
106          catch (CommandException e) {
107            throw e;
108          }
109          catch (Exception e) {
110            throw new CommandException(ErrorKind.EVALUATION, "An error occured during the evalution of '" + request + "'", e);
111          }
112        }
113      }
114      public void close() throws IOException, CommandException {
115        try {
116          consumer.flush();
117          consumer.close();
118        }
119        catch (Exception e) {
120          throw new CommandException(ErrorKind.EVALUATION, "An error occured during the evalution of '" + request + "'", e);
121        }
122      }
123    };
124    return new ReplResponse.Invoke(invoker);
125  }
126
127  public CompletionMatch complete(ShellSession session, String prefix) {
128    return new CompletionMatch(Delimiter.EMPTY, Completion.create());
129  }
130}