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