/* * Copyright 2014 Yaroslav Mytkalyk * 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. */ package com.docd.purefm.commandline; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import java.util.LinkedList; import java.util.List; /** * Executes Shell commands and waits for termination * * @author Doctoror */ public final class CommandLine { private static final int EXIT_CODE_SUCCESS = 0; private CommandLine() {} @Nullable public static synchronized List<String> executeForResult(@NonNull final Command command) { final List<String> result = new LinkedList<>(); final ExecutionStatus status = new ExecutionStatus(); command.setCommandListener(new Command.CommandListener() { @Override public void commandOutput(int i, String s) { result.add(s); } @Override public void commandTerminated(int i, String s) { synchronized (status) { status.finished = true; status.notify(); } } @Override public void commandCompleted(int i, int exitCode) { status.exitCode = exitCode; synchronized (status) { status.finished = true; status.notify(); } } }); if (ShellHolder.getInstance().execute(command)) { synchronized (status) { if (!status.finished) { try { status.wait(); } catch (InterruptedException e) { command.terminate("Interrupted"); } } } if (status.exitCode == EXIT_CODE_SUCCESS) { return result; } } return null; } public static synchronized boolean execute(@NonNull final Command command) { final ExecutionStatus status = new ExecutionStatus(); command.setCommandListener(new Command.CommandListener() { @Override public void commandOutput(int id, String line) { } @Override public void commandTerminated(int id, String reason) { synchronized (status) { status.finished = true; status.notify(); } } @Override public void commandCompleted(int id, int exitCode) { status.exitCode = exitCode; synchronized (status) { status.finished = true; status.notify(); } } }); if (ShellHolder.getInstance().execute(command)) { synchronized (status) { if (!status.finished) { try { status.wait(); } catch (InterruptedException e) { command.terminate("Interrupted"); } } } return status.exitCode == EXIT_CODE_SUCCESS; } return false; } public static boolean execute(@NonNull final String command) { return ShellHolder.getInstance().execute(new Command(ShellHolder.getNextCommandId(), command)); } public static final class ExecutionStatus { public int exitCode = -1; public boolean finished; } // private static String writeCommand(final String command, final DataOutputStream outputStream) throws IOException { // /* // * Termination string should also contain symbols not allowed in filesystems to reduce // * possibility of misinterpreting the stdout output with termination string using ls command // */ // final String terminationLine = "/:" + new String(Hex.encodeHex(DigestUtils.md5(command))); // outputStream.writeBytes(appendTerminationCommands(command, terminationLine)); // outputStream.flush(); // return terminationLine; // } // // private static String appendTerminationCommands(final String command, final String terminationString) { // return command + ";echo \"" + terminationString + "\";echo $?\n"; // } // // private static boolean cleanInputStream(final BufferedReader reader, final String terminationLine) throws IOException { // String line; // while ((line = reader.readLine()) != null && !line.equals(terminationLine)); // final String errorCode = reader.readLine(); // try { // return Integer.parseInt(errorCode) == 0; // } catch (NumberFormatException e) { // Log.w("inputStreamToStringList", "Expected error code, but received \'" + errorCode + "\'"); // return false; // } // } // // private static boolean inputStreamToStringList(final BufferedReader reader, final String terminationLine, final List<String> target) throws IOException { // String line; // while ((line = reader.readLine()) != null && !line.equals(terminationLine)) { // target.add(line); // } // final String errorCode = reader.readLine(); // try { // return Integer.parseInt(errorCode) == 0; // } catch (NumberFormatException e) { // Log.w("inputStreamToStringList", "Expected error code, but received \'" + errorCode + "\'"); // return false; // } // } }