Package org.jboss.forge.aesh

Source Code of org.jboss.forge.aesh.ForgeShellImpl$ForgeConsoleCallback

/*
* Copyright 2012 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.jboss.forge.aesh;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.enterprise.event.Observes;
import javax.inject.Inject;
import javax.inject.Singleton;

import org.jboss.aesh.cl.CommandLine;
import org.jboss.aesh.cl.exception.ArgumentParserException;
import org.jboss.aesh.cl.exception.CommandLineParserException;
import org.jboss.aesh.cl.exception.OptionParserException;
import org.jboss.aesh.cl.exception.RequiredOptionException;
import org.jboss.aesh.console.Config;
import org.jboss.aesh.console.Console;
import org.jboss.aesh.console.ConsoleCallback;
import org.jboss.aesh.console.ConsoleOutput;
import org.jboss.aesh.console.Prompt;
import org.jboss.aesh.console.settings.Settings;
import org.jboss.aesh.terminal.CharacterType;
import org.jboss.aesh.terminal.Color;
import org.jboss.aesh.terminal.TerminalCharacter;
import org.jboss.forge.aesh.spi.ShellConfiguration;
import org.jboss.forge.aesh.util.CommandLineUtil;
import org.jboss.forge.aesh.util.UICommandDelegate;
import org.jboss.forge.container.Forge;
import org.jboss.forge.container.addons.Addon;
import org.jboss.forge.container.addons.AddonRegistry;
import org.jboss.forge.container.event.PostStartup;
import org.jboss.forge.container.event.PreShutdown;
import org.jboss.forge.container.services.Exported;
import org.jboss.forge.container.services.ExportedInstance;
import org.jboss.forge.ui.UICommand;
import org.jboss.forge.ui.result.NavigationResult;
import org.jboss.forge.ui.result.Result;
import org.jboss.forge.ui.wizard.UIWizard;

/**
* @author <a href="mailto:stale.pedersen@jboss.org">Ståle W. Pedersen</a>
*/
@Singleton
@Exported
public class ForgeShellImpl implements ForgeShell
{
   private static final Logger logger = Logger.getLogger(ForgeShellImpl.class.getName());

   private Console console;
   private Prompt prompt;
   private List<ShellCommand> wizardSteps = new ArrayList<ShellCommand>();

   private List<ShellCommand> commands;

   @Inject
   private Forge forge;

   @Inject
   private Addon self;

   @Inject
   private AddonRegistry registry;

   void observe(@Observes PostStartup startup) throws Exception
   {
      startShell();
   }

   void stop(@Observes PreShutdown shutdown) throws Exception
   {
      if (console != null && console.isRunning())
         console.stop();
   }

   public void addCommand(ShellCommand command)
   {
      commands.add(command);
      console.addCompletion(command);
   }

   private void initShell() throws Exception
   {
      prompt = createPrompt();

      Settings.getInstance().setReadInputrc(false);
      Settings.getInstance().setLogging(true);

      for (ExportedInstance<ShellConfiguration> instance : registry.getExportedInstances(ShellConfiguration.class))
      {
         ShellConfiguration provider = instance.get();
         provider.configure();
      }

      commands = new ArrayList<ShellCommand>();
      console = Console.getInstance();
      console.setPrompt(prompt);
      console.setConsoleCallback(new ForgeConsoleCallback());

      refreshAvailableCommands();
   }

   private void refreshAvailableCommands()
   {
      Set<ExportedInstance<UICommand>> instances = registry.getExportedInstances(UICommand.class);

      Set<UICommand> loaded = new HashSet<UICommand>();
      for (ExportedInstance<UICommand> instance : instances)
      {
         UICommand command = instance.get();
         loaded.add(command);
         if (!isCommandLoaded(command))
         {
            try
            {
               addCommand(new ShellCommand(registry, this, command));
            }
            catch (Exception e)
            {
               logger.log(Level.SEVERE, "Failed to load command [" + instance + "]");
            }
         }
      }

      Iterator<ShellCommand> iterable = commands.iterator();
      Set<ShellCommand> toRemove = new HashSet<ShellCommand>();
      while (iterable.hasNext())
      {
         ShellCommand next = iterable.next();
         if (!isCommandAvailable(loaded, next.getCommand().getMetadata().getName()))
         {
            toRemove.add(next);
         }
      }
      commands.removeAll(toRemove);
   }

   private boolean isCommandLoaded(UICommand uiCommand)
   {
      for (ShellCommand command : commands)
      {
         if (command.getCommand().getMetadata().getName()
                  .equals(new UICommandDelegate(uiCommand).getMetadata().getName()))
            return true;
      }
      return false;
   }

   private boolean isCommandAvailable(Set<UICommand> availableCommands, String name)
   {
      for (UICommand command : availableCommands)
      {
         if (new UICommandDelegate(command).getMetadata().getName().equals(name))
            return true;
      }
      return false;
   }

   public void startShell() throws Exception
   {
      initShell();
      console.start();
   }

   public AddonRegistry getRegistry()
   {
      return registry;
   }

   public String getPrompt()
   {
      return prompt.getPromptAsString();
   }

   public Console getConsole()
   {
      return console;
   }

   public void stopShell() throws IOException
   {
      if (console != null && console.isRunning())
      {
         console.stop();
         console.reset();
      }
   }

   private Prompt createPrompt()
   {

      List<TerminalCharacter> chars = new ArrayList<TerminalCharacter>();
      chars.add(new TerminalCharacter('[', Color.DEFAULT_BG, Color.BLUE_TEXT));
      chars.add(new TerminalCharacter('f', Color.DEFAULT_BG, Color.RED_TEXT,
               CharacterType.BOLD));
      chars.add(new TerminalCharacter('o', Color.DEFAULT_BG, Color.RED_TEXT,
               CharacterType.BOLD));
      chars.add(new TerminalCharacter('r', Color.DEFAULT_BG, Color.RED_TEXT,
               CharacterType.BOLD));
      chars.add(new TerminalCharacter('g', Color.DEFAULT_BG, Color.RED_TEXT,
               CharacterType.BOLD));
      chars.add(new TerminalCharacter('e', Color.DEFAULT_BG, Color.RED_TEXT,
               CharacterType.BOLD));
      chars.add(new TerminalCharacter(']', Color.DEFAULT_BG, Color.BLUE_TEXT,
               CharacterType.PLAIN));
      chars.add(new TerminalCharacter('$', Color.DEFAULT_BG, Color.DEFAULT_TEXT));
      chars.add(new TerminalCharacter(' ', Color.DEFAULT_BG, Color.DEFAULT_TEXT));

      return new Prompt(chars);
   }

   private ForgeShell getForgeShell()
   {
      return this;
   }

   class ForgeConsoleCallback implements ConsoleCallback
   {
      @Override
      public int readConsoleOutput(ConsoleOutput output) throws IOException
      {
         refreshAvailableCommands();
         if (output.getBuffer() != null && !output.getBuffer().trim().isEmpty())
         {
            // we're currently not in a wizard context
            if (wizardSteps.size() == 0)
               return parseUICommand(output);
            else
               return parseWizardStep(output);
         }
         return -1;
      }

      /**
       * We're in a wizard and we need to add the steps in a list so they can be executed when we've come to the end of
       * the wizard.
       *
       * @throws IOException
       */
      private int parseWizardStep(ConsoleOutput output) throws IOException
      {
         // get latest command added
         ShellCommand currentCommand = wizardSteps.get(wizardSteps.size() - 1);
         try
         {
            CommandLine cl = currentCommand.parse(output.getBuffer());
            if (cl != null)
            {
               // populate the inputs to the context
               CommandLineUtil.populateUIInputs(cl, currentCommand.getContext(), registry);
               currentCommand.getContext().setConsoleOutput(output);

               // so now the options are parsed and added to the uicontext of that command
               // try to get next command in the wizard
               UIWizard wizard = (UIWizard) wizardSteps.get(0).getCommand();
               NavigationResult navResult = wizard.next(wizardSteps.get(0).getContext());
               // we have another step, lets add it to the list
               // this will be processed next
               if (navResult != null)
               {
                  Object cmd = navResult.getNext();
                  wizardSteps.add(new ShellCommand(registry, getForgeShell(), (UICommand) cmd));
               }
               // we have come to the final step, execute the wizard
               else
                  return executeWizardSteps();
            }

         }
         catch (CommandLineParserException e)
         {
            // parser exception (we must add some logic here to give the user more info on
            // what input was wrong to prevent loosing all the steps in the wizard.
         }
         catch (Exception e)
         {
            // wizard.next(..) exception
         }

         return 0;
      }

      /**
       * When the wizard is at its final step, go through all the commands and execute them
       *
       * @throws IOException
       */
      private int executeWizardSteps() throws IOException
      {
         for (ShellCommand command : wizardSteps)
         {
            try
            {
               Result result = command.getCommand().execute(command.getContext());
               if (result != null &&
                        result.getMessage() != null && result.getMessage().length() > 0)
                  getConsole().pushToStdOut(result.getMessage() + Config.getLineSeparator());
            }
            catch (Exception e)
            {
               // not sure what we do here, need to think about it
            }
         }
         // empty the list
         wizardSteps.clear();
         return 1;
      }

      private int parseUICommand(ConsoleOutput output) throws IOException
      {
         int result = 1;
         CommandLine cl = null;
         for (ShellCommand command : commands)
         {
            try
            {
               cl = command.parse(output.getBuffer());
               logger.info("Parsing: " + output.getBuffer() + ", CommandLine is:" + cl);
               if (cl != null)
               {
                  if (command.getCommand() instanceof UIWizard)
                  {
                     wizardSteps.add(command);
                     return parseWizardStep(output);
                  }
                  try
                  {
                     command.run(output, cl);
                     result = 0;
                     break;
                  }
                  catch (Exception e)
                  {
                     logger.log(Level.SEVERE, "Command " + command + " failed to run with: " + output, e);
                     result = 1;
                  }
               }
            }
            catch (CommandLineParserException iae)
            {
               if (iae instanceof OptionParserException ||
                        iae instanceof ArgumentParserException ||
                        iae instanceof RequiredOptionException)
               {
                  console.pushToStdOut(iae.getMessage() + Config.getLineSeparator());
                  logger.info("GOT: " + iae.getMessage() + "\n Parser: " + command.getContext().getParser());
                  result = 1;
                  break;
               }
               else
               {
                  logger.log(Level.INFO, "Command: " + command + ", did not match: " + output.getBuffer() +
                           "\n" + iae.getMessage());
               }
            }
         }
         // if we didnt find any commands matching
         if (cl == null)
         {
            console.pushToStdOut(output.getBuffer() + ": command not found." + Config.getLineSeparator());
         }

         return result;
      }
   }

}
TOP

Related Classes of org.jboss.forge.aesh.ForgeShellImpl$ForgeConsoleCallback

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.