/******************************************************************************* * Copyright (c) 2009, 2016 Red Hat, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Red Hat - initial API and implementation *******************************************************************************/ package org.eclipse.linuxtools.rpm.core.utils; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.SequenceInputStream; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.linuxtools.tools.launch.core.factory.RuntimeProcessFactory; import org.eclipse.osgi.util.NLS; import org.osgi.framework.FrameworkUtil; /** * Utilities for calling system executables. */ public class Utils { /** * Runs the given command and parameters. * * @param command * The command with all parameters. * @return Stream containing the combined content of stderr and stdout. * @throws IOException * If IOException occurs. */ public static BufferedProcessInputStream runCommandToInputStream(String... command) throws IOException { return runCommandToInputStream(null, command); } /** * Runs the given command and parameters. * @param project rpm project * * @param command * The command with all parameters. * @return Stream containing the combined content of stderr and stdout. * @throws IOException * If IOException occurs. * @since 2.1 */ private static BufferedProcessInputStream runCommandToInputStream(IProject project, String... command) throws IOException { Process p = RuntimeProcessFactory.getFactory().exec(command, project); return new BufferedProcessInputStream(p); } /** * Runs the given command and parameters. Note that the command's process can * be terminated by interrupting the thread this method runs in, but only after * the process' execution has begun. * * @param outStream * The stream to write the output to. * @param project * The project which is executing this command. * @param command * The command with all parameters. * @return An IStatus indicating the result of the command. * @throws IOException If an IOException occurs. * @since 1.1 */ public static IStatus runCommand(final OutputStream outStream, IProject project, String... command) throws IOException { return watchProcess(outStream, RuntimeProcessFactory.getFactory().exec(command, project)); } /** * Watches the streams of the given running process. Note that the process can * be terminated at any time by interrupting the thread this method runs in. * * @param outStream * The stream to write the output to. * @param child * The process to watch the output of. * @return An IStatus indicating the result of the command. * @since 2.2 */ public static IStatus watchProcess(final OutputStream outStream, Process child) { final BufferedInputStream in = new BufferedInputStream( new SequenceInputStream(child.getInputStream(), child.getErrorStream())); Thread readinJob = new Thread(() -> { try { int i; while ((i = in.read()) != -1) { outStream.write(i); } outStream.flush(); outStream.close(); in.close(); } catch (IOException e) {} return; }); readinJob.start(); boolean canceled = false; try { // Catch interrupt attempts made before the wait if (Thread.currentThread().isInterrupted()) { throw new InterruptedException(); } child.waitFor(); } catch (InterruptedException e) { child.destroy(); canceled = true; } while (readinJob.isAlive()) { try { readinJob.join(); } catch (InterruptedException e) {} } if (canceled) { return Status.CANCEL_STATUS; } if (child.exitValue() != 0) { return new Status(IStatus.ERROR, FrameworkUtil.getBundle(Utils.class).getSymbolicName(), NLS.bind(Messages.Utils_NON_ZERO_RETURN_CODE, child.exitValue()), null); } return Status.OK_STATUS; } /** * Run a command and return its output. * @param command The command to execute. * @return The output of the executed command. * @throws IOException If an I/O exception occurred. */ public static String runCommandToString(String... command) throws IOException { return runCommandToString(null, command); } /** * Run a command and return its output. * @param project rpm Project * @param command The command to execute. * @return The output of the executed command. * @throws IOException If an I/O exception occurred. * @since 2.1 */ public static String runCommandToString(IProject project, String... command) throws IOException { BufferedInputStream in = runCommandToInputStream(project, command); return inputStreamToString(in); } /** * Reads the content of the given InputStream and returns its textual * representation. * * @param stream * The InputStream to read. * @return Textual content of the stream. * @throws IOException If an IOException occurs. */ private static String inputStreamToString(InputStream stream) throws IOException { StringBuilder retStr = new StringBuilder(); int c; while ((c = stream.read()) != -1) { retStr.append((char) c); } stream.close(); return retStr.toString(); } }