All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.tidalwave.blueshades.util.Executor Maven / Gradle / Ivy

/***********************************************************************************************************************
 *
 * blueShades - a Java UI for Argyll
 * Copyright (C) 2011-2016 by Tidalwave s.a.s. (http://www.tidalwave.it)
 *
 ***********************************************************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 ***********************************************************************************************************************
 *
 * WWW: http://blueshades.tidalwave.it
 * SCM: https://bitbucket.org/tidalwave/blueshades-src
 *
 **********************************************************************************************************************/
package it.tidalwave.blueshades.util;

import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import it.tidalwave.util.NotFoundException;
import lombok.AccessLevel;
import lombok.Cleanup;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/***********************************************************************************************************************
 * 
 * @author  Fabrizio Giudici
 * @version $Id$
 *
 **********************************************************************************************************************/
@ThreadSafe @NoArgsConstructor(access=AccessLevel.PRIVATE) @Slf4j
public class Executor 
  {
    /*******************************************************************************************************************
     * 
     *
     ******************************************************************************************************************/
    @RequiredArgsConstructor(access=AccessLevel.PACKAGE)
    public class ConsoleOutput
      {
        @Nonnull
        private final InputStream input;
        
        @Getter
        private final List content = Collections.synchronizedList(new ArrayList());
        
        /***************************************************************************************************************
         * 
         *
         ***************************************************************************************************************/
        @Nonnull
        public ConsoleOutput start()
          {
            Executors.newSingleThreadExecutor().submit(runnable); 
            return this;
          }
        
        /***************************************************************************************************************
         * 
         *
         ***************************************************************************************************************/
        private final Runnable runnable = new Runnable() 
          {
            @Override
            public void run() 
              {
                try
                  {
                    read();  
                  }
                catch (IOException e)
                  {
                    log.warn("while reading from process console", e); 
                  }
              }
          };
        
        /***************************************************************************************************************
         * 
         *
         ***************************************************************************************************************/
        @Nonnull
        public Scanner filteredAndSplitBy (final @Nonnull String filterRegexp, final @Nonnull String delimiterRegexp)
          {
            final String string = filteredBy(filterRegexp).get(0);
            return new Scanner(string).useDelimiter(Pattern.compile(delimiterRegexp));
          }
        
        /***************************************************************************************************************
         * 
         *
         ***************************************************************************************************************/
        @Nonnull
        public List filteredBy (final @Nonnull String filter)
          {
            final Pattern p = Pattern.compile(filter);
            final List result = new ArrayList();

            for (final String s : new ArrayList(content))
              {
                final Matcher m = p.matcher(s);
                
                if (m.matches())
                  {
                    result.add(m.group(1));  
                  }
              }
            
            return result;
          }
        
        /***************************************************************************************************************
         * 
         *
         ***************************************************************************************************************/
        @Nonnull
        public ConsoleOutput waitFor (final @Nonnull String regexp)
          throws InterruptedException, IOException
          {
            log.info("waitFor({})", regexp);
            
            while (filteredBy(regexp).isEmpty())
              {
                try
                  {
                    final int exitValue = process.exitValue();
                    throw new IOException("Process exited with " + exitValue);  
                  }
                catch (IllegalThreadStateException e) // ok, process not terminated yet
                  {
                    synchronized (this)
                      {
                        wait(50); // FIXME: polls because it doesn't get notified
                      }
                  }
              }
            
            return this;
          } 
        
        /***************************************************************************************************************
         * 
         *
         ***************************************************************************************************************/
        public void clear()
          {
            content.clear();  
          }
    
        /***************************************************************************************************************
         * 
         *
         ***************************************************************************************************************/
        private void read()
          throws IOException
          {
            final @Cleanup BufferedReader br = new BufferedReader(new InputStreamReader(input));

            for (;;)
              {
                final String s = br.readLine();

                if (s == null)
                  { 
                    break;   
                  }  

                log.info(">>>>>>>> {}", s);
                content.add(s);  
                
                synchronized (this)
                  {
                    notifyAll();  
                  }
              }

            br.close();
          }
      }
    
    private final List arguments = new ArrayList();

    private Process process;
    
    @Getter
    private ConsoleOutput stdout;
    
    @Getter
    private ConsoleOutput stderr;
    
    private PrintWriter stdin;
    
    /*******************************************************************************************************************
     * 
     *
     ******************************************************************************************************************/
    @Nonnull
    public static Executor forExecutable (final @Nonnull String executable)
      {
        final Executor executor = new Executor();
        final String argyllHome = System.getenv("ARGYLL_HOME"); // used during development
//        final String path = (argyllHome != null) ? argyllHome + "/bin/"
//                                                 : (System.getProperty("netbeans.home") + "/../../../../MacOS/Argyll_V1.3.5/bin/");
        final String path = "/Users/fritz/Applications/Argyll_V1.3.5/bin/";
        executor.arguments.add(new File(path + executable).getAbsolutePath());
        return executor;
      }
    
//    /*******************************************************************************************************************
//     * 
//     *
//     ******************************************************************************************************************/
//    @Nonnull
//    private static String findPath (final @Nonnull String executable)
//      throws NotFoundException
//      {
//        for (final String path : System.getenv("PATH").split(File.pathSeparator))            
//          {
//            final File file = new File(new File(path), executable);
//            
//            if (file.canExecute())
//              {
//                return file.getAbsolutePath(); 
//              }
//          }
//        
//        throw new NotFoundException("Can't find " + executable + " in PATH");
//      }
    
    /*******************************************************************************************************************
     * 
     *
     ******************************************************************************************************************/
    @Nonnull
    public Executor withArgument (final @Nonnull String argument)
      {
        arguments.add(argument);
        return this;
      }
    
    /*******************************************************************************************************************
     * 
     *
     ******************************************************************************************************************/
    @Nonnull
    public Executor start()
      throws IOException
      {
        log.info(">>>> executing {} ...", arguments);
        
        final List environment = new ArrayList();
        
//        for (final Entry e : System.getenv().entrySet())
//          {
//            environment.add(String.format("%s=%s", e.getKey(), e.getValue()));  
//          }
        
        environment.add("ARGYLL_NOT_INTERACTIVE=true");
        log.info(">>>> environment: {}", environment);
        process = Runtime.getRuntime().exec(arguments.toArray(new String[0]),
                                            environment.toArray(new String[0]));
        
        stdout = new ConsoleOutput(process.getInputStream()).start();
        stderr = new ConsoleOutput(process.getErrorStream()).start();
        stdin  = new PrintWriter(process.getOutputStream(), true);
        
        return this;
      }

    /*******************************************************************************************************************
     * 
     *
     ******************************************************************************************************************/
    @Nonnull
    public Executor waitForCompletion()
      throws IOException, InterruptedException
      {
        if (process.waitFor() != 0)
          {
//            throw new IOException("Process exited with " + process.exitValue());  
          }
        
        return this;
      }

    /*******************************************************************************************************************
     * 
     *
     ******************************************************************************************************************/
    @Nonnull
    public Executor send (final @Nonnull String string) 
      throws IOException
      {
        log.info(">>>> sending '{}'...", string);
        stdin.println(string);
        return this;
      }
  }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy