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.GroovyRuntimeException; 022import groovy.lang.MissingMethodException; 023import groovy.lang.MissingPropertyException; 024import groovy.lang.Script; 025import org.codehaus.groovy.runtime.InvokerInvocationException; 026import org.crsh.shell.impl.command.spi.CommandCreationException; 027import org.crsh.shell.impl.command.spi.CommandInvoker; 028import org.crsh.command.InvocationContext; 029import org.crsh.command.ScriptException; 030import org.crsh.shell.impl.command.spi.ShellCommand; 031import org.crsh.lang.groovy.closure.PipeLineClosure; 032import org.crsh.lang.groovy.closure.PipeLineInvoker; 033import org.crsh.shell.impl.command.CRaSH; 034import org.crsh.text.RenderPrintWriter; 035 036import java.io.IOException; 037import java.lang.reflect.UndeclaredThrowableException; 038import java.util.LinkedList; 039 040public abstract class GroovyScriptCommand extends Script { 041 042 /** . */ 043 private LinkedList<InvocationContext<?>> stack; 044 045 /** The current context. */ 046 protected InvocationContext context; 047 048 /** The current output. */ 049 protected RenderPrintWriter out; 050 051 protected GroovyScriptCommand() { 052 this.stack = null; 053 } 054 055 public final void pushContext(InvocationContext<?> context) throws NullPointerException { 056 if (context == null) { 057 throw new NullPointerException(); 058 } 059 060 // 061 if (stack == null) { 062 stack = new LinkedList<InvocationContext<?>>(); 063 } 064 065 // Save current context (is null the first time) 066 stack.addLast((InvocationContext)this.context); 067 068 // Set new context 069 this.context = context; 070 this.out = context.getWriter(); 071 } 072 073 public final InvocationContext<?> popContext() { 074 if (stack == null || stack.isEmpty()) { 075 throw new IllegalStateException("Cannot pop a context anymore from the stack"); 076 } 077 InvocationContext context = this.context; 078 this.context = stack.removeLast(); 079 this.out = this.context != null ? this.context.getWriter() : null; 080 return context; 081 } 082 083 public final void execute(String s) throws ScriptException, IOException { 084 InvocationContext<?> context = peekContext(); 085 CommandInvoker invoker = context.resolve(s); 086 invoker.invoke(context); 087 } 088 089 public final InvocationContext<?> peekContext() { 090 return (InvocationContext<?>)context; 091 } 092 093 @Override 094 public final Object invokeMethod(String name, Object args) { 095 096 // 097 try { 098 return super.invokeMethod(name, args); 099 } 100 catch (MissingMethodException missing) { 101 if (context instanceof InvocationContext) { 102 CRaSH crash = (CRaSH)context.getSession().get("crash"); 103 if (crash != null) { 104 ShellCommand<?> cmd; 105 try { 106 cmd = crash.getCommand(name); 107 } 108 catch (CommandCreationException ce) { 109 throw new InvokerInvocationException(ce); 110 } 111 if (cmd != null) { 112 InvocationContext<Object> ic = (InvocationContext<Object>)peekContext(); 113 PipeLineClosure closure = new PipeLineClosure(ic, name, cmd); 114 PipeLineInvoker evaluation = closure.bind(args); 115 try { 116 evaluation.invoke(ic); 117 return null; 118 } 119 catch (IOException e) { 120 throw new GroovyRuntimeException(e); 121 } 122 catch (UndeclaredThrowableException e) { 123 throw new GroovyRuntimeException(e.getCause()); 124 } 125 } 126 } 127 } 128 129 // 130 throw missing; 131 } 132 } 133 134 @Override 135 public final Object getProperty(String property) { 136 if ("out".equals(property)) { 137 if (context instanceof InvocationContext<?>) { 138 return ((InvocationContext<?>)context).getWriter(); 139 } else { 140 return null; 141 } 142 } else if ("context".equals(property)) { 143 return context; 144 } else { 145 if (context instanceof InvocationContext<?>) { 146 CRaSH crash = (CRaSH)context.getSession().get("crash"); 147 if (crash != null) { 148 try { 149 ShellCommand<?> cmd = crash.getCommand(property); 150 if (cmd != null) { 151 InvocationContext<Object> ic = (InvocationContext<Object>)peekContext(); 152 return new PipeLineClosure(ic, property, cmd); 153 } 154 } catch (CommandCreationException e) { 155 throw new InvokerInvocationException(e); 156 } 157 } 158 } 159 160 // 161 try { 162 return super.getProperty(property); 163 } 164 catch (MissingPropertyException e) { 165 return null; 166 } 167 } 168 } 169}