diff --git a/nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/KeystoreManager.java b/nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/KeystoreManager.java index 48cd4b72eb6..cec62b8ff23 100644 --- a/nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/KeystoreManager.java +++ b/nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/KeystoreManager.java @@ -38,10 +38,10 @@ import com.sun.enterprise.admin.servermgmt.pe.PEFileLayout; import com.sun.enterprise.universal.glassfish.ASenvPropertyReader; import com.sun.enterprise.universal.io.SmartFile; +import com.sun.enterprise.universal.process.ProcessManager; +import com.sun.enterprise.universal.process.ProcessManagerException; import com.sun.enterprise.universal.process.ProcessUtils; -import com.sun.enterprise.util.ExecException; import com.sun.enterprise.util.OS; -import com.sun.enterprise.util.ProcessExecutor; import com.sun.enterprise.util.SystemPropertyConstants; import com.sun.enterprise.util.i18n.StringManager; import com.sun.enterprise.util.net.NetUtils; @@ -86,46 +86,47 @@ public class KeystoreManager { KEYTOOL_CMD = nonFinalKeyTool; } - protected static class KeytoolExecutor extends ProcessExecutor { + protected static class KeytoolExecutor extends ProcessManager { - public KeytoolExecutor(String[] args, long timeoutInSeconds) { - super(args, timeoutInSeconds); - setExecutionRetentionFlag(true); + public KeytoolExecutor(String[] args, int timeoutInSeconds) { + super(args); + setTimeoutMsec(timeoutInSeconds * 1000); addKeytoolCommand(); } - public KeytoolExecutor(String[] args, long timeoutInSeconds, String[] inputLines) { - super(args, timeoutInSeconds, inputLines); - setExecutionRetentionFlag(true); + public KeytoolExecutor(String[] args, int timeoutInSeconds, String[] inputLines) { + super(args); + setTimeoutMsec(timeoutInSeconds * 1000); + setStdinLines(Arrays.asList(inputLines)); addKeytoolCommand(); } // We must override this message so that the stdout appears in the exec exception. // Keytool seems to output errors to stdout. - @Override protected String getExceptionMessage() { - return getLatestOutput(mOutFile) + " " + getFileBuffer(mErrFile); + return getStdout() + " " + getStderr(); } private void addKeytoolCommand() { + String[] mCmdStrings = builder.command().toArray(new String[0]); if (!mCmdStrings[0].equals(KEYTOOL_CMD)) { String[] newArgs = new String[mCmdStrings.length + 1]; newArgs[0] = KEYTOOL_CMD; System.arraycopy(mCmdStrings, 0, newArgs, 1, mCmdStrings.length); mCmdStrings = newArgs; + builder.command(Arrays.asList(mCmdStrings)); } } public void execute(String keystoreErrorMsg, File keystoreName) throws RepositoryException { try { - super.execute(); - if (getProcessExitValue() != 0) { + if (super.execute() != 0) { throw new RepositoryException( - _strMgr.getString(keystoreErrorMsg, keystoreName) + getLastExecutionError() + " " + getLastExecutionOutput()); + _strMgr.getString(keystoreErrorMsg, keystoreName) + getStderr() + " " + getStdout()); } - } catch (ExecException ex) { + } catch (ProcessManagerException ex) { throw new RepositoryException( - _strMgr.getString(keystoreErrorMsg, keystoreName) + getLastExecutionError() + " " + getLastExecutionOutput(), ex); + _strMgr.getString(keystoreErrorMsg, keystoreName) + getStderr() + " " + getStdout(), ex); } } } diff --git a/nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/services/SMFService.java b/nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/services/SMFService.java index d14343d0481..c6caff58ef9 100644 --- a/nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/services/SMFService.java +++ b/nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/services/SMFService.java @@ -20,7 +20,6 @@ import com.sun.enterprise.universal.io.SmartFile; import com.sun.enterprise.universal.process.ProcessManager; import com.sun.enterprise.util.OS; -import com.sun.enterprise.util.ProcessExecutor; import com.sun.enterprise.util.SystemPropertyConstants; import com.sun.enterprise.util.i18n.StringManager; import com.sun.enterprise.util.io.FileUtils; @@ -400,11 +399,11 @@ private boolean isUserSmfAuthorized(final String user, final StringBuilder auths } try { final String[] cmd = new String[] { path2Auths, user }; - ProcessExecutor pe = new ProcessExecutor(cmd); - pe.setExecutionRetentionFlag(true); - pe.execute(); - auths.append(pe.getLastExecutionOutput()); - final StringTokenizer st = new StringTokenizer(pe.getLastExecutionOutput(), at); + ProcessManager pm = new ProcessManager(cmd); + pm.setTimeoutMsec(600 * 1000); + pm.execute(); + auths.append(pm.getStdout()); + final StringTokenizer st = new StringTokenizer(pm.getStdout(), at); while (st.hasMoreTokens()) { String t = st.nextToken(); t = t.trim(); @@ -423,9 +422,9 @@ private boolean serviceNameExists(final String sn) { boolean exists = false; try { final String[] cmd = new String[] { "/usr/bin/svcs", sn }; - ProcessExecutor pe = new ProcessExecutor(cmd); - pe.setExecutionRetentionFlag(true); - pe.execute(); + ProcessManager pm = new ProcessManager(cmd); + pm.setTimeoutMsec(600 * 1000); + pm.execute(); exists = true; } catch (final Exception e) { //returns a non-zero status -- the service does not exist, status is already set @@ -462,8 +461,9 @@ private void validateManifest(final String manifestPath) throws Exception { private void validateService() throws Exception { final String[] cmda = new String[] { SMFService.SVCCFG, "validate", getManifestFilePath() }; - final ProcessExecutor pe = new ProcessExecutor(cmda); - pe.execute(); + final ProcessManager pm = new ProcessManager(cmda); + pm.setTimeoutMsec(600 * 1000); + pm.execute(); if (info.trace) { printOut("Validated the SMF Service: " + info.fqsn + " using: " + SMFService.SVCCFG); } @@ -471,13 +471,13 @@ private void validateService() throws Exception { private boolean importService() throws Exception { final String[] cmda = new String[] { SMFService.SVCCFG, "import", getManifestFilePath() }; - final ProcessExecutor pe = new ProcessExecutor(cmda); - + final ProcessManager pm = new ProcessManager(cmda); + pm.setTimeoutMsec(600 * 1000); if (info.dryRun) { cleanupManifest(); } else { - pe.execute(); //throws ExecException in case of an error + pm.execute(); //throws ExecException in case of an error } if (info.trace) { diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/universal/process/ProcessManager.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/universal/process/ProcessManager.java index 6cfca745c95..556938cb00c 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/universal/process/ProcessManager.java +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/universal/process/ProcessManager.java @@ -42,11 +42,10 @@ * @since JDK 1.4 * @author bnevins 2005 */ -@Deprecated -public final class ProcessManager { +public class ProcessManager { private static final Logger LOG = System.getLogger(ProcessManager.class.getName()); - private final ProcessBuilder builder; + protected final ProcessBuilder builder; private final StringBuffer sb_out; private final StringBuffer sb_err; private int timeout; diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/ProcessExecutor.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/ProcessExecutor.java deleted file mode 100644 index e2fa146108e..00000000000 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/ProcessExecutor.java +++ /dev/null @@ -1,657 +0,0 @@ -/* - * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.enterprise.util; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.RandomAccessFile; -import java.util.ArrayList; - - -/** - * @author Kedar - * @version 1.0 - * @deprecated Use ProcessManager instead - */ -@Deprecated -public class ProcessExecutor { - public static final long kDefaultTimeoutMillis = 600000; - public static final long kSleepTime = 2000; - private static final long DEFAULT_TIMEOUT_SEC = 600; - private static final String NEWLINE = System.getProperty("line.separator"); - private long mTimeoutMilliseconds = 0; - protected String[] mCmdStrings = null; - protected File mOutFile = null; - protected File mErrFile = null; - private OutputStream mOutStream = null; - private OutputStream mErrStream = null; - private File mWorkingDir = null; //working directory - private String[] mEnv = null; //environment - private String[] mInputLines = null; // strings to set in process's InputStream (like from redirection) - private int mExitValue = -1; - private Process mSubProcess = null; // used to get handle to child process for ProcessManager funtionality - private boolean mVerboseMode = false; - private boolean retainExecutionLogs = false; - private String lastExecutionOutputString = null; - private String lastExecutionErrorString = null; - private boolean bDebug = false; - - /** - * Creates new ProcessExecutor - */ - public ProcessExecutor(String[] cmd) { - this(cmd, DEFAULT_TIMEOUT_SEC, null); - } - - /** - * Creates new ProcessExecutor - */ - public ProcessExecutor(String[] cmd, String[] inputLines) { - this(cmd, DEFAULT_TIMEOUT_SEC, inputLines); - } - - /** - * Creates new ProcessExecutor - */ - public ProcessExecutor(String[] cmd, long timeoutSeconds) { - this(cmd, timeoutSeconds, null); - } - - public ProcessExecutor(String[] cmd, long timeoutSeconds, String[] inputLines) { - this(cmd, timeoutSeconds, inputLines, null, null); - } - - /** - * Creates a new - * ProcessExecutor that executes the given command. - * - * @param cmd String that has command name and its command line arguments - * @param timeoutSeconds long integer timeout to be applied in seconds. - * After this time if the process to execute does not end, it will be - * destroyed. - */ - public ProcessExecutor(String[] cmd, long timeoutSeconds, String[] inputLines, - String[] env, File workingDir) { - mCmdStrings = cmd; - mInputLines = inputLines; - mEnv = env; - mWorkingDir = workingDir; - char fwdSlashChar = '/'; - char backSlashChar = '\\'; - - if (System.getProperty("Debug") != null) { - // turn on debug, this option was added to help developers - // debug the their code - bDebug = true; - } - - for (int i = 0; i < mCmdStrings.length; i++) { - if (OS.isUnix()) { - mCmdStrings[i] = mCmdStrings[i].replace(backSlashChar, fwdSlashChar); - } - else { - mCmdStrings[i] = mCmdStrings[i].replace(fwdSlashChar, backSlashChar); - } - } - mTimeoutMilliseconds = timeoutSeconds * 1000; - } - - /** - * This is the setting after the fact that an instance of ProcessExecutor is - * created. This is to be used in case the output and error of the last - * execute call has to be retained for latter analysis. - * - * @param s boolean representing whether to retain, true means the buffers - * will be retained, false otherwise. - */ - public void setExecutionRetentionFlag(final boolean s) { - this.retainExecutionLogs = s; - } - - public boolean getExecutionRetentionFlag() { - return (this.retainExecutionLogs); - } - - /** - * Returns the last LAST_BYTES bytes in the error stream of last execution - * as a String, if the ProcessExecutor was configured properly. It may - * return null if the retentionFlag is set to false. - */ - public String getLastExecutionError() { - return (this.lastExecutionErrorString); - } - - /** - * Returns the last LAST_BYTES bytes in the output stream of last execution - * as a String, if the ProcessExecutor was configured properly. It may - * return null if the retentionFlag is set to false. - */ - public String getLastExecutionOutput() { - return (this.lastExecutionOutputString); - } - - private void init() throws ExecException { - try { - mOutFile = File.createTempFile("stdout", null); - mOutFile.deleteOnExit(); - mErrFile = File.createTempFile("stderr", null); - mErrFile.deleteOnExit(); - } - catch (IllegalArgumentException iae) { - deleteTempFiles(); - throw new ExecException("Internal error (util.ProcessExecutor.init()): " + iae.getMessage()); - } - catch (IOException ioe) { - deleteTempFiles(); - throw new ExecException(cannotCreateTempFiles()); - } - } - - private final static String cannotCreateTempFiles() { - return "Could not create temporary files - check " - + System.getProperty("java.io.tmpdir") - + " to see if its writeable and not-full"; - } - - private void deleteTempFiles() { - if (mOutStream != null) { - try { - mOutStream.flush(); - mOutStream.close(); - } - catch (IOException ioe) { - // Ignore - } - } - - if (mErrStream != null) { - try { - mErrStream.flush(); - mErrStream.close(); - } - catch (IOException ioe) { - // Ignore - } - } - if (mOutFile != null) - delete(mOutFile); - if (mErrFile != null) - delete(mErrFile); - } - - public void execute() throws ExecException { - execute(false); - } - - /* - * Executes the command. Redirects the standard output and error streams - * safely to files. This makes the subprocess NOT block or wait on buffers - * getting flushed. This is done in a threaded manner. Note that the - * subprocess will be killed if it does not end in given timeout. - * - * @throws ExecException if anything goes wrong in subprocess, or subprocess - * terminates abruptly. - */ - public String[] execute(boolean bReturnOutputLines) throws ExecException { - return execute(bReturnOutputLines, true); - } - - /** - * Allows a subclass to control the error message returned when a non-zero - * exit code is returned from a failed execution - * - * @return - */ - protected String getExceptionMessage() { - /* - * read the error message from error file - */ - String errorMessage = getFileBuffer(mErrFile); - if (errorMessage.length() == 0) { - errorMessage = "The Process Output: " + getLatestOutput(mOutFile); - } - return "abnormal subprocess termination: Detailed Message:" + errorMessage; - } - - /* - * Executes the command. Redirects the standard output and error streams - * safely to files. This makes the subprocess NOT block or wait on buffers - * getting flushed. This is done in a threaded manner. Note that the - * subprocess will be killed if it does not end in given timeout. - * - * @throws ExecException if anything goes wrong in subprocess, or subprocess - * terminates abruptly. - */ - public String[] execute(boolean bReturnOutputLines, boolean bStartUpTimeLimit) throws ExecException { - init(); - InputStream inputStream = null; - try { - - if (bDebug) { - System.out.println("\n**** Executing command:"); - for (int ii = 0; ii < mCmdStrings.length; ii++) { - System.out.println(mCmdStrings[ii]); - } - } - - mSubProcess = Runtime.getRuntime().exec(mCmdStrings, mEnv, mWorkingDir); - if (mInputLines != null) - addInputLinesToProcessInput(mSubProcess); - if (!bReturnOutputLines) - mOutStream = redirectProcessOutput(mSubProcess); - else - inputStream = mSubProcess.getInputStream(); //attach to input stream for later reading - mErrStream = redirectProcessError(mSubProcess); - - // see if process should startup in a limited ammount of time - // processes used by ProcessManager don't return - if (bStartUpTimeLimit) { - long timeBefore = System.currentTimeMillis(); - boolean timeoutReached = false; - boolean isSubProcessFinished = false; - boolean shouldBeDone = false; - while (!shouldBeDone) { - sleep(kSleepTime); - long timeAfter = System.currentTimeMillis(); - timeoutReached = (timeAfter - timeBefore) >= mTimeoutMilliseconds; - try { - mExitValue = mSubProcess.exitValue(); - isSubProcessFinished = true; - } - catch (IllegalThreadStateException itse) { - isSubProcessFinished = false; - //ignore exception - } - shouldBeDone = timeoutReached || isSubProcessFinished; - } - if (!isSubProcessFinished) { - mSubProcess.destroy(); - mExitValue = -255; - throw new ExecException("Subprocess timed out after " + mTimeoutMilliseconds + "mS"); - } - else { - mExitValue = mSubProcess.exitValue(); - if (debug()) { - System.out.println("Subprocess command line = " + a2s(mCmdStrings)); - System.out.println("Subprocess exit value = " + mExitValue); - } - if (mExitValue != 0) { - mExitValue = mSubProcess.exitValue(); - if (mExitValue != 0) { - throw new ExecException(getExceptionMessage()); - } - } - } - } - } - catch (SecurityException se) { - throw new ExecException(se.getMessage()); - } - catch (IOException ioe) { - throw new ExecException(ioe.getMessage()); - } - finally { - - // retain buffers before deleting them - retainBuffers(); - - // only delete files if the time is limited - // for processes that don't return, the temp files will remain - if (bStartUpTimeLimit) { - deleteTempFiles(); - } - } - - if (bReturnOutputLines) { - return getInputStrings(inputStream); - } - else { - return null; - } - - } - - /** - * Get the exit value of the process executed. If this method is called - * before process execution is complete (i.e. before execute() method has - * returned, it will return -1. If sub process is terminated at timeout, the - * method will return -255 - */ - public int getProcessExitValue() { - return mExitValue; - } - - private void addInputLinesToProcessInput(Process subProcess) throws ExecException { - if (mInputLines == null) - return; - - PrintWriter out = null; - try { - out = new PrintWriter(new BufferedWriter( - new OutputStreamWriter(subProcess.getOutputStream()))); - - for (int i = 0; i < mInputLines.length; i++) { - if (bDebug) { - System.out.println("InputLine ->" + mInputLines[i] + "<-"); - } - out.println(mInputLines[i]); - } - out.flush(); - } - catch (Exception e) { - throw new ExecException(e.getMessage()); - } - finally { - try { - out.close(); - } - catch (Throwable t) { - } - } - } - - private String[] getInputStrings(InputStream inputStream) throws ExecException { - if (inputStream == null) - return null; - BufferedReader in = null; - ArrayList list = new ArrayList(); - String str; - try { - in = new BufferedReader(new InputStreamReader(inputStream)); - while ((str = in.readLine()) != null) - list.add(str); - if (list.size() < 1) - return null; - return (String[]) list.toArray(new String[list.size()]); - - } - catch (Exception e) { - throw new ExecException(e.getMessage()); - } - finally { - try { - in.close(); - } - catch (Throwable t) { - } - } - } - - private OutputStream redirectProcessOutput(Process subProcess) throws ExecException { - OutputStream out = null; - try { - InputStream in = subProcess.getInputStream(); - // Redirect stderr for verbose mode - if (mVerboseMode) { - // send output to stderr - out = System.err; - } - else { - // send to temp file - out = new FileOutputStream(mOutFile); - } - - new FlusherThread(in, out).start(); - } - catch (Exception e) { - throw new ExecException(e.getMessage()); - } - return out; - } - - private OutputStream redirectProcessError(Process subProcess) throws ExecException { - OutputStream out = null; - try { - InputStream in = subProcess.getErrorStream(); - // Redirect stderr for verbose mode - if (mVerboseMode) { - // send output to stderr - out = System.err; - } - else { - // send to temp file - out = new FileOutputStream(mErrFile); - } - new FlusherThread(in, out).start(); - } - catch (Exception e) { - throw new ExecException(e.getMessage()); - } - return out; - } - - public void setVerbose(boolean verbose) { - mVerboseMode = verbose; - } - - private void sleep(long millis) { - try { - Thread.sleep(millis); - } - catch (InterruptedException ie) { - //ignore exception - } - } - - /** - * Returns the contents of a file as a String. It never returns a null. If - * the file is empty, an empty string is returned. - * - * @param file the file to read - */ - protected String getFileBuffer(File file) { - final StringBuffer sb = new StringBuffer(); - BufferedReader reader = null; - try { - reader = new BufferedReader(new FileReader(file)); - String line = null; - while ((line = reader.readLine()) != null) { - sb.append(line); - sb.append(NEWLINE); - } - } - catch (Exception e) { - //squelch the exception - } - finally { - try { - reader.close(); - } - catch (Exception e) { - } - } - return (sb.toString()); - } - - protected String getLatestOutput(final File f) { - return (new RAFileReader(f).readLastBytesAsString()); - } - - public void retainBuffers() { - if (this.retainExecutionLogs) { - this.lastExecutionErrorString = this.getLatestOutput(this.mErrFile); - this.lastExecutionOutputString = this.getLatestOutput(this.mOutFile); - } - } - - private boolean debug() { - final String td = System.getProperty("java.io.tmpdir"); - final String n = "as_debug_process_executor"; // a debug hook - final File f = new File(td, n); - return (f.exists()); - } - - private String a2s(String[] a) { - final StringBuffer s = new StringBuffer(); - if (a != null) { - for (int i = 0; i < a.length; i++) { - s.append(a[i]); - s.append(" "); - } - } - return (s.toString()); - } - - /* - * bnevins, April 2012 - * I added this method to solve a FindBugs low-level issue about ignoring the - * return value. - */ - private static void delete(File f) { - if(f != null && !f.delete()) { - f.deleteOnExit(); - } - } - - private static class RAFileReader { - final File file; - final static int LAST_BYTES = 16384; - final static String RMODE = "r"; //read - - RAFileReader(final File file) { - this.file = file; - } - - String readLastBytesAsString() { - final int n = getNumberOfBytes(LAST_BYTES); - final StringBuffer sb = new StringBuffer(); - final long ln = file.length(); //if SecurityManager is not present, this is safe. - if (ln == 0) - return (sb.toString()); //nothing to read, file may not exist, is protected, is a directory etc. - assert (n <= ln) : ("Asked to read number of bytes more than size of file"); - final long s = ln - n; - return (readWithoutCheck(s)); - } - - private String readWithoutCheck(final long seekPos) { - final StringBuffer sb = new StringBuffer(); - RandomAccessFile rf = null; - int lines = 0; - try { - rf = new RandomAccessFile(file, RMODE); - rf.seek(seekPos); - String tmp = rf.readLine(); - while (tmp != null) { - lines++; - sb.append(tmp); - //sb.append(Character.LINE_SEPARATOR); - sb.append('\n'); // adding a newline character is going to add one extra byte - tmp = rf.readLine(); - } - } - catch (Exception e) { - //e.printStackTrace(); //ignore - } - finally { - try { - if (rf != null) - rf.close(); - } - catch (Exception e) { - }//ignore; - } - //System.out.println("ln-seekPos = " + (ln - seekPos) ); - //System.out.println("bytes = " + sb.toString().getBytes().length); - //System.out.println("lines = " + lines); - //assert ((ln - seekPos) == (sb.toString().getBytes().length + lines)) : "Wrong number of bytes read"; - return (sb.toString()); - } - - private int getNumberOfBytes(final int max) { - final long ln = file.length(); - return (max >= ln ? (int) ln : max); - } - } - - // used for ProcessManager to watchdog subProcess - public Process getSubProcess() { - return mSubProcess; - } - - public static void main(String args[]) { - testProcessError(); - } - - /* - * This method tests the condition of process throwing an error. On Unixlike - * systems this throws an error in error file. On non-unixlike Systems it - * will throw IOException for CreateProcess, which is desired - */ - private static void testProcessError() { - ProcessExecutor executor = new ProcessExecutor( - new String[]{"/usr/bin/ls", "-wrongPARAMS123"}); - try { - executor.execute(); - } - catch (ExecException ee) { - System.out.println(ee.getMessage()); - } - } -} -/** - * inner class to flush runtime.exec process so it doesn't hang - */ -class FlusherThread extends Thread { - InputStream mInStream = null; - OutputStream mOutStream = null; - public static final int kSize = 1024; - - FlusherThread(InputStream in, OutputStream out) { - mInStream = in; - mOutStream = out; - } - - @Override - public void run() { - // check for null stream - if (mInStream == null) - return; - - // transfer bytes from input to output stream - try { - int byteCnt = 0; - byte[] buffer = new byte[4096]; - while ((byteCnt = mInStream.read(buffer)) != -1) { - if (mOutStream != null && byteCnt > 0) { - mOutStream.write(buffer, 0, byteCnt); - mOutStream.flush(); - } - Thread.yield(); - } - } - catch (IOException e) { - // ignore - } - finally { - try { - mOutStream.close(); - } - catch (IOException ioe) { - // ignore - } - } - } -}