From 56a6d5e290d78888d3640a555385d123abb0d503 Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Feb 2012 12:57:23 -0800 Subject: SDK Manager: use find_lock.exe when install dir is locked. For the SDK Manager on Windows, this uses find_lock.exe to try to find the processes that are locking an existing SDK folder that cannot be moved out of the way. The result is displayed in a simple yes/no dialog or on the command-line if invoked without UI. Change-Id: I39fa7529e207e870376a30c8311440f9c240d4b3 --- .../src/com/android/sdklib/SdkConstants.java | 64 +++++++----- .../internal/repository/ArchiveInstaller.java | 109 ++++++++++++++++++--- .../internal/repository/SdkUpdaterNoWindow.java | 40 +++++++- 3 files changed, 172 insertions(+), 41 deletions(-) (limited to 'sdkmanager/libs') diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java index d13108a..4f3ed9f 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java @@ -114,41 +114,45 @@ public final class SdkConstants { /** dx.jar file */ public static final String FN_DX_JAR = "dx.jar"; //$NON-NLS-1$ - /** dx executable (with extension for the current OS) */ - public final static String FN_DX = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ? - "dx.bat" : "dx"; //$NON-NLS-1$ //$NON-NLS-2$ + /** dx executable (with extension for the current OS) */ + public final static String FN_DX = + "dx" + ext(".bat", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - /** aapt executable (with extension for the current OS) */ - public final static String FN_AAPT = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ? - "aapt.exe" : "aapt"; //$NON-NLS-1$ //$NON-NLS-2$ + /** aapt executable (with extension for the current OS) */ + public final static String FN_AAPT = + "aapt" + ext(".exe", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - /** aidl executable (with extension for the current OS) */ - public final static String FN_AIDL = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ? - "aidl.exe" : "aidl"; //$NON-NLS-1$ //$NON-NLS-2$ + /** aidl executable (with extension for the current OS) */ + public final static String FN_AIDL = + "aidl" + ext(".exe", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - /** renderscript executable (with extension for the current OS) */ - public final static String FN_RENDERSCRIPT = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ? - "llvm-rs-cc.exe" : "llvm-rs-cc"; //$NON-NLS-1$ //$NON-NLS-2$ + /** renderscript executable (with extension for the current OS) */ + public final static String FN_RENDERSCRIPT = + "llvm-rs-cc" + ext(".exe", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - /** adb executable (with extension for the current OS) */ - public final static String FN_ADB = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ? - "adb.exe" : "adb"; //$NON-NLS-1$ //$NON-NLS-2$ + /** adb executable (with extension for the current OS) */ + public final static String FN_ADB = + "adb" + ext(".exe", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ /** emulator executable for the current OS */ - public final static String FN_EMULATOR = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ? - "emulator.exe" : "emulator"; //$NON-NLS-1$ //$NON-NLS-2$ + public final static String FN_EMULATOR = + "emulator" + ext(".exe", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - /** zipalign executable (with extension for the current OS) */ - public final static String FN_ZIPALIGN = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ? - "zipalign.exe" : "zipalign"; //$NON-NLS-1$ //$NON-NLS-2$ + /** zipalign executable (with extension for the current OS) */ + public final static String FN_ZIPALIGN = + "zipalign" + ext(".exe", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - /** dexdump executable (with extension for the current OS) */ - public final static String FN_DEXDUMP = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ? - "dexdump.exe" : "dexdump"; //$NON-NLS-1$ //$NON-NLS-2$ + /** dexdump executable (with extension for the current OS) */ + public final static String FN_DEXDUMP = + "dexdump" + ext(".exe", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - /** zipalign executable (with extension for the current OS) */ - public final static String FN_PROGUARD = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ? - "proguard.bat" : "proguard.sh"; //$NON-NLS-1$ //$NON-NLS-2$ + /** proguard executable (with extension for the current OS) */ + public final static String FN_PROGUARD = + "proguard" + ext(".bat", ".sh"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + /** find_lock for Windows (with extension for the current OS) */ + public final static String FN_FIND_LOCK = + "find_lock" + ext(".exe", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ /** properties file for SDK Updater packages */ public final static String FN_SOURCE_PROP = "source.properties"; //$NON-NLS-1$ @@ -476,4 +480,12 @@ public final class SdkConstants { return "Other"; } + + private static String ext(String windowsExtension, String nonWindowsExtension) { + if (CURRENT_PLATFORM == PLATFORM_WINDOWS) { + return windowsExtension; + } else { + return nonWindowsExtension; + } + } } diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java index 9046e63..911c475 100755 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java @@ -23,6 +23,8 @@ import com.android.sdklib.SdkManager; import com.android.sdklib.io.FileOp; import com.android.sdklib.io.IFileOp; import com.android.sdklib.repository.RepoConstants; +import com.android.sdklib.util.GrabProcessOutput; +import com.android.sdklib.util.GrabProcessOutput.IProcessOutput; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipFile; @@ -37,10 +39,13 @@ import java.io.InputStream; import java.io.OutputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.Arrays; import java.util.Enumeration; import java.util.HashSet; import java.util.Properties; import java.util.Set; +import java.util.TreeSet; +import java.util.regex.Pattern; /** * Performs the work of installing a given {@link Archive}. @@ -503,18 +508,11 @@ public class ArchiveInstaller { destFolder.getPath(), oldDestFolder.getPath()); if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS) { - String msg = String.format( - "-= Warning ! =-\n" + - "A folder failed to be moved. On Windows this " + - "typically means that a program is using that folder (for " + - "example Windows Explorer or your anti-virus software.)\n" + - "Please momentarily deactivate your anti-virus software or " + - "close any running programs that may be accessing the " + - "directory '%1$s'.\n" + - "When ready, press YES to try again.", - destFolder.getPath()); - - if (monitor.displayPrompt("SDK Manager: failed to install", msg)) { + boolean tryAgain = true; + + tryAgain = windowsDestDirLocked(osSdkRoot, destFolder, monitor); + + if (tryAgain) { // loop, trying to rename the temp dir into the destination continue; } else { @@ -586,6 +584,93 @@ public class ArchiveInstaller { } } + private boolean windowsDestDirLocked( + String osSdkRoot, + File destFolder, + final ITaskMonitor monitor) { + String msg = null; + + assert SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS; + + File findLockExe = FileOp.append( + osSdkRoot, SdkConstants.FD_TOOLS, SdkConstants.FD_LIB, SdkConstants.FN_FIND_LOCK); + + if (mFileOp.exists(findLockExe)) { + try { + final StringBuilder result = new StringBuilder(); + String command[] = new String[] { + findLockExe.getAbsolutePath(), + destFolder.getAbsolutePath() + }; + Process process = Runtime.getRuntime().exec(command); + int retCode = GrabProcessOutput.grabProcessOutput( + process, + true /*waitForReaders*/, + new IProcessOutput() { + @Override + public void out(String line) { + if (line != null) { + result.append(line).append("\n"); + } + } + + @Override + public void err(String line) { + if (line != null) { + monitor.logError("[find_lock] Error: %1$s", line); + } + } + }); + + if (retCode == 0 && result.length() > 0) { + // TODO create a better dialog + + String found = result.toString().trim(); + monitor.logError("[find_lock] Directory locked by %1$s", found); + + TreeSet apps = new TreeSet(Arrays.asList( + found.split(Pattern.quote(";")))); //$NON-NLS-1$ + StringBuilder appStr = new StringBuilder(); + for (String app : apps) { + appStr.append("\n - ").append(app.trim()); //$NON-NLS-1$ + } + + msg = String.format( + "-= Warning ! =-\n" + + "The following processes: %1$s\n" + + "are locking the following directory: \n" + + " %2$s\n" + + "Please close these applications so that the installation can continue.\n" + + "When ready, press YES to try again.", + appStr.toString(), + destFolder.getPath()); + } + + } catch (Exception e) { + monitor.error(e, "[find_lock failed]"); + } + + + } + + if (msg == null) { + // Old way: simply display a generic text and let user figure it out. + msg = String.format( + "-= Warning ! =-\n" + + "A folder failed to be moved. On Windows this " + + "typically means that a program is using that folder (for " + + "example Windows Explorer or your anti-virus software.)\n" + + "Please momentarily deactivate your anti-virus software or " + + "close any running programs that may be accessing the " + + "directory '%1$s'.\n" + + "When ready, press YES to try again.", + destFolder.getPath()); + } + + boolean tryAgain = monitor.displayPrompt("SDK Manager: failed to install", msg); + return tryAgain; + } + /** * Tries to rename/move a folder. *

diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterNoWindow.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterNoWindow.java index 7b94c94..89f084c 100755 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterNoWindow.java +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterNoWindow.java @@ -347,11 +347,37 @@ public class SdkUpdaterNoWindow { @Override public boolean displayPrompt(final String title, final String message) { // TODO Make it interactive if mForce==false - mSdkLog.printf("\n%s\n%s\n[y/n] => %s\n", + mSdkLog.printf("\n%1$s\n%2$s\n%3$s", //$NON-NLS-1$ title, message, - mForce ? "yes" : "no (use --force to override)"); - return mForce; + mForce ? "--force used, will reply yes\n" : + "Note: you can use --force to override to yes.\n"); + if (mForce) { + return true; + } + + while (true) { + mSdkLog.printf("%1$s", "[y/n] =>"); //$NON-NLS-1$ + try { + byte[] readBuffer = new byte[2048]; + String reply = readLine(readBuffer).trim(); + mSdkLog.printf("\n"); //$NON-NLS-1$ + if (reply.length() > 0 && reply.length() <= 3) { + char c = reply.charAt(0); + if (c == 'y' || c == 'Y') { + return true; + } else if (c == 'n' || c == 'N') { + return false; + } + } + mSdkLog.printf("Unknown reply '%s'. Please use y[es]/n[o].\n"); //$NON-NLS-1$ + + } catch (IOException e) { + // Exception. Be conservative and say no. + mSdkLog.printf("\n"); //$NON-NLS-1$ + return false; + } + } } /** @@ -417,6 +443,14 @@ public class SdkUpdaterNoWindow { return new UserCredentials(login, password, workstation, domain); } + /** + * Reads current console input in the given buffer. + * + * @param buffer Buffer to hold the user input. Must be larger than the largest + * expected input. Cannot be null. + * @return A new string. May be empty but not null. + * @throws IOException in case the buffer isn't long enough. + */ private String readLine(byte[] buffer) throws IOException { int count = System.in.read(buffer); -- cgit v1.1