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.command; 020 021import groovy.lang.Binding; 022import groovy.lang.Closure; 023import org.crsh.cli.impl.Delimiter; 024import org.crsh.cli.impl.completion.CompletionMatch; 025import org.crsh.cli.spi.Completion; 026import org.crsh.command.CommandContext; 027import org.crsh.command.CommandCreationException; 028import org.crsh.command.CommandInvoker; 029import org.crsh.command.DescriptionFormat; 030import org.crsh.command.InvocationContextImpl; 031import org.crsh.command.RuntimeContext; 032import org.crsh.command.ShellCommand; 033import org.crsh.shell.ErrorType; 034import org.crsh.text.RenderPrintWriter; 035import org.crsh.util.Strings; 036 037import java.io.IOException; 038import java.lang.reflect.UndeclaredThrowableException; 039import java.util.List; 040import java.util.Map; 041 042/** @author Julien Viet */ 043public class GroovyScriptShellCommand<C extends GroovyScriptCommand> implements ShellCommand { 044 045 /** . */ 046 private final Class<C> clazz; 047 048 public GroovyScriptShellCommand(Class<C> clazz) { 049 this.clazz = clazz; 050 } 051 052 private C createCommand() throws CommandCreationException { 053 C command; 054 try { 055 command = clazz.newInstance(); 056 } 057 catch (Exception e) { 058 String name = clazz.getSimpleName(); 059 throw new CommandCreationException(name, ErrorType.INTERNAL, "Could not create command " + name + " instance", e); 060 } 061 return command; 062 } 063 064 public final CompletionMatch complete(RuntimeContext context, String line) { 065 return new CompletionMatch(Delimiter.EMPTY, Completion.create()); 066 } 067 068 public final String describe(String line, DescriptionFormat mode) { 069 return null; 070 } 071 072 public final CommandInvoker<?, ?> resolveInvoker(String line) throws CommandCreationException { 073 List<String> chunks = Strings.chunks(line); 074 String[] args = chunks.toArray(new String[chunks.size()]); 075 return getInvoker(args); 076 } 077 078 public final CommandInvoker<?, ?> resolveInvoker(String name, Map<String, ?> options, List<?> args) throws CommandCreationException { 079 String[] tmp = new String[args.size()]; 080 for (int i = 0;i < tmp.length;i++) { 081 tmp[i] = args.get(i).toString(); 082 } 083 return getInvoker(tmp); 084 } 085 086 private CommandInvoker<Object, Object> getInvoker(final String[] args) throws CommandCreationException { 087 final C command = createCommand(); 088 return new CommandInvoker<Object, Object>() { 089 090 public final Class<Object> getProducedType() { 091 return Object.class; 092 } 093 094 public final Class<Object> getConsumedType() { 095 return Object.class; 096 } 097 098 public void open(CommandContext<? super Object> consumer) { 099 // Set up current binding 100 Binding binding = new Binding(consumer.getSession()); 101 102 // Set the args on the script 103 binding.setProperty("args", args); 104 105 // 106 command.setBinding(binding); 107 108 // 109 command.pushContext(new InvocationContextImpl<Object>((CommandContext<Object>)consumer)); 110 111 // 112 try { 113 // 114 Object res = command.run(); 115 116 // Evaluate the closure 117 if (res instanceof Closure) { 118 Closure closure = (Closure)res; 119 res = closure.call(args); 120 } 121 122 // 123 if (res != null) { 124 RenderPrintWriter writer = command.peekContext().getWriter(); 125 if (writer.isEmpty()) { 126 writer.print(res); 127 } 128 } 129 } 130 catch (Exception t) { 131 throw GroovyCommand.unwrap(t); 132 } 133 } 134 135 public void provide(Object element) throws IOException { 136 // Should never be called 137 } 138 139 public void flush() throws IOException { 140 command.peekContext().flush(); 141 } 142 143 public void close() throws IOException, UndeclaredThrowableException { 144 command.popContext(); 145 } 146 }; 147 } 148 149 150}