/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.command.internal; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.commons.logging.LogFactory; import de.rcenvironment.core.command.common.CommandException; import de.rcenvironment.core.command.spi.CommandContext; import de.rcenvironment.core.command.spi.CommandDescription; import de.rcenvironment.core.command.spi.CommandPlugin; import de.rcenvironment.core.command.spi.SingleCommandHandler; /** * Dispatches a single command to the appropriate {@link CommandPlugin}, or generates an error message if no matching {@link CommandPlugin} * is registered. * * @author Robert Mischke */ public class CommandPluginDispatcher implements SingleCommandHandler { private Map<String, CommandPlugin> pluginsByTopLevelCommand = new HashMap<String, CommandPlugin>(); @Override public void execute(CommandContext context) throws CommandException { if (context.consumeNextTokenIfEquals("explain")) { context.println("Parsed command tokens: " + context.consumeRemainingTokens()); return; } CommandPlugin plugin = null; String topLevelCommand = context.peekNextToken(); synchronized (pluginsByTopLevelCommand) { if (topLevelCommand == null) { throw new IllegalArgumentException("Empty command"); } plugin = pluginsByTopLevelCommand.get(topLevelCommand); } if (plugin != null) { try { plugin.execute(context); } catch (RuntimeException e) { LogFactory.getLog(getClass()).error("Uncaught exception in command handler", e); throw CommandException.executionError("Uncaught exception in command handler: " + e.toString(), context); } } else { // no command recognized throw CommandException.unknownCommand(context); } } /** * Registers a new {@link CommandPlugin}, which is then used for handling commands matching the descriptions provided by * {@link CommandPlugin#getCommandDescriptions()}. * * @param plugin the new plugin */ public void registerPlugin(CommandPlugin plugin) { Set<String> topLevelCommands = determineTopLevelCommands(plugin); synchronized (pluginsByTopLevelCommand) { for (String command : topLevelCommands) { if (pluginsByTopLevelCommand.get(command) != null) { LogFactory.getLog(getClass()).warn( "Ignoring new command plugin registration as another plugin already handles the command " + command); continue; } pluginsByTopLevelCommand.put(command, plugin); } } } /** * Unregisters a new {@link CommandPlugin}. * * @param plugin the plugin to remove */ public void unregisterPlugin(CommandPlugin plugin) { Set<String> topLevelCommands = determineTopLevelCommands(plugin); synchronized (pluginsByTopLevelCommand) { for (String command : topLevelCommands) { if (pluginsByTopLevelCommand.get(command) != plugin) { LogFactory.getLog(getClass()).warn( "Another plugin is handling the command " + command); continue; } pluginsByTopLevelCommand.remove(command); } } } private Set<String> determineTopLevelCommands(CommandPlugin plugin) { Set<String> topLevelCommands = new HashSet<>(); for (CommandDescription cd : plugin.getCommandDescriptions()) { String[] staticPartSegments = cd.getStaticPart().split(" "); // handle "a/b ..." command aliases String[] tlcs = staticPartSegments[0].split("/"); for (String tlc : tlcs) { topLevelCommands.add(tlc); } } return topLevelCommands; } }