001 /* 002 * Copyright (C) 2003-2009 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.command; 020 021 import groovy.lang.Binding; 022 import groovy.lang.Closure; 023 import groovy.lang.MissingMethodException; 024 import groovy.lang.MissingPropertyException; 025 import groovy.lang.Script; 026 import org.codehaus.groovy.runtime.InvokerInvocationException; 027 import org.crsh.cmdline.CommandCompletion; 028 import org.crsh.cmdline.Delimiter; 029 import org.crsh.cmdline.spi.ValueCompletion; 030 import org.crsh.shell.impl.command.CRaSH; 031 import org.crsh.text.ShellPrintWriter; 032 import org.crsh.util.Strings; 033 034 import java.util.List; 035 036 /** 037 * This class provides the base class for Groovy scripts. It should not be used directly as it is rather used 038 * for configuring a Groovy {@link org.codehaus.groovy.control.CompilerConfiguration#setScriptBaseClass(String)} class. 039 * 040 * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> 041 * @version $Revision$ 042 */ 043 public abstract class GroovyScriptCommand extends Script implements ShellCommand, CommandInvoker<Void, Void> { 044 045 /** . */ 046 private CommandContext context; 047 048 /** . */ 049 private String[] args; 050 051 public final Class<Void> getProducedType() { 052 return Void.class; 053 } 054 055 public final Class<Void> getConsumedType() { 056 return Void.class; 057 } 058 059 @Override 060 public Object invokeMethod(String name, Object args) { 061 062 // 063 try { 064 return super.invokeMethod(name, args); 065 } 066 catch (MissingMethodException e) { 067 if (context instanceof InvocationContext) { 068 InvocationContext ic = (InvocationContext)context; 069 CRaSH crash = (CRaSH)context.getSession().get("crash"); 070 if (crash != null) { 071 ShellCommand cmd; 072 try { 073 cmd = crash.getCommand(name); 074 } 075 catch (NoSuchCommandException ce) { 076 throw new InvokerInvocationException(ce); 077 } 078 if (cmd != null) { 079 CommandDispatcher dispatcher = new CommandDispatcher(cmd, ic); 080 return dispatcher.dispatch("", args); 081 } 082 } 083 } 084 085 // 086 throw e; 087 } 088 } 089 090 @Override 091 public final Object getProperty(String property) { 092 if ("out".equals(property)) { 093 if (context instanceof InvocationContext<?, ?>) { 094 return ((InvocationContext<?, ?>)context).getWriter(); 095 } else { 096 return null; 097 } 098 } else if ("context".equals(property)) { 099 return context; 100 } else { 101 if (context instanceof InvocationContext<?, ?>) { 102 CRaSH crash = (CRaSH)context.getSession().get("crash"); 103 if (crash != null) { 104 try { 105 ShellCommand cmd = crash.getCommand(property); 106 if (cmd != null) { 107 return new CommandDispatcher(cmd, (InvocationContext<?, ?>)context); 108 } 109 } catch (NoSuchCommandException e) { 110 throw new InvokerInvocationException(e); 111 } 112 } 113 } 114 115 // 116 try { 117 return super.getProperty(property); 118 } 119 catch (MissingPropertyException e) { 120 return null; 121 } 122 } 123 } 124 125 public final CommandCompletion complete(CommandContext context, String line) { 126 return new CommandCompletion(Delimiter.EMPTY, ValueCompletion.create()); 127 } 128 129 public String describe(String line, DescriptionFormat mode) { 130 return null; 131 } 132 133 public final void invoke(InvocationContext<Void, Void> context) throws ScriptException { 134 135 // Set up current binding 136 Binding binding = new Binding(context.getSession()); 137 138 // Set the args on the script 139 binding.setProperty("args", args); 140 141 // 142 setBinding(binding); 143 144 // 145 this.context = context; 146 try { 147 // 148 Object res = run(); 149 150 // Evaluate the closure 151 if (res instanceof Closure) { 152 Closure closure = (Closure)res; 153 res = closure.call(args); 154 } 155 156 // 157 if (res != null) { 158 ShellPrintWriter writer = context.getWriter(); 159 if (writer.isEmpty()) { 160 writer.print(res); 161 } 162 } 163 } 164 catch (Exception t) { 165 throw CRaSHCommand.toScript(t); 166 } 167 finally { 168 this.context = null; 169 } 170 } 171 172 public final CommandInvoker<?, ?> createInvoker(String line) { 173 List<String> chunks = Strings.chunks(line); 174 this.args = chunks.toArray(new String[chunks.size()]); 175 return this; 176 } 177 }