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 020 package org.crsh.text.ui; 021 022 import groovy.lang.Closure; 023 import org.crsh.command.CRaSHCommand; 024 import org.crsh.command.CommandInvoker; 025 import org.crsh.command.GroovyScriptCommand; 026 import org.crsh.command.InvocationContext; 027 import org.crsh.command.ScriptException; 028 import org.crsh.text.RenderPrintWriter; 029 import org.crsh.text.Renderable; 030 import org.crsh.text.Renderer; 031 032 import java.io.IOException; 033 import java.util.LinkedList; 034 import java.util.Map; 035 036 public class EvalElement extends Element { 037 038 /** The closure to evaluate. */ 039 Closure closure; 040 041 public Renderer renderer() { 042 043 Object owner = closure.getOwner(); 044 045 // 046 final InvocationContext ctx; 047 Object cmd; 048 while (true) { 049 if (owner instanceof CRaSHCommand) { 050 cmd = owner; 051 ctx = ((CRaSHCommand)cmd).peekContext(); 052 break; 053 } else if (owner instanceof GroovyScriptCommand) { 054 cmd = owner; 055 ctx = ((GroovyScriptCommand)cmd).peekContext(); 056 break; 057 } else if (owner instanceof Closure) { 058 owner = ((Closure)owner).getOwner(); 059 } else { 060 throw new UnsupportedOperationException("Cannot resolver owner " + owner + " to command"); 061 } 062 } 063 064 // 065 final LinkedList<Renderer> renderers = new LinkedList<Renderer>(); 066 067 // 068 final InvocationContext nested = new InvocationContext() { 069 070 /** . */ 071 private LinkedList<Object> buffer = new LinkedList<Object>(); 072 073 /** . */ 074 private Renderable renderable; 075 076 public CommandInvoker<?, ?> resolve(String s) throws ScriptException, IOException { 077 return ctx.resolve(s); 078 } 079 080 public boolean isPiped() { 081 throw new UnsupportedOperationException(); 082 } 083 084 public boolean takeAlternateBuffer() { 085 return false; 086 } 087 088 public boolean releaseAlternateBuffer() { 089 return false; 090 } 091 092 public RenderPrintWriter getWriter() { 093 return ctx.getWriter(); 094 } 095 096 public Map<String, Object> getSession() { 097 return ctx.getSession(); 098 } 099 100 public Map<String, Object> getAttributes() { 101 return ctx.getAttributes(); 102 } 103 104 public int getWidth() { 105 return ctx.getWidth(); 106 } 107 108 public int getHeight() { 109 return ctx.getHeight(); 110 } 111 112 public String getProperty(String propertyName) { 113 return ctx.getProperty(propertyName); 114 } 115 116 public String readLine(String msg, boolean echo) { 117 return null; 118 } 119 120 public Class getConsumedType() { 121 return Object.class; 122 } 123 124 public void provide(Object element) throws IOException { 125 Renderable current = Renderable.getRenderable(element.getClass()); 126 if (current == null) { 127 current = Renderable.ANY; 128 } 129 if (current != null) { 130 if (renderable != null && !current.equals(renderable)) { 131 flush(); 132 } 133 buffer.addLast(element); 134 renderable = current; 135 } 136 } 137 138 public void flush() throws IOException { 139 // We don't really flush, we just compute renderables from the buffer 140 if (buffer.size() > 0) { 141 Renderer i = renderable.renderer(buffer.iterator()); 142 buffer.clear(); 143 renderers.add(i); 144 } 145 } 146 147 public void close() throws IOException { 148 // Nothing to do, except maybe release resources (and also prevent to do any other operation) 149 } 150 }; 151 152 if (cmd instanceof CRaSHCommand) { 153 ((CRaSHCommand)cmd).pushContext(nested); 154 } else { 155 ((GroovyScriptCommand)cmd).pushContext(nested); 156 } 157 try { 158 closure.call(); 159 } 160 finally { 161 if (cmd instanceof CRaSHCommand) { 162 ((CRaSHCommand)cmd).popContext(); 163 } else { 164 ((GroovyScriptCommand)cmd).popContext(); 165 } 166 } 167 168 // Be sure to flush 169 try { 170 nested.flush(); 171 } 172 catch (IOException e) { 173 e.printStackTrace(); 174 } 175 176 // 177 return Renderer.vertical(renderers); 178 } 179 }