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 020package org.crsh.shell.impl.command; 021 022import org.crsh.command.CommandCreationException; 023import org.crsh.command.ShellCommand; 024import org.crsh.plugin.PluginContext; 025import org.crsh.plugin.ResourceKind; 026import org.crsh.util.TimestampedObject; 027import org.crsh.vfs.Resource; 028 029import java.security.Principal; 030import java.util.ArrayList; 031import java.util.HashMap; 032import java.util.Map; 033import java.util.concurrent.ConcurrentHashMap; 034 035public class CRaSH { 036 037 /** . */ 038 final PluginContext context; 039 040 /** . */ 041 final HashMap<String, CommandManager> managers; 042 043 /** . */ 044 private final Map<String, TimestampedObject<? extends ShellCommand>> commandCache = new ConcurrentHashMap<String, TimestampedObject<? extends ShellCommand>>(); 045 046 /** 047 * Create a new CRaSH. 048 * 049 * @param context the plugin context 050 * @throws NullPointerException if the context argument is null 051 */ 052 public CRaSH(PluginContext context) throws NullPointerException { 053 054 // 055 HashMap<String, CommandManager> managers = new HashMap<String, CommandManager>(); 056 for (CommandManager manager : context.getPlugins(CommandManager.class)) { 057 for (String ext : manager.getExtensions()) { 058 managers.put(ext, manager); 059 } 060 } 061 062 063 this.context = context; 064 this.managers = managers; 065 } 066 067 public CRaSHSession createSession(Principal user) { 068 return new CRaSHSession(this, user); 069 } 070 071 /** 072 * Returns the plugin context. 073 * 074 * @return the plugin context 075 */ 076 public PluginContext getContext() { 077 return context; 078 } 079 080 /** 081 * Attempt to obtain a command instance. Null is returned when such command does not exist. 082 * 083 * @param name the command name 084 * @return a command instance 085 * @throws org.crsh.command.CommandCreationException if an error occured preventing the command creation 086 * @throws NullPointerException if the name argument is null 087 */ 088 public ShellCommand getCommand(String name) throws CommandCreationException, NullPointerException { 089 for (CommandManager manager : managers.values()) { 090 for (String ext : manager.getExtensions()) { 091 Iterable<Resource> resources = context.loadResources(name + "." + ext, ResourceKind.COMMAND); 092 for (Resource resource : resources) { 093 return getShellCommand(manager, name, resource); 094 } 095 } 096 } 097 return null; 098 } 099 100 public Iterable<String> getCommandNames() { 101 ArrayList<String> names = new ArrayList<String>(); 102 for (String resourceName : context.listResources(ResourceKind.COMMAND)) { 103 int index = resourceName.indexOf('.'); 104 String name = resourceName.substring(0, index); 105 String ext = resourceName.substring(index + 1); 106 if (managers.containsKey(ext)) { 107 names.add(name); 108 } 109 } 110 return names; 111 } 112 113 private ShellCommand getShellCommand(CommandManager manager, String name, Resource script) throws CommandCreationException { 114 TimestampedObject<? extends ShellCommand> ref = commandCache.get(name); 115 if (ref != null) { 116 if (script.getTimestamp() != ref.getTimestamp()) { 117 ref = null; 118 } 119 } 120 ShellCommand command; 121 if (ref == null) { 122 command = manager.resolveCommand(name, script.getContent()); 123 if (command != null) { 124 commandCache.put(name, new TimestampedObject<ShellCommand>(script.getTimestamp(), command)); 125 } 126 } else { 127 command = ref.getObject(); 128 } 129 return command; 130 } 131}