Package org.jboss.forge.addon.shell.command

Source Code of org.jboss.forge.addon.shell.command.RunCommand$ScriptCommandListener

/**
* Copyright 2013 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.addon.shell.command;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import javax.inject.Inject;

import org.jboss.aesh.console.settings.SettingsBuilder;
import org.jboss.forge.addon.resource.DirectoryResource;
import org.jboss.forge.addon.resource.FileResource;
import org.jboss.forge.addon.resource.Resource;
import org.jboss.forge.addon.resource.ResourceFactory;
import org.jboss.forge.addon.resource.util.ResourcePathResolver;
import org.jboss.forge.addon.shell.Shell;
import org.jboss.forge.addon.shell.ShellFactory;
import org.jboss.forge.addon.shell.ui.AbstractShellCommand;
import org.jboss.forge.addon.shell.ui.ShellContext;
import org.jboss.forge.addon.ui.command.AbstractCommandExecutionListener;
import org.jboss.forge.addon.ui.command.CommandExecutionListener;
import org.jboss.forge.addon.ui.command.UICommand;
import org.jboss.forge.addon.ui.context.UIBuilder;
import org.jboss.forge.addon.ui.context.UIContext;
import org.jboss.forge.addon.ui.context.UIExecutionContext;
import org.jboss.forge.addon.ui.hints.InputType;
import org.jboss.forge.addon.ui.impl.result.CompositeResultImpl;
import org.jboss.forge.addon.ui.input.UIInput;
import org.jboss.forge.addon.ui.input.UIInputMany;
import org.jboss.forge.addon.ui.metadata.UICommandMetadata;
import org.jboss.forge.addon.ui.metadata.WithAttributes;
import org.jboss.forge.addon.ui.result.Failed;
import org.jboss.forge.addon.ui.result.Result;
import org.jboss.forge.addon.ui.result.Results;
import org.jboss.forge.addon.ui.util.Metadata;
import org.jboss.forge.furnace.exception.ContainerException;
import org.jboss.forge.furnace.spi.ListenerRegistration;
import org.jboss.forge.furnace.util.Assert;
import org.jboss.forge.furnace.util.OperatingSystemUtils;

/**
* Implementation of the "run script" command
*
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*/
public class RunCommand extends AbstractShellCommand
{
   @Inject
   ResourceFactory resourceFactory;

   @Inject
   @WithAttributes(label = "Timeout (seconds)", defaultValue = "15", required = false,
            description = "Set the timeout after which this script should abort if execution has not completed.")
   private UIInput<Integer> timeout;

   @Inject
   @WithAttributes(label = "Arguments", type = InputType.FILE_PICKER, required = true)
   private UIInputMany<String> arguments;

   @Inject
   private ShellFactory shellFactory;

   @Override
   public UICommandMetadata getMetadata(UIContext context)
   {
      return Metadata.from(super.getMetadata(context), getClass()).name("run")
               .description("Execute/run a forge script file.");
   }

   @Override
   public void initializeUI(UIBuilder builder) throws Exception
   {
      builder.add(arguments);
   }

   @Override
   public Result execute(UIExecutionContext context) throws Exception
   {
      List<Result> results = new ArrayList<>();
      Resource<?> currentResource = (Resource<?>) context.getUIContext().getInitialSelection().get();

      ALL: for (String path : arguments.getValue())
      {
         List<Resource<?>> resources = new ResourcePathResolver(resourceFactory, currentResource, path).resolve();
         for (Resource<?> resource : resources)
         {
            if (resource.exists())
            {
               final PipedOutputStream stdin = new PipedOutputStream();
               final ByteArrayOutputStream stdout = new ByteArrayOutputStream();
               final ByteArrayOutputStream stderr = new ByteArrayOutputStream();
               BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));

               Shell scriptShell = shellFactory.createShell(((FileResource<?>) context.getUIContext()
                        .getInitialSelection().get()).getUnderlyingResourceObject(),
                        new SettingsBuilder().inputStream(new PipedInputStream(stdin))
                                 .outputStream(new PrintStream(stdout))
                                 .outputStreamError(new PrintStream(stderr)).create());

               BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getResourceInputStream()));

               try
               {
                  long startTime = System.currentTimeMillis();
                  while (reader.ready())
                  {
                     try
                     {
                        Result result = execute(scriptShell, writer, reader.readLine(), timeout.getValue(),
                                 TimeUnit.SECONDS, startTime);

                        results.add(result);

                        context.getUIContext().getProvider().getOutput().out().write(stdout.toByteArray());
                        context.getUIContext().getProvider().getOutput().err().write(stderr.toByteArray());

                        if (result instanceof Failed)
                           break ALL;
                     }
                     catch (TimeoutException e)
                     {
                        results.add(Results.fail(path + ": timed out.", e));
                        break ALL;
                     }
                  }
               }
               finally
               {
                  reader.close();
                  scriptShell.close();
               }
            }
            else
            {
               results.add(Results.fail(path + ": not found."));
               break ALL;
            }
         }
      }

      return CompositeResultImpl.from(results);
   }

   public Result execute(Shell shell, BufferedWriter stdin, String line, int quantity, TimeUnit unit, long startTime)
            throws TimeoutException
   {
      Assert.notNull(line, "Line to execute cannot be null.");

      Result result;
      if (!line.trim().endsWith(OperatingSystemUtils.getLineSeparator()))
         line = line + OperatingSystemUtils.getLineSeparator();
      ScriptCommandListener listener = new ScriptCommandListener();
      ListenerRegistration<CommandExecutionListener> listenerRegistration = shell.addCommandExecutionListener(listener);
      try
      {
         stdin.write(line);
         stdin.flush();
         while (!listener.isExecuted())
         {
            if (System.currentTimeMillis() > (startTime + TimeUnit.MILLISECONDS.convert(quantity, unit)))
            {
               throw new TimeoutException("Timeout expired waiting for command [" + line + "] to execute.");
            }

            try
            {
               Thread.sleep(10);
            }
            catch (InterruptedException e)
            {
               throw new ContainerException("Command [" + line + "] did not respond.", e);
            }
         }
         result = listener.getResult();
      }
      catch (IOException e)
      {
         throw new RuntimeException("Failed to execute command.", e);
      }
      finally
      {
         listenerRegistration.removeListener();
      }
      return result;
   }

   public class ScriptCommandListener extends AbstractCommandExecutionListener
   {
      Result result;

      @Override
      public void preCommandExecuted(UICommand command, UIExecutionContext context)
      {
      }

      @Override
      public void postCommandExecuted(UICommand command, UIExecutionContext context, Result result)
      {
         synchronized (this)
         {
            this.result = result;
         }
      }

      @Override
      public void postCommandFailure(UICommand command, UIExecutionContext context, Throwable failure)
      {
         synchronized (this)
         {
            this.result = Results.fail("Error encountered during command execution.", failure);
         }
      }

      public boolean isExecuted()
      {
         synchronized (this)
         {
            return result != null;
         }
      }

      public Result getResult()
      {
         synchronized (this)
         {
            return result;
         }
      }

      public void reset()
      {
         synchronized (this)
         {
            result = null;
         }
      }
   }

   @Override
   public boolean isEnabled(ShellContext context)
   {
      return super.isEnabled(context) && context.getInitialSelection().get() instanceof DirectoryResource;
   }
}
TOP

Related Classes of org.jboss.forge.addon.shell.command.RunCommand$ScriptCommandListener

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.