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.groovy.repl;
020    
021    import groovy.lang.GroovyShell;
022    import org.crsh.cli.impl.Delimiter;
023    import org.crsh.cli.impl.completion.CompletionMatch;
024    import org.crsh.cli.spi.Completion;
025    import org.crsh.command.CommandContext;
026    import org.crsh.command.CommandInvoker;
027    import org.crsh.command.InvocationContextImpl;
028    import org.crsh.lang.groovy.closure.PipeLineInvoker;
029    import org.crsh.lang.groovy.shell.ShellBinding;
030    import org.crsh.lang.groovy.shell.GroovyCommandManager;
031    import org.crsh.repl.EvalResponse;
032    import org.crsh.repl.REPL;
033    import org.crsh.repl.REPLSession;
034    
035    import java.io.IOException;
036    
037    /**
038     * Groovy REPL implementation.
039     *
040     * @author Julien Viet
041     */
042    public class GroovyREPL implements REPL {
043    
044      public String getName() {
045        return "groovy";
046      }
047    
048      public EvalResponse eval(final REPLSession session, final String request) {
049        CommandInvoker<Void, Object> invoker = new CommandInvoker<Void, Object>() {
050          public void provide(Void element) throws IOException {
051            throw new UnsupportedOperationException("Should not be invoked");
052          }
053          public Class<Void> getConsumedType() {
054            return Void.class;
055          }
056          public void flush() throws IOException {
057          }
058          public Class<Object> getProducedType() {
059            return Object.class;
060          }
061          CommandContext<Object> foo;
062          public void open(CommandContext<? super Object> consumer) {
063            this.foo = (CommandContext<Object>)consumer;
064            GroovyShell shell = GroovyCommandManager.getGroovyShell(session.getContext(), session);
065            ShellBinding binding = (ShellBinding)shell.getContext();
066            binding.setCurrent(foo);
067            Object o;
068            try {
069              o = shell.evaluate(request);
070            }
071            finally {
072              binding.setCurrent(null);
073            }
074            if (o instanceof PipeLineInvoker) {
075              PipeLineInvoker eval = (PipeLineInvoker)o;
076              try {
077                eval.invoke(new InvocationContextImpl<Object>(foo));
078              }
079              catch (Exception e) {
080                throw new UnsupportedOperationException("handle me gracefully", e);
081              }
082            } else {
083              try {
084                if (o != null) {
085                  consumer.provide(o);
086                }
087              }
088              catch (IOException e) {
089                throw new UnsupportedOperationException("handle me gracefully", e);
090              }
091            }
092          }
093          public void close() throws IOException {
094            foo.flush();
095            foo.close();
096          }
097        };
098        return new EvalResponse.Invoke(invoker);
099      }
100    
101      public CompletionMatch complete(REPLSession session, String prefix) {
102        return new CompletionMatch(Delimiter.EMPTY, Completion.create());
103      }
104    }