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<CommandResolution>> commandCache = new ConcurrentHashMap<String, TimestampedObject<CommandResolution>>(); 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 description. Null is returned when such command does not exist. 082 * 083 * @param name the command name 084 * @return a command description 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 String getCommandDescription(String name) throws CommandCreationException, NullPointerException { 089 CommandResolution resolution = resolveCommand(name); 090 return resolution != null ? resolution.getDescription() : null; 091 } 092 093 /** 094 * Attempt to obtain a command instance. Null is returned when such command does not exist. 095 * 096 * @param name the command name 097 * @return a command instance 098 * @throws org.crsh.command.CommandCreationException if an error occured preventing the command creation 099 * @throws NullPointerException if the name argument is null 100 */ 101 public ShellCommand getCommand(String name) throws CommandCreationException, NullPointerException { 102 CommandResolution resolution = resolveCommand(name); 103 return resolution != null ? resolution.getCommand() : null; 104 } 105 106 /** 107 * Attempt to obtain a command instance. Null is returned when such command does not exist. 108 * 109 * @param name the command name 110 * @return a command instance 111 * @throws org.crsh.command.CommandCreationException if an error occured preventing the command creation 112 * @throws NullPointerException if the name argument is null 113 */ 114 public CommandResolution resolveCommand(String name) throws CommandCreationException, NullPointerException { 115 if (name == null) { 116 throw new NullPointerException("No null name accepted"); 117 } 118 for (CommandManager manager : managers.values()) { 119 for (String ext : manager.getExtensions()) { 120 Iterable<Resource> resources = context.loadResources(name + "." + ext, ResourceKind.COMMAND); 121 for (Resource resource : resources) { 122 CommandResolution resolution = resolveCommand(manager, name, resource); 123 if (resolution != null) { 124 return resolution; 125 } 126 } 127 } 128 } 129 return null; 130 } 131 132 public Iterable<String> getCommandNames() { 133 ArrayList<String> names = new ArrayList<String>(); 134 for (String resourceName : context.listResources(ResourceKind.COMMAND)) { 135 int index = resourceName.indexOf('.'); 136 String name = resourceName.substring(0, index); 137 String ext = resourceName.substring(index + 1); 138 if (managers.containsKey(ext)) { 139 names.add(name); 140 } 141 } 142 return names; 143 } 144 145 private CommandResolution resolveCommand(CommandManager manager, String name, Resource script) throws CommandCreationException { 146 TimestampedObject<CommandResolution> ref = commandCache.get(name); 147 if (ref != null) { 148 if (script.getTimestamp() != ref.getTimestamp()) { 149 ref = null; 150 } 151 } 152 CommandResolution command; 153 if (ref == null) { 154 command = manager.resolveCommand(name, script.getContent()); 155 if (command != null) { 156 commandCache.put(name, new TimestampedObject<CommandResolution>(script.getTimestamp(), command)); 157 } 158 } else { 159 command = ref.getObject(); 160 } 161 return command; 162 } 163}