1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package ohos.devtools.datasources.transport.hdc; 17 18 import ohos.devtools.datasources.utils.plugin.service.PlugManager; 19 import ohos.devtools.datasources.utils.profilerlog.ProfilerLogManager; 20 import org.jetbrains.annotations.NotNull; 21 import org.slf4j.Logger; 22 import org.slf4j.LoggerFactory; 23 24 import java.io.IOException; 25 import java.io.InputStream; 26 import java.util.ArrayList; 27 import java.util.concurrent.Callable; 28 import java.util.concurrent.ExecutionException; 29 import java.util.concurrent.ExecutorService; 30 import java.util.concurrent.Future; 31 import java.util.concurrent.SynchronousQueue; 32 import java.util.concurrent.ThreadPoolExecutor; 33 import java.util.concurrent.TimeUnit; 34 import java.util.concurrent.TimeoutException; 35 36 /** 37 * CmdExecutors 38 * 39 * @since 2021/9/20 40 */ 41 public class CmdExecutors { 42 private static final Logger LOGGER = LoggerFactory.getLogger(CmdExecutors.class); 43 44 static ExecutorService pool = 45 new ThreadPoolExecutor(0, Integer.MAX_VALUE, 3L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); 46 47 /** 48 * executeCommand 49 * 50 * @param command command 51 * @param timeout timeout 52 * @return ExecResult 53 */ executeCommand(ArrayList<String> command, long timeout)54 public ExecResult executeCommand(ArrayList<String> command, long timeout) { 55 if (ProfilerLogManager.isInfoEnabled()) { 56 LOGGER.info("executeCommand"); 57 } 58 Process process = null; 59 InputStream pIn = null; 60 InputStream pErr = null; 61 IoStreamConsumer outputGobbler = null; 62 IoStreamConsumer errorGobbler = null; 63 Future<Integer> executeFuture = null; 64 try { 65 process = new ProcessBuilder(command).start(); 66 pIn = process.getInputStream(); 67 pErr = process.getErrorStream(); 68 if (PlugManager.getInstance().getSystemOsName().contains("win") && command.contains("hdc_std")) { 69 outputGobbler = new IoStreamConsumer(pIn); 70 errorGobbler = new IoStreamConsumer(pErr); 71 } else { 72 outputGobbler = new IoReadLineConsumer(pIn); 73 errorGobbler = new IoReadLineConsumer(pErr); 74 } 75 outputGobbler.start(); 76 errorGobbler.start(); 77 Callable<Integer> call = new StreamCallBack(process); 78 executeFuture = pool.submit(call); 79 int exitCode = executeFuture.get(timeout, TimeUnit.SECONDS); 80 ArrayList<String> content = outputGobbler.getContent(); 81 return new ExecResult(exitCode, content); 82 } catch (InterruptedException exception) { 83 if (ProfilerLogManager.isErrorEnabled()) { 84 LOGGER.error("command [" + command + "] failed.", exception); 85 } 86 return getExecResult(outputGobbler, errorGobbler, -1); 87 } catch (ExecutionException | IOException | TimeoutException timeoutException) { 88 if (ProfilerLogManager.isErrorEnabled()) { 89 LOGGER.error("command [" + command + "] failed.", timeoutException); 90 } 91 return getExecResult(outputGobbler, errorGobbler, -2); 92 } finally { 93 if (executeFuture != null) { 94 executeFuture.cancel(true); 95 } 96 if (process != null) { 97 process.destroy(); 98 } 99 } 100 } 101 102 class StreamCallBack implements Callable<java.lang.Integer> { 103 Process process; 104 105 /** 106 * StreamCallBack 107 * 108 * @param process process 109 */ StreamCallBack(Process process)110 public StreamCallBack(Process process) { 111 this.process = process; 112 } 113 114 @Override call()115 public java.lang.Integer call() throws Exception { 116 process.waitFor(); 117 return process.exitValue(); 118 } 119 } 120 121 /** 122 * executeCommand 123 * 124 * @param command command 125 * @param timeout timeout 126 * @return ExecResult 127 */ executeCommandByLine(ArrayList<String> command, long timeout)128 public ExecResult executeCommandByLine(ArrayList<String> command, long timeout) { 129 if (ProfilerLogManager.isInfoEnabled()) { 130 LOGGER.info("executeCommand"); 131 } 132 Process process = null; 133 InputStream pIn = null; 134 InputStream pErr = null; 135 IoReadLineConsumer outputGobbler = null; 136 IoReadLineConsumer errorGobbler = null; 137 Future<Integer> executeFuture = null; 138 try { 139 process = new ProcessBuilder(command).start(); 140 Process prcess = process; 141 pIn = process.getInputStream(); 142 outputGobbler = new IoReadLineConsumer(pIn); 143 outputGobbler.start(); 144 pErr = process.getErrorStream(); 145 errorGobbler = new IoReadLineConsumer(pErr); 146 errorGobbler.start(); 147 Callable<Integer> call = new StreamCallBack(process); 148 executeFuture = pool.submit(call); 149 int exitCode = executeFuture.get(timeout, TimeUnit.SECONDS); 150 ArrayList<String> content = outputGobbler.getContent(); 151 return new ExecResult(exitCode, content); 152 } catch (IOException | TimeoutException | ExecutionException | InterruptedException exception) { 153 if (ProfilerLogManager.isErrorEnabled()) { 154 LOGGER.error("command [" + command + "] failed.", exception); 155 } 156 return getExecResult(outputGobbler, errorGobbler, -1); 157 } finally { 158 if (executeFuture != null) { 159 executeFuture.cancel(true); 160 } 161 if (process != null) { 162 process.destroy(); 163 } 164 } 165 } 166 167 @NotNull getExecResult(IoStreamConsumer outputGobbler, IoStreamConsumer errorGobbler, int exitCode)168 private ExecResult getExecResult(IoStreamConsumer outputGobbler, IoStreamConsumer errorGobbler, int exitCode) { 169 if (ProfilerLogManager.isInfoEnabled()) { 170 LOGGER.info("getExecResult"); 171 } 172 if (errorGobbler.getContent().size() > 0 && outputGobbler.getContent().size() > 0) { 173 ArrayList<String> result = new ArrayList<>(); 174 result.addAll(outputGobbler.getContent()); 175 result.addAll(errorGobbler.getContent()); 176 return new ExecResult(exitCode, result); 177 } else if (errorGobbler.getContent().size() > 0) { 178 return new ExecResult(exitCode, errorGobbler.getContent()); 179 } else { 180 return new ExecResult(exitCode, outputGobbler.getContent()); 181 } 182 } 183 }