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.groovy.shell;
020    
021    import groovy.lang.Binding;
022    import groovy.lang.Closure;
023    import groovy.lang.GroovyShell;
024    import org.codehaus.groovy.control.CompilerConfiguration;
025    import org.codehaus.groovy.runtime.InvokerHelper;
026    import org.crsh.command.NoSuchCommandException;
027    import org.crsh.command.ShellCommand;
028    import org.crsh.lang.CommandManager;
029    import org.crsh.lang.groovy.command.GroovyScript;
030    import org.crsh.lang.groovy.command.GroovyScriptCommand;
031    import org.crsh.plugin.PluginContext;
032    import org.crsh.plugin.ResourceKind;
033    
034    import java.util.HashMap;
035    import java.util.Map;
036    import java.util.logging.Level;
037    import java.util.logging.Logger;
038    
039    /** @author Julien Viet */
040    public class GroovyCommandManager extends CommandManager {
041    
042      /** . */
043      static final Logger log = Logger.getLogger(GroovyCommandManager.class.getName());
044    
045      /** . */
046      final PluginContext context;
047    
048      /** . */
049      final AbstractClassManager<? extends ShellCommand> commandManager;
050    
051      /** . */
052      final AbstractClassManager<? extends GroovyScript> scriptManager;
053    
054      public GroovyCommandManager(PluginContext context) {
055        this.context = context;
056        this.commandManager = new ClassManager<ShellCommand>(context, ResourceKind.COMMAND, ShellCommand.class, GroovyScriptCommand.class);
057        this.scriptManager = new ClassManager<GroovyScript>(context, ResourceKind.LIFECYCLE, GroovyScript.class, GroovyScript.class);
058      }
059    
060      public String doCallBack(HashMap<String, Object> session, String name, String defaultValue) {
061        return eval(session, name, defaultValue);
062      }
063    
064      public void init(HashMap<String, Object> session) {
065        try {
066          GroovyScript login = getLifeCycle(session, "login");
067          if (login != null) {
068            login.setBinding(new Binding(session));
069            login.run();
070          }
071        }
072        catch (NoSuchCommandException e) {
073          e.printStackTrace();
074        }
075      }
076    
077      public void destroy(HashMap<String, Object> session) {
078        try {
079          GroovyScript logout = getLifeCycle(session, "logout");
080          if (logout != null) {
081            logout.setBinding(new Binding(session));
082            logout.run();
083          }
084        }
085        catch (NoSuchCommandException e) {
086          e.printStackTrace();
087        }
088      }
089    
090      public GroovyShell getGroovyShell(Map<String, Object> session) {
091        return getGroovyShell(context, session);
092      }
093    
094      /**
095       * The underlying groovu shell used for the REPL.
096       *
097       * @return a groovy shell operating on the session attributes
098       */
099      public static GroovyShell getGroovyShell(PluginContext context, Map<String, Object> session) {
100        GroovyShell shell = (GroovyShell)session.get("shell");
101        if (shell == null) {
102          CompilerConfiguration config = new CompilerConfiguration();
103          config.setRecompileGroovySource(true);
104          ShellBinding binding = new ShellBinding(session);
105          shell = new GroovyShell(context.getLoader(), binding, config);
106          session.put("shell", shell);
107        }
108        return shell;
109      }
110    
111      private String eval(HashMap<String, Object> session, String name, String def) {
112        try {
113          GroovyShell shell = getGroovyShell(session);
114          Object ret = shell.evaluate("return " + name + ";");
115          if (ret instanceof Closure) {
116            log.log(Level.FINEST, "Invoking " + name + " closure");
117            Closure c = (Closure)ret;
118            ret = c.call();
119          } else if (ret == null) {
120            log.log(Level.FINEST, "No " + name + " will use empty");
121            return def;
122          }
123          return String.valueOf(ret);
124        }
125        catch (Exception e) {
126          log.log(Level.SEVERE, "Could not get a " + name + " message, will use empty", e);
127          return def;
128        }
129      }
130    
131      public GroovyScript getLifeCycle(HashMap<String, Object> session, String name) throws NoSuchCommandException, NullPointerException {
132        Class<? extends GroovyScript> scriptClass = scriptManager.getClass(name);
133        if (scriptClass != null) {
134          GroovyScript script = (GroovyScript)InvokerHelper.createScript(scriptClass, new Binding(session));
135          script.setBinding(new Binding(session));
136          return script;
137        } else {
138          return null;
139        }
140      }
141    
142      public ShellCommand getCommand(String name) throws NoSuchCommandException, NullPointerException {
143        return commandManager.getInstance(name);
144      }
145    }