aboutsummaryrefslogtreecommitdiffstats
path: root/ddms/libs/ddmlib/src/com/android
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2010-07-20 17:25:36 -0700
committerXavier Ducrohet <xav@android.com>2010-07-26 10:55:08 -0700
commit9db3286c710abeb2c9478c2f95657d945a55d176 (patch)
treed3e5b901646d1c2ee6bd3990bb8da99c05eb78d3 /ddms/libs/ddmlib/src/com/android
parentf56173887a9f6430425c93203a8c260a73b1480a (diff)
downloadsdk-9db3286c710abeb2c9478c2f95657d945a55d176.zip
sdk-9db3286c710abeb2c9478c2f95657d945a55d176.tar.gz
sdk-9db3286c710abeb2c9478c2f95657d945a55d176.tar.bz2
Update the ddmlib api for push/pull/install
The API now throws SyncException instead of returning SyncResult. The IDevice API to install/uninstall now returns a single InstallException that encapsulate all the other ddmlib exception. Also, the recently added exceptions now don't extend IOException anymore. Change-Id: Ib334c4157a6add1882233dfaaa032aea1910eede
Diffstat (limited to 'ddms/libs/ddmlib/src/com/android')
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/AdbCommandRejectedException.java3
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/CanceledException.java40
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/Device.java107
-rwxr-xr-xddms/libs/ddmlib/src/com/android/ddmlib/IDevice.java41
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/InstallException.java42
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/ShellCommandUnresponsiveException.java3
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/SyncException.java93
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/SyncService.java418
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/TimeoutException.java3
9 files changed, 401 insertions, 349 deletions
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/AdbCommandRejectedException.java b/ddms/libs/ddmlib/src/com/android/ddmlib/AdbCommandRejectedException.java
index 673acb5..ae7d014 100644
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/AdbCommandRejectedException.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/AdbCommandRejectedException.java
@@ -16,12 +16,11 @@
package com.android.ddmlib;
-import java.io.IOException;
/**
* Exception thrown when adb refuses a command.
*/
-public class AdbCommandRejectedException extends IOException {
+public class AdbCommandRejectedException extends Exception {
private static final long serialVersionUID = 1L;
private final boolean mIsDeviceOffline;
private final boolean mErrorDuringDeviceSelection;
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/CanceledException.java b/ddms/libs/ddmlib/src/com/android/ddmlib/CanceledException.java
new file mode 100644
index 0000000..84eda03
--- /dev/null
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/CanceledException.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.android.ddmlib;
+
+/**
+ * Abstract exception for exception that can be thrown when a user input cancels the action.
+ * <p/>
+ * {@link #wasCanceled()} returns whether the action was canceled because of user input.
+ *
+ */
+public abstract class CanceledException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ CanceledException(String message) {
+ super(message);
+ }
+
+ CanceledException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Returns true if the action was canceled by user input.
+ */
+ public abstract boolean wasCanceled();
+}
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/Device.java b/ddms/libs/ddmlib/src/com/android/ddmlib/Device.java
index 7eff98e..bb61e5f 100644
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/Device.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/Device.java
@@ -16,7 +16,6 @@
package com.android.ddmlib;
-import com.android.ddmlib.SyncService.SyncResult;
import com.android.ddmlib.log.LogReceiver;
import java.io.File;
@@ -408,16 +407,25 @@ final class Device implements IDevice {
}
public String installPackage(String packageFilePath, boolean reinstall)
- throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
- IOException {
- String remoteFilePath = syncPackageToDevice(packageFilePath);
- String result = installRemotePackage(remoteFilePath, reinstall);
- removeRemotePackage(remoteFilePath);
- return result;
+ throws InstallException {
+ try {
+ String remoteFilePath = syncPackageToDevice(packageFilePath);
+ String result = installRemotePackage(remoteFilePath, reinstall);
+ removeRemotePackage(remoteFilePath);
+ return result;
+ } catch (IOException e) {
+ throw new InstallException(e);
+ } catch (AdbCommandRejectedException e) {
+ throw new InstallException(e);
+ } catch (TimeoutException e) {
+ throw new InstallException(e);
+ } catch (SyncException e) {
+ throw new InstallException(e);
+ }
}
public String syncPackageToDevice(String localFilePath)
- throws IOException, AdbCommandRejectedException, TimeoutException {
+ throws IOException, AdbCommandRejectedException, TimeoutException, SyncException {
try {
String packageFileName = getFileName(localFilePath);
String remoteFilePath = String.format("/data/local/tmp/%1$s", packageFileName); //$NON-NLS-1$
@@ -430,24 +438,23 @@ final class Device implements IDevice {
String message = String.format("Uploading file onto device '%1$s'",
getSerialNumber());
Log.d(LOG_TAG, message);
- SyncResult result = sync.pushFile(localFilePath, remoteFilePath,
- SyncService.getNullProgressMonitor());
-
- if (result.getCode() != SyncService.RESULT_OK) {
- throw new IOException(String.format("Unable to upload file: %1$s",
- result.getMessage()));
- }
+ sync.pushFile(localFilePath, remoteFilePath, SyncService.getNullProgressMonitor());
} else {
throw new IOException("Unable to open sync connection!");
}
return remoteFilePath;
} catch (TimeoutException e) {
- Log.e(LOG_TAG, "Unable to open sync connection! Timeout.");
+ Log.e(LOG_TAG, "Error during Sync: timeout.");
+ throw e;
+
+ } catch (SyncException e) {
+ Log.e(LOG_TAG, String.format("Error during Sync: %1$s", e.getMessage()));
throw e;
+
} catch (IOException e) {
- Log.e(LOG_TAG, String.format("Unable to open sync connection! reason: %1$s",
- e.getMessage()));
+ Log.e(LOG_TAG, String.format("Error during Sync: %1$s", e.getMessage()));
throw e;
+
}
}
@@ -461,40 +468,52 @@ final class Device implements IDevice {
}
public String installRemotePackage(String remoteFilePath, boolean reinstall)
- throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
- IOException {
- InstallReceiver receiver = new InstallReceiver();
- String cmd = String.format(reinstall ? "pm install -r \"%1$s\"" : "pm install \"%1$s\"",
- remoteFilePath);
- executeShellCommand(cmd, receiver, INSTALL_TIMEOUT);
- return receiver.getErrorMessage();
+ throws InstallException {
+ try {
+ InstallReceiver receiver = new InstallReceiver();
+ String cmd = String.format(reinstall ? "pm install -r \"%1$s\"" : "pm install \"%1$s\"",
+ remoteFilePath);
+ executeShellCommand(cmd, receiver, INSTALL_TIMEOUT);
+ return receiver.getErrorMessage();
+ } catch (TimeoutException e) {
+ throw new InstallException(e);
+ } catch (AdbCommandRejectedException e) {
+ throw new InstallException(e);
+ } catch (ShellCommandUnresponsiveException e) {
+ throw new InstallException(e);
+ } catch (IOException e) {
+ throw new InstallException(e);
+ }
}
- /**
- * {@inheritDoc}
- */
- public void removeRemotePackage(String remoteFilePath)
- throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
- IOException {
- // now we delete the app we sync'ed
+ public void removeRemotePackage(String remoteFilePath) throws InstallException {
try {
executeShellCommand("rm " + remoteFilePath, new NullOutputReceiver(), INSTALL_TIMEOUT);
} catch (IOException e) {
- Log.e(LOG_TAG, String.format("Failed to delete temporary package: %1$s",
- e.getMessage()));
- throw e;
+ throw new InstallException(e);
+ } catch (TimeoutException e) {
+ throw new InstallException(e);
+ } catch (AdbCommandRejectedException e) {
+ throw new InstallException(e);
+ } catch (ShellCommandUnresponsiveException e) {
+ throw new InstallException(e);
}
}
- /**
- * {@inheritDoc}
- */
- public String uninstallPackage(String packageName)
- throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
- IOException {
- InstallReceiver receiver = new InstallReceiver();
- executeShellCommand("pm uninstall " + packageName, receiver, INSTALL_TIMEOUT);
- return receiver.getErrorMessage();
+ public String uninstallPackage(String packageName) throws InstallException {
+ try {
+ InstallReceiver receiver = new InstallReceiver();
+ executeShellCommand("pm uninstall " + packageName, receiver, INSTALL_TIMEOUT);
+ return receiver.getErrorMessage();
+ } catch (TimeoutException e) {
+ throw new InstallException(e);
+ } catch (AdbCommandRejectedException e) {
+ throw new InstallException(e);
+ } catch (ShellCommandUnresponsiveException e) {
+ throw new InstallException(e);
+ } catch (IOException e) {
+ throw new InstallException(e);
+ }
}
/*
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/IDevice.java b/ddms/libs/ddmlib/src/com/android/ddmlib/IDevice.java
index 01814ac..c2e2c16 100755
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/IDevice.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/IDevice.java
@@ -322,15 +322,10 @@ public interface IDevice {
* @param packageFilePath the absolute file system path to file on local host to install
* @param reinstall set to <code>true</code> if re-install of app should be performed
* @return a {@link String} with an error code, or <code>null</code> if success.
- * @throws TimeoutException in case of timeout on the connection.
- * @throws AdbCommandRejectedException if adb rejects the command
- * @throws ShellCommandUnresponsiveException if the device didn't respond for long time when
- * performing the action.
- * @throws IOException in case of I/O error on the connection.
+ * @throws InstallException if the installation fails.
*/
public String installPackage(String packageFilePath, boolean reinstall)
- throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
- IOException;
+ throws InstallException;
/**
* Pushes a file to device
@@ -340,53 +335,37 @@ public interface IDevice {
* @throws TimeoutException in case of timeout on the connection.
* @throws AdbCommandRejectedException if adb rejects the command
* @throws IOException in case of I/O error on the connection.
+ * @throws SyncException if an error happens during the push of the package on the device.
*/
public String syncPackageToDevice(String localFilePath)
- throws TimeoutException, AdbCommandRejectedException, IOException;
+ throws TimeoutException, AdbCommandRejectedException, IOException, SyncException;
/**
* Installs the application package that was pushed to a temporary location on the device.
*
* @param remoteFilePath absolute file path to package file on device
* @param reinstall set to <code>true</code> if re-install of app should be performed
- * @throws TimeoutException in case of timeout on the connection.
- * @throws AdbCommandRejectedException if adb rejects the command
- * @throws ShellCommandUnresponsiveException if the device didn't respond for long time when
- * performing the action.
- * @throws IOException if installation failed
+ * @throws InstallException if the installation fails.
*/
public String installRemotePackage(String remoteFilePath, boolean reinstall)
- throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
- IOException;
+ throws InstallException;
/**
* Removes a file from device.
*
* @param remoteFilePath path on device of file to remove
- * @throws TimeoutException in case of timeout on the connection.
- * @throws AdbCommandRejectedException if adb rejects the command
- * @throws ShellCommandUnresponsiveException if the device didn't respond for long time when
- * performing the action.
- * @throws IOException if file removal failed
+ * @throws InstallException if the installation fails.
*/
- public void removeRemotePackage(String remoteFilePath)
- throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
- IOException;
+ public void removeRemotePackage(String remoteFilePath) throws InstallException;
/**
* Uninstalls an package from the device.
*
* @param packageName the Android application package name to uninstall
* @return a {@link String} with an error code, or <code>null</code> if success.
- * @throws TimeoutException in case of timeout on the connection.
- * @throws AdbCommandRejectedException if adb rejects the command
- * @throws ShellCommandUnresponsiveException if the device didn't respond for long time when
- * performing the action.
- * @throws IOException
+ * @throws InstallException if the uninstallation fails.
*/
- public String uninstallPackage(String packageName)
- throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
- IOException;
+ public String uninstallPackage(String packageName) throws InstallException;
/**
* Reboot the device.
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/InstallException.java b/ddms/libs/ddmlib/src/com/android/ddmlib/InstallException.java
new file mode 100644
index 0000000..7aa718f
--- /dev/null
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/InstallException.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.android.ddmlib;
+
+/**
+ * Thrown if installation or uninstallation of application fails.
+ */
+public class InstallException extends CanceledException {
+ private static final long serialVersionUID = 1L;
+
+ public InstallException(Throwable cause) {
+ super(cause.getMessage(), cause);
+ }
+
+ public InstallException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Returns true if the installation was canceled by user input. This can typically only
+ * happen in the sync phase.
+ */
+ @Override
+ public boolean wasCanceled() {
+ Throwable cause = getCause();
+ return cause instanceof SyncException && ((SyncException)cause).wasCanceled();
+ }
+}
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/ShellCommandUnresponsiveException.java b/ddms/libs/ddmlib/src/com/android/ddmlib/ShellCommandUnresponsiveException.java
index 2dc5d3a..09823c4 100644
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/ShellCommandUnresponsiveException.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/ShellCommandUnresponsiveException.java
@@ -16,13 +16,12 @@
package com.android.ddmlib;
-import java.io.IOException;
/**
* Exception thrown when a shell command executed on a device takes too long to send its output.
* <p/>The command may not actually be unresponsive, it just has spent too much time not outputting
* any thing to the console.
*/
-public class ShellCommandUnresponsiveException extends IOException {
+public class ShellCommandUnresponsiveException extends Exception {
private static final long serialVersionUID = 1L;
}
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/SyncException.java b/ddms/libs/ddmlib/src/com/android/ddmlib/SyncException.java
new file mode 100644
index 0000000..1e9b692
--- /dev/null
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/SyncException.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.android.ddmlib;
+
+import java.io.IOException;
+
+/**
+ * Exception thrown when a transfer using {@link SyncService} doesn't complete.
+ * <p/>This is different from an {@link IOException} because it's not the underlying connection
+ * that triggered the error, but the adb transfer protocol that didn't work somehow, or that the
+ * targets (local and/or remote) were wrong.
+ */
+public class SyncException extends CanceledException {
+ private static final long serialVersionUID = 1L;
+
+ public enum SyncError {
+ /** canceled transfer */
+ CANCELED("Operation was canceled by the user."),
+ /** Transfer error */
+ TRANSFER_PROTOCOL_ERROR("Adb Transfer Protocol Error."),
+ /** unknown remote object during a pull */
+ NO_REMOTE_OBJECT("Remote object doesn't exist!"),
+ /** Result code when attempting to pull multiple files into a file */
+ TARGET_IS_FILE("Target object is a file."),
+ /** Result code when attempting to pull multiple into a directory that does not exist. */
+ NO_DIR_TARGET("Target directory doesn't exist."),
+ /** wrong encoding on the remote path. */
+ REMOTE_PATH_ENCODING("Remote Path encoding is not supported."),
+ /** remote path that is too long. */
+ REMOTE_PATH_LENGTH("Remote path is too long."),
+ /** error while reading local file. */
+ FILE_READ_ERROR("Reading local file failed!"),
+ /** attempting to push a directory. */
+ LOCAL_IS_DIRECTORY("Local path is a directory."),
+ /** when the target path of a multi file push is a file. */
+ REMOTE_IS_FILE("Remote path is a file."),
+ /** receiving too much data from the remove device at once */
+ BUFFER_OVERRUN("Receiving too much data.");
+
+ private final String mMessage;
+
+ private SyncError(String message) {
+ mMessage = message;
+ }
+
+ public String getMessage() {
+ return mMessage;
+ }
+ }
+
+ private final SyncError mError;
+
+ public SyncException(SyncError error) {
+ super(error.getMessage());
+ mError = error;
+ }
+
+ public SyncException(SyncError error, String message) {
+ super(message);
+ mError = error;
+ }
+
+ public SyncException(SyncError error, Throwable cause) {
+ super(error.getMessage(), cause);
+ mError = error;
+ }
+
+ public SyncError getErrorCode() {
+ return mError;
+ }
+
+ /**
+ * Returns true if the sync was canceled by user input.
+ */
+ @Override
+ public boolean wasCanceled() {
+ return mError == SyncError.CANCELED;
+ }
+}
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/SyncService.java b/ddms/libs/ddmlib/src/com/android/ddmlib/SyncService.java
index d2b8af3..0303a03 100644
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/SyncService.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/SyncService.java
@@ -18,6 +18,7 @@ package com.android.ddmlib;
import com.android.ddmlib.AdbHelper.AdbResponse;
import com.android.ddmlib.FileListingService.FileEntry;
+import com.android.ddmlib.SyncException.SyncError;
import com.android.ddmlib.utils.ArrayHelper;
import java.io.File;
@@ -78,69 +79,6 @@ public final class SyncService {
private final static int SYNC_DATA_MAX = 64*1024;
private final static int REMOTE_PATH_MAX_LENGTH = 1024;
- /** Result code for transfer success. */
- public static final int RESULT_OK = 0;
- /** Result code for canceled transfer */
- public static final int RESULT_CANCELED = 1;
- /** Result code for unknown error */
- public static final int RESULT_UNKNOWN_ERROR = 2;
- /** Result code for network connection error */
- public static final int RESULT_CONNECTION_ERROR = 3;
- /** Result code for unknown remote object during a pull */
- public static final int RESULT_NO_REMOTE_OBJECT = 4;
- /** Result code when attempting to pull multiple files into a file */
- public static final int RESULT_TARGET_IS_FILE = 5;
- /** Result code when attempting to pull multiple into a directory that does not exist. */
- public static final int RESULT_NO_DIR_TARGET = 6;
- /** Result code for wrong encoding on the remote path. */
- public static final int RESULT_REMOTE_PATH_ENCODING = 7;
- /** Result code for remote path that is too long. */
- public static final int RESULT_REMOTE_PATH_LENGTH = 8;
- /** Result code for error while writing local file. */
- public static final int RESULT_FILE_WRITE_ERROR = 9;
- /** Result code for error while reading local file. */
- public static final int RESULT_FILE_READ_ERROR = 10;
- /** Result code for attempting to push a file that does not exist. */
- public static final int RESULT_NO_LOCAL_FILE = 11;
- /** Result code for attempting to push a directory. */
- public static final int RESULT_LOCAL_IS_DIRECTORY = 12;
- /** Result code for when the target path of a multi file push is a file. */
- public static final int RESULT_REMOTE_IS_FILE = 13;
- /** Result code for receiving too much data from the remove device at once */
- public static final int RESULT_BUFFER_OVERRUN = 14;
- /** Result code for network connection timeout */
- public static final int RESULT_CONNECTION_TIMEOUT = 15;
-
- /**
- * A file transfer result.
- * <p/>
- * This contains a code, and an optional string
- */
- public static class SyncResult {
- private int mCode;
- private String mMessage;
- SyncResult(int code, String message) {
- mCode = code;
- mMessage = message;
- }
-
- SyncResult(int code, Exception e) {
- this(code, e.getMessage());
- }
-
- SyncResult(int code) {
- this(code, errorCodeToString(code));
- }
-
- public int getCode() {
- return mCode;
- }
-
- public String getMessage() {
- return mMessage;
- }
- }
-
/**
* Classes which implement this interface provide methods that deal
* with displaying transfer progress.
@@ -287,68 +225,30 @@ public final class SyncService {
}
/**
- * Converts an error code into a non-localized string
- * @param code the error code;
- */
- private static String errorCodeToString(int code) {
- switch (code) {
- case RESULT_OK:
- return "Success.";
- case RESULT_CANCELED:
- return "Tranfert canceled by the user.";
- case RESULT_UNKNOWN_ERROR:
- return "Unknown Error.";
- case RESULT_CONNECTION_ERROR:
- return "Adb Connection Error.";
- case RESULT_NO_REMOTE_OBJECT:
- return "Remote object doesn't exist!";
- case RESULT_TARGET_IS_FILE:
- return "Target object is a file.";
- case RESULT_NO_DIR_TARGET:
- return "Target directory doesn't exist.";
- case RESULT_REMOTE_PATH_ENCODING:
- return "Remote Path encoding is not supported.";
- case RESULT_REMOTE_PATH_LENGTH:
- return "Remove path is too long.";
- case RESULT_FILE_WRITE_ERROR:
- return "Writing local file failed!";
- case RESULT_FILE_READ_ERROR:
- return "Reading local file failed!";
- case RESULT_NO_LOCAL_FILE:
- return "Local file doesn't exist.";
- case RESULT_LOCAL_IS_DIRECTORY:
- return "Local path is a directory.";
- case RESULT_REMOTE_IS_FILE:
- return "Remote path is a file.";
- case RESULT_BUFFER_OVERRUN:
- return "Receiving too much data.";
- case RESULT_CONNECTION_TIMEOUT:
- return "timeout";
- }
-
- throw new RuntimeException();
- }
-
- /**
* Pulls file(s) or folder(s).
* @param entries the remote item(s) to pull
* @param localPath The local destination. If the entries count is > 1 or
* if the unique entry is a folder, this should be a folder.
* @param monitor The progress monitor. Cannot be null.
- * @return a {@link SyncResult} object with a code and an optional message.
+ * @throws SyncException
+ * @throws FileNotFoundException if the file exists but is a directory, does not exist but
+ * cannot be created, or cannot be opened for any other reason.
+ * @throws IOException
+ * @throws TimeoutException
*
* @see FileListingService.FileEntry
* @see #getNullProgressMonitor()
*/
- public SyncResult pull(FileEntry[] entries, String localPath, ISyncProgressMonitor monitor) {
+ public void pull(FileEntry[] entries, String localPath, ISyncProgressMonitor monitor)
+ throws SyncException, FileNotFoundException, IOException, TimeoutException {
// first we check the destination is a directory and exists
File f = new File(localPath);
if (f.exists() == false) {
- return new SyncResult(RESULT_NO_DIR_TARGET);
+ throw new SyncException(SyncError.NO_DIR_TARGET);
}
if (f.isDirectory() == false) {
- return new SyncResult(RESULT_TARGET_IS_FILE);
+ throw new SyncException(SyncError.TARGET_IS_FILE);
}
// get a FileListingService object
@@ -360,11 +260,9 @@ public final class SyncService {
// start the monitor
monitor.start(total);
- SyncResult result = doPull(entries, localPath, fls, monitor);
+ doPull(entries, localPath, fls, monitor);
monitor.stop();
-
- return result;
}
/**
@@ -372,20 +270,23 @@ public final class SyncService {
* @param remote the remote file
* @param localFilename The local destination.
* @param monitor The progress monitor. Cannot be null.
- * @return a {@link SyncResult} object with a code and an optional message.
+ *
+ * @throws SyncException
+ * @throws IOException
+ * @throws FileNotFoundException
+ * @throws TimeoutException
*
* @see FileListingService.FileEntry
* @see #getNullProgressMonitor()
*/
- public SyncResult pullFile(FileEntry remote, String localFilename,
- ISyncProgressMonitor monitor) {
+ public void pullFile(FileEntry remote, String localFilename, ISyncProgressMonitor monitor)
+ throws FileNotFoundException, IOException, SyncException, TimeoutException {
int total = remote.getSizeValue();
monitor.start(total);
- SyncResult result = doPullFile(remote.getFullPath(), localFilename, monitor);
+ doPullFile(remote.getFullPath(), localFilename, monitor);
monitor.stop();
- return result;
}
/**
@@ -396,19 +297,28 @@ public final class SyncService {
* @param remoteFilepath the full path to the remote file
* @param localFilename The local destination.
* @param monitor The progress monitor. Cannot be null.
- * @return a {@link SyncResult} object with a code and an optional message.
+ *
+ * @throws IOException in case of an IO exception.
+ * @throws TimeoutException in case of a timeout reading responses from the device.
+ * @throws SyncException in case of a sync exception.
*
* @see #getNullProgressMonitor()
*/
- public SyncResult pullFile(String remoteFilepath, String localFilename,
- ISyncProgressMonitor monitor) {
+ public void pullFile(String remoteFilepath, String localFilename,
+ ISyncProgressMonitor monitor) throws TimeoutException, IOException, SyncException {
+ Integer mode = readMode(remoteFilepath);
+ if (mode == null) {
+ // attempts to download anyway
+ } else if (mode == 0) {
+ throw new SyncException(SyncError.NO_REMOTE_OBJECT);
+ }
+
monitor.start(0);
//TODO: use the {@link FileListingService} to get the file size.
- SyncResult result = doPullFile(remoteFilepath, localFilename, monitor);
+ doPullFile(remoteFilepath, localFilename, monitor);
monitor.stop();
- return result;
}
/**
@@ -416,11 +326,16 @@ public final class SyncService {
* @param local An array of loca files to push
* @param remote the remote {@link FileEntry} representing a directory.
* @param monitor The progress monitor. Cannot be null.
- * @return a {@link SyncResult} object with a code and an optional message.
+ * @throws SyncException
+ * @throws FileNotFoundException if the file exists but is a directory, does not exist but
+ * cannot be created, or cannot be opened for any other reason.
+ * @throws IOException
+ * @throws TimeoutException
*/
- public SyncResult push(String[] local, FileEntry remote, ISyncProgressMonitor monitor) {
+ public void push(String[] local, FileEntry remote, ISyncProgressMonitor monitor)
+ throws SyncException, FileNotFoundException, IOException, TimeoutException {
if (remote.isDirectory() == false) {
- return new SyncResult(RESULT_REMOTE_IS_FILE);
+ throw new SyncException(SyncError.REMOTE_IS_FILE);
}
// make a list of File from the list of String
@@ -435,11 +350,9 @@ public final class SyncService {
monitor.start(total);
- SyncResult result = doPush(fileArray, remote.getFullPath(), monitor);
+ doPush(fileArray, remote.getFullPath(), monitor);
monitor.stop();
-
- return result;
}
/**
@@ -447,25 +360,30 @@ public final class SyncService {
* @param local the local filepath.
* @param remote The remote filepath.
* @param monitor The progress monitor. Cannot be null.
- * @return a {@link SyncResult} object with a code and an optional message.
+ *
+ * @throws SyncException
+ * @throws FileNotFoundException if the file exists but is a directory, does not exist but
+ * cannot be created, or cannot be opened for any other reason.
+ * @throws IOException
+ * @throws TimeoutException
+ *
*/
- public SyncResult pushFile(String local, String remote, ISyncProgressMonitor monitor) {
+ public void pushFile(String local, String remote, ISyncProgressMonitor monitor)
+ throws SyncException, FileNotFoundException, IOException, TimeoutException {
File f = new File(local);
if (f.exists() == false) {
- return new SyncResult(RESULT_NO_LOCAL_FILE);
+ throw new FileNotFoundException();
}
if (f.isDirectory()) {
- return new SyncResult(RESULT_LOCAL_IS_DIRECTORY);
+ throw new SyncException(SyncError.LOCAL_IS_DIRECTORY);
}
monitor.start((int)f.length());
- SyncResult result = doPushFile(local, remote, monitor);
+ doPushFile(local, remote, monitor);
monitor.stop();
-
- return result;
}
/**
@@ -520,16 +438,22 @@ public final class SyncService {
* @param localPath the localpath to a directory
* @param fileListingService a FileListingService object to browse through remote directories.
* @param monitor the progress monitor. Must be started already.
- * @return a {@link SyncResult} object with a code and an optional message.
+ *
+ * @throws FileNotFoundException if the file exists but is a directory, does not exist but
+ * cannot be created, or cannot be opened for any other reason.
+ * @throws IOException
+ * @throws SyncException
+ * @throws TimeoutException
*/
- private SyncResult doPull(FileEntry[] entries, String localPath,
+ private void doPull(FileEntry[] entries, String localPath,
FileListingService fileListingService,
- ISyncProgressMonitor monitor) {
+ ISyncProgressMonitor monitor) throws SyncException, FileNotFoundException, IOException,
+ TimeoutException {
for (FileEntry e : entries) {
// check if we're cancelled
if (monitor.isCanceled() == true) {
- return new SyncResult(RESULT_CANCELED);
+ throw new SyncException(SyncError.CANCELED);
}
// get type (we only pull directory and files for now)
@@ -545,22 +469,14 @@ public final class SyncService {
// then recursively call the content. Since we did a ls command
// to get the number of files, we can use the cache
FileEntry[] children = fileListingService.getChildren(e, true, null);
- SyncResult result = doPull(children, dest, fileListingService, monitor);
- if (result.mCode != RESULT_OK) {
- return result;
- }
+ doPull(children, dest, fileListingService, monitor);
monitor.advance(1);
} else if (type == FileListingService.TYPE_FILE) {
monitor.startSubTask(e.getFullPath());
String dest = localPath + File.separator + e.getName();
- SyncResult result = doPullFile(e.getFullPath(), dest, monitor);
- if (result.mCode != RESULT_OK) {
- return result;
- }
+ doPullFile(e.getFullPath(), dest, monitor);
}
}
-
- return new SyncResult(RESULT_OK);
}
/**
@@ -568,10 +484,15 @@ public final class SyncService {
* @param remotePath the remote file (length max is 1024)
* @param localPath the local destination
* @param monitor the monitor. The monitor must be started already.
- * @return a {@link SyncResult} object with a code and an optional message.
+ * @throws FileNotFoundException if the file exists but is a directory, does not exist but
+ * cannot be created, or cannot be opened for any other reason.
+ * @throws IOException
+ * @throws SyncException
+ * @throws TimeoutException
*/
- private SyncResult doPullFile(String remotePath, String localPath,
- ISyncProgressMonitor monitor) {
+ private void doPullFile(String remotePath, String localPath,
+ ISyncProgressMonitor monitor) throws FileNotFoundException, IOException, SyncException,
+ TimeoutException {
byte[] msg = null;
byte[] pullResult = new byte[8];
@@ -581,7 +502,7 @@ public final class SyncService {
byte[] remotePathContent = remotePath.getBytes(AdbHelper.DEFAULT_ENCODING);
if (remotePathContent.length > REMOTE_PATH_MAX_LENGTH) {
- return new SyncResult(RESULT_REMOTE_PATH_LENGTH);
+ throw new SyncException(SyncError.REMOTE_PATH_LENGTH);
}
// create the full request message
@@ -597,14 +518,11 @@ public final class SyncService {
// check we have the proper data back
if (checkResult(pullResult, ID_DATA) == false &&
checkResult(pullResult, ID_DONE) == false) {
- return new SyncResult(RESULT_CONNECTION_ERROR);
+ throw new SyncException(SyncError.TRANSFER_PROTOCOL_ERROR,
+ readErrorMessage(pullResult, timeOut));
}
} catch (UnsupportedEncodingException e) {
- return new SyncResult(RESULT_REMOTE_PATH_ENCODING, e);
- } catch (TimeoutException e) {
- return new SyncResult(RESULT_CONNECTION_TIMEOUT, e);
- } catch (IOException e) {
- return new SyncResult(RESULT_CONNECTION_ERROR, e);
+ throw new SyncException(SyncError.REMOTE_PATH_ENCODING, e);
}
// access the destination file
@@ -613,11 +531,7 @@ public final class SyncService {
// create the stream to write in the file. We use a new try/catch block to differentiate
// between file and network io exceptions.
FileOutputStream fos = null;
- try {
- fos = new FileOutputStream(f);
- } catch (FileNotFoundException e) {
- return new SyncResult(RESULT_FILE_WRITE_ERROR, e);
- }
+ fos = new FileOutputStream(f);
// the buffer to read the data
byte[] data = new byte[SYNC_DATA_MAX];
@@ -626,7 +540,7 @@ public final class SyncService {
while (true) {
// check if we're cancelled
if (monitor.isCanceled() == true) {
- return new SyncResult(RESULT_CANCELED);
+ throw new SyncException(SyncError.CANCELED);
}
// if we're done, we stop the loop
@@ -635,43 +549,29 @@ public final class SyncService {
}
if (checkResult(pullResult, ID_DATA) == false) {
// hmm there's an error
- return new SyncResult(RESULT_CONNECTION_ERROR);
+ throw new SyncException(SyncError.TRANSFER_PROTOCOL_ERROR,
+ readErrorMessage(pullResult, timeOut));
}
int length = ArrayHelper.swap32bitFromArray(pullResult, 4);
if (length > SYNC_DATA_MAX) {
// buffer overrun!
// error and exit
- return new SyncResult(RESULT_BUFFER_OVERRUN);
+ throw new SyncException(SyncError.BUFFER_OVERRUN);
}
- try {
- // now read the length we received
- AdbHelper.read(mChannel, data, length, timeOut);
+ // now read the length we received
+ AdbHelper.read(mChannel, data, length, timeOut);
- // get the header for the next packet.
- AdbHelper.read(mChannel, pullResult, -1, timeOut);
- } catch (TimeoutException e) {
- return new SyncResult(RESULT_CONNECTION_TIMEOUT, e);
- } catch (IOException e) {
- return new SyncResult(RESULT_CONNECTION_ERROR, e);
- }
+ // get the header for the next packet.
+ AdbHelper.read(mChannel, pullResult, -1, timeOut);
// write the content in the file
- try {
- fos.write(data, 0, length);
- } catch (IOException e) {
- return new SyncResult(RESULT_FILE_WRITE_ERROR, e);
- }
+ fos.write(data, 0, length);
monitor.advance(length);
}
- try {
- fos.flush();
- } catch (IOException e) {
- return new SyncResult(RESULT_FILE_WRITE_ERROR, e);
- }
- return new SyncResult(RESULT_OK);
+ fos.flush();
}
@@ -680,39 +580,36 @@ public final class SyncService {
* @param fileArray
* @param remotePath
* @param monitor
- * @return a {@link SyncResult} object with a code and an optional message.
+ *
+ * @throws SyncException
+ * @throws FileNotFoundException if the file exists but is a directory, does not exist but
+ * cannot be created, or cannot be opened for any other reason.
+ * @throws IOException
+ * @throws TimeoutException
*/
- private SyncResult doPush(File[] fileArray, String remotePath, ISyncProgressMonitor monitor) {
+ private void doPush(File[] fileArray, String remotePath, ISyncProgressMonitor monitor)
+ throws SyncException, FileNotFoundException, IOException, TimeoutException {
for (File f : fileArray) {
// check if we're canceled
if (monitor.isCanceled() == true) {
- return new SyncResult(RESULT_CANCELED);
+ throw new SyncException(SyncError.CANCELED);
}
if (f.exists()) {
if (f.isDirectory()) {
// append the name of the directory to the remote path
String dest = remotePath + "/" + f.getName(); // $NON-NLS-1S
monitor.startSubTask(dest);
- SyncResult result = doPush(f.listFiles(), dest, monitor);
-
- if (result.mCode != RESULT_OK) {
- return result;
- }
+ doPush(f.listFiles(), dest, monitor);
monitor.advance(1);
} else if (f.isFile()) {
// append the name of the file to the remote path
String remoteFile = remotePath + "/" + f.getName(); // $NON-NLS-1S
monitor.startSubTask(remoteFile);
- SyncResult result = doPushFile(f.getAbsolutePath(), remoteFile, monitor);
- if (result.mCode != RESULT_OK) {
- return result;
- }
+ doPushFile(f.getAbsolutePath(), remoteFile, monitor);
}
}
}
-
- return new SyncResult(RESULT_OK);
}
/**
@@ -720,10 +617,16 @@ public final class SyncService {
* @param localPath the local file to push
* @param remotePath the remote file (length max is 1024)
* @param monitor the monitor. The monitor must be started already.
- * @return a {@link SyncResult} object with a code and an optional message.
+ *
+ * @throws SyncException
+ * @throws FileNotFoundException if the file exists but is a directory, does not exist but
+ * cannot be created, or cannot be opened for any other reason.
+ * @throws IOException
+ * @throws TimeoutException
*/
- private SyncResult doPushFile(String localPath, String remotePath,
- ISyncProgressMonitor monitor) {
+ private void doPushFile(String localPath, String remotePath,
+ ISyncProgressMonitor monitor) throws SyncException, FileNotFoundException, IOException,
+ TimeoutException {
FileInputStream fis = null;
byte[] msg;
@@ -733,36 +636,23 @@ public final class SyncService {
byte[] remotePathContent = remotePath.getBytes(AdbHelper.DEFAULT_ENCODING);
if (remotePathContent.length > REMOTE_PATH_MAX_LENGTH) {
- return new SyncResult(RESULT_REMOTE_PATH_LENGTH);
+ throw new SyncException(SyncError.REMOTE_PATH_LENGTH);
}
File f = new File(localPath);
- // this shouldn't happen but still...
- if (f.exists() == false) {
- return new SyncResult(RESULT_NO_LOCAL_FILE);
- }
-
// create the stream to read the file
fis = new FileInputStream(f);
// create the header for the action
msg = createSendFileReq(ID_SEND, remotePathContent, 0644);
} catch (UnsupportedEncodingException e) {
- return new SyncResult(RESULT_REMOTE_PATH_ENCODING, e);
- } catch (FileNotFoundException e) {
- return new SyncResult(RESULT_FILE_READ_ERROR, e);
+ throw new SyncException(SyncError.REMOTE_PATH_ENCODING, e);
}
// and send it. We use a custom try/catch block to make the difference between
// file and network IO exceptions.
- try {
- AdbHelper.write(mChannel, msg, -1, timeOut);
- } catch (TimeoutException e) {
- return new SyncResult(RESULT_CONNECTION_TIMEOUT, e);
- } catch (IOException e) {
- return new SyncResult(RESULT_CONNECTION_ERROR, e);
- }
+ AdbHelper.write(mChannel, msg, -1, timeOut);
// create the buffer used to read.
// we read max SYNC_DATA_MAX, but we need 2 4 bytes at the beginning.
@@ -775,16 +665,11 @@ public final class SyncService {
while (true) {
// check if we're canceled
if (monitor.isCanceled() == true) {
- return new SyncResult(RESULT_CANCELED);
+ throw new SyncException(SyncError.CANCELED);
}
// read up to SYNC_DATA_MAX
- int readCount = 0;
- try {
- readCount = fis.read(mBuffer, 8, SYNC_DATA_MAX);
- } catch (IOException e) {
- return new SyncResult(RESULT_FILE_READ_ERROR, e);
- }
+ int readCount = fis.read(mBuffer, 8, SYNC_DATA_MAX);
if (readCount == -1) {
// we reached the end of the file
@@ -796,65 +681,62 @@ public final class SyncService {
ArrayHelper.swap32bitsToArray(readCount, mBuffer, 4);
// now write it
- try {
- AdbHelper.write(mChannel, mBuffer, readCount+8, timeOut);
- } catch (TimeoutException e) {
- return new SyncResult(RESULT_CONNECTION_TIMEOUT, e);
- } catch (IOException e) {
- return new SyncResult(RESULT_CONNECTION_ERROR, e);
- }
+ AdbHelper.write(mChannel, mBuffer, readCount+8, timeOut);
// and advance the monitor
monitor.advance(readCount);
}
// close the local file
- try {
- fis.close();
- } catch (IOException e) {
- return new SyncResult(RESULT_FILE_READ_ERROR, e);
- }
+ fis.close();
- try {
- // create the DONE message
- long time = System.currentTimeMillis() / 1000;
- msg = createReq(ID_DONE, (int)time);
+ // create the DONE message
+ long time = System.currentTimeMillis() / 1000;
+ msg = createReq(ID_DONE, (int)time);
- // and send it.
- AdbHelper.write(mChannel, msg, -1, timeOut);
+ // and send it.
+ AdbHelper.write(mChannel, msg, -1, timeOut);
- // read the result, in a byte array containing 2 ints
- // (id, size)
- byte[] result = new byte[8];
- AdbHelper.read(mChannel, result, -1 /* full length */, timeOut);
+ // read the result, in a byte array containing 2 ints
+ // (id, size)
+ byte[] result = new byte[8];
+ AdbHelper.read(mChannel, result, -1 /* full length */, timeOut);
+
+ if (checkResult(result, ID_OKAY) == false) {
+ throw new SyncException(SyncError.TRANSFER_PROTOCOL_ERROR,
+ readErrorMessage(result, timeOut));
+ }
+ }
- if (checkResult(result, ID_OKAY) == false) {
- if (checkResult(result, ID_FAIL)) {
- // read some error message...
- int len = ArrayHelper.swap32bitFromArray(result, 4);
+ /**
+ * Reads an error message from the opened {@link #mChannel}.
+ * @param result the current adb result. Must contain both FAIL and the length of the message.
+ * @param timeOut
+ * @return
+ * @throws TimeoutException
+ * @throws IOException
+ */
+ private String readErrorMessage(byte[] result, final int timeOut) throws TimeoutException,
+ IOException {
+ if (checkResult(result, ID_FAIL)) {
+ int len = ArrayHelper.swap32bitFromArray(result, 4);
- AdbHelper.read(mChannel, mBuffer, len, timeOut);
+ if (len > 0) {
+ AdbHelper.read(mChannel, mBuffer, len, timeOut);
- // output the result?
- String message = new String(mBuffer, 0, len);
- Log.e("ddms", "transfer error: " + message);
- return new SyncResult(RESULT_UNKNOWN_ERROR, message);
- }
+ String message = new String(mBuffer, 0, len);
+ Log.e("ddms", "transfer error: " + message);
- return new SyncResult(RESULT_UNKNOWN_ERROR);
+ return message;
}
- } catch (TimeoutException e) {
- return new SyncResult(RESULT_CONNECTION_TIMEOUT, e);
- } catch (IOException e) {
- return new SyncResult(RESULT_CONNECTION_ERROR, e);
}
- return new SyncResult(RESULT_OK);
+ return null;
}
/**
* Returns the mode of the remote file.
* @param path the remote file
- * @return and Integer containing the mode if all went well or null
+ * @return an Integer containing the mode if all went well or null
* otherwise
* @throws IOException
* @throws TimeoutException
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/TimeoutException.java b/ddms/libs/ddmlib/src/com/android/ddmlib/TimeoutException.java
index 25be2f9..78f5db7 100644
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/TimeoutException.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/TimeoutException.java
@@ -16,12 +16,11 @@
package com.android.ddmlib;
-import java.io.IOException;
/**
* Exception thrown when a connection to Adb failed with a timeout.
*
*/
-public class TimeoutException extends IOException {
+public class TimeoutException extends Exception {
private static final long serialVersionUID = 1L;
}