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