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.impl.groovy.command; 020 021 import groovy.lang.MissingMethodException; 022 import groovy.lang.MissingPropertyException; 023 import groovy.lang.Script; 024 import org.crsh.lang.impl.groovy.Helper; 025 import org.crsh.shell.impl.command.spi.CommandException; 026 import org.crsh.shell.impl.command.spi.CommandInvoker; 027 import org.crsh.command.InvocationContext; 028 import org.crsh.lang.impl.groovy.closure.PipeLineClosure; 029 import org.crsh.text.RenderPrintWriter; 030 031 import java.lang.reflect.UndeclaredThrowableException; 032 import java.util.LinkedList; 033 034 public abstract class GroovyScriptCommand extends Script { 035 036 /** . */ 037 private LinkedList<InvocationContext<?>> stack; 038 039 /** The current context. */ 040 protected InvocationContext context; 041 042 /** The current output. */ 043 protected RenderPrintWriter out; 044 045 protected GroovyScriptCommand() { 046 this.stack = null; 047 } 048 049 public final void pushContext(InvocationContext<?> context) throws NullPointerException { 050 if (context == null) { 051 throw new NullPointerException(); 052 } 053 054 // 055 if (stack == null) { 056 stack = new LinkedList<InvocationContext<?>>(); 057 } 058 059 // Save current context (is null the first time) 060 stack.addLast(this.context); 061 062 // Set new context 063 this.context = context; 064 this.out = context.getWriter(); 065 } 066 067 public final InvocationContext<?> popContext() { 068 if (stack == null || stack.isEmpty()) { 069 throw new IllegalStateException("Cannot pop a context anymore from the stack"); 070 } 071 InvocationContext context = this.context; 072 this.context = stack.removeLast(); 073 this.out = this.context != null ? this.context.getWriter() : null; 074 return context; 075 } 076 077 public final void execute(String s) throws Exception { 078 InvocationContext<?> context = peekContext(); 079 try { 080 CommandInvoker invoker = context.resolve(s); 081 invoker.invoke(context); 082 } 083 catch (CommandException e) { 084 Throwable cause = e.getCause(); 085 if (cause instanceof Exception) { 086 throw (Exception)cause; 087 } else if (cause instanceof Error) { 088 throw (Error)cause; 089 } else { 090 throw new UndeclaredThrowableException(cause); 091 } 092 } 093 } 094 095 public final InvocationContext<?> peekContext() { 096 return (InvocationContext<?>)context; 097 } 098 099 @Override 100 public final Object invokeMethod(String name, Object args) { 101 102 // 103 try { 104 return super.invokeMethod(name, args); 105 } 106 catch (MissingMethodException missing) { 107 return Helper.invokeMethod(context, name, args, missing); 108 } 109 } 110 111 @Override 112 public final Object getProperty(String property) { 113 if ("out".equals(property)) { 114 return ((InvocationContext<?>)context).getWriter(); 115 } else if ("context".equals(property)) { 116 return context; 117 } else { 118 PipeLineClosure ret = Helper.resolveProperty(context, property); 119 if (ret != null) { 120 return ret; 121 } 122 try { 123 return super.getProperty(property); 124 } 125 catch (MissingPropertyException e) { 126 return null; 127 } 128 } 129 } 130 }