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 takeAlternateBuffer() { 081 return false; 082 } 083 084 public boolean releaseAlternateBuffer() { 085 return false; 086 } 087 088 public RenderPrintWriter getWriter() { 089 return ctx.getWriter(); 090 } 091 092 public Map<String, Object> getSession() { 093 return ctx.getSession(); 094 } 095 096 public Map<String, Object> getAttributes() { 097 return ctx.getAttributes(); 098 } 099 100 public int getWidth() { 101 return ctx.getWidth(); 102 } 103 104 public int getHeight() { 105 return ctx.getHeight(); 106 } 107 108 public String getProperty(String propertyName) { 109 return ctx.getProperty(propertyName); 110 } 111 112 public String readLine(String msg, boolean echo) { 113 return null; 114 } 115 116 public Class getConsumedType() { 117 return Object.class; 118 } 119 120 public void provide(Object element) throws IOException { 121 Renderable current = Renderable.getRenderable(element.getClass()); 122 if (current == null) { 123 current = Renderable.ANY; 124 } 125 if (current != null) { 126 if (renderable != null && !current.equals(renderable)) { 127 flush(); 128 } 129 buffer.addLast(element); 130 renderable = current; 131 } 132 } 133 134 public void flush() throws IOException { 135 // We don't really flush, we just compute renderables from the buffer 136 if (buffer.size() > 0) { 137 Renderer i = renderable.renderer(buffer.iterator()); 138 buffer.clear(); 139 renderers.add(i); 140 } 141 } 142 }; 143 144 if (cmd instanceof CRaSHCommand) { 145 ((CRaSHCommand)cmd).pushContext(nested); 146 } else { 147 ((GroovyScriptCommand)cmd).pushContext(nested); 148 } 149 try { 150 closure.call(); 151 } 152 finally { 153 if (cmd instanceof CRaSHCommand) { 154 ((CRaSHCommand)cmd).popContext(); 155 } else { 156 ((GroovyScriptCommand)cmd).popContext(); 157 } 158 } 159 160 // Be sure to flush 161 try { 162 nested.flush(); 163 } 164 catch (IOException e) { 165 e.printStackTrace(); 166 } 167 168 // 169 return Renderer.vertical(renderers); 170 } 171 }