SDK Updater: Support post install script for updating SDK Setup.exe.

The new post_tools_install.bat will be found in SDK/tools/lib.
This also moves find_java.bat into the same lib folder.

SDK Bug: 2404830

Change-Id: I84e3671918931079f296500e296ec1a55931b851
diff --git a/apkbuilder/etc/apkbuilder.bat b/apkbuilder/etc/apkbuilder.bat
index 948eec0..eaaf9b8 100755
--- a/apkbuilder/etc/apkbuilder.bat
+++ b/apkbuilder/etc/apkbuilder.bat
@@ -26,7 +26,7 @@
 
 rem Check we have a valid Java.exe in the path.
 set java_exe=
-call find_java.bat
+call lib\find_java.bat
 if not defined java_exe goto :EOF
 
 set jarfile=apkbuilder.jar
diff --git a/ddms/app/etc/ddms.bat b/ddms/app/etc/ddms.bat
index c98621b..271ac4c 100755
--- a/ddms/app/etc/ddms.bat
+++ b/ddms/app/etc/ddms.bat
@@ -26,7 +26,7 @@
 
 rem Check we have a valid Java.exe in the path.
 set java_exe=
-call find_java.bat
+call lib\find_java.bat
 if not defined java_exe goto :EOF
 
 set jarfile=ddms.jar
diff --git a/draw9patch/etc/draw9patch.bat b/draw9patch/etc/draw9patch.bat
index c94956f..b6826fc 100755
--- a/draw9patch/etc/draw9patch.bat
+++ b/draw9patch/etc/draw9patch.bat
@@ -26,7 +26,7 @@
 
 rem Check we have a valid Java.exe in the path.
 set java_exe=
-call find_java.bat
+call lib\find_java.bat
 if not defined java_exe goto :EOF
 
 set jarfile=draw9patch.jar
diff --git a/files/post_tools_install.bat b/files/post_tools_install.bat
new file mode 100644
index 0000000..94928c6
--- /dev/null
+++ b/files/post_tools_install.bat
@@ -0,0 +1,38 @@
+@echo off

+rem Copyright (C) 2010 The Android Open Source Project

+rem

+rem Licensed under the Apache License, Version 2.0 (the "License");

+rem you may not use this file except in compliance with the License.

+rem You may obtain a copy of the License at

+rem

+rem      http://www.apache.org/licenses/LICENSE-2.0

+rem

+rem Unless required by applicable law or agreed to in writing, software

+rem distributed under the License is distributed on an "AS IS" BASIS,

+rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+rem See the License for the specific language governing permissions and

+rem limitations under the License.

+

+rem This script is called by the SDK Manager once a new version of the tools

+rem package as been installed.

+

+rem don't modify the caller's environment

+setlocal

+

+rem Set up prog to be the path of this script, including following symlinks,

+rem and set up progdir to be the fully-qualified pathname of its directory.

+set prog=%~f0

+

+rem Grab current directory before we change it

+set work_dir=%cd%

+

+rem Change current directory and drive to where the script is, to avoid

+rem issues with directories containing whitespaces.

+cd /d %~dp0

+

+set src=SDK Setup.exe

+set dst=..\..\%src%

+

+if not exist "%src%" goto :EOF

+  echo Updating %src%

+  copy /V /Y "%src%" "%dst%"
\ No newline at end of file
diff --git a/hierarchyviewer/etc/hierarchyviewer.bat b/hierarchyviewer/etc/hierarchyviewer.bat
index 28a4d8d..3f8c416 100755
--- a/hierarchyviewer/etc/hierarchyviewer.bat
+++ b/hierarchyviewer/etc/hierarchyviewer.bat
@@ -26,7 +26,7 @@
 
 rem Check we have a valid Java.exe in the path.
 set java_exe=
-call find_java.bat
+call lib\find_java.bat
 if not defined java_exe goto :EOF
 
 set jarfile=hierarchyviewer.jar
diff --git a/layoutopt/app/etc/layoutopt.bat b/layoutopt/app/etc/layoutopt.bat
index 7fedf31..9200227 100755
--- a/layoutopt/app/etc/layoutopt.bat
+++ b/layoutopt/app/etc/layoutopt.bat
@@ -26,7 +26,7 @@
 
 rem Check we have a valid Java.exe in the path.
 set java_exe=
-call find_java.bat
+call lib\find_java.bat
 if not defined java_exe goto :EOF
 
 set jarfile=layoutopt.jar
diff --git a/sdkmanager/app/etc/android.bat b/sdkmanager/app/etc/android.bat
index 196e684..bd2fdec 100755
--- a/sdkmanager/app/etc/android.bat
+++ b/sdkmanager/app/etc/android.bat
@@ -34,7 +34,7 @@
 
 rem Check we have a valid Java.exe in the path.
 set java_exe=
-call find_java.bat
+call lib\find_java.bat
 if not defined java_exe goto :EOF
 
 set jar_path=lib\sdkmanager.jar
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java
index 7c0eef5..01b52d1 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java
@@ -405,18 +405,13 @@
 

         archiveFile = downloadFile(osSdkRoot, monitor, forceHttp);

         if (archiveFile != null) {

-            boolean installSuccess = false;

-            try {

-                pkg.preInstallHook(osSdkRoot, this);

-                if (unarchive(osSdkRoot, archiveFile, sdkManager, monitor)) {

-                    monitor.setResult("Installed %1$s", name);

-                    // Delete the temp archive if it exists, only on success

-                    deleteFileOrFolder(archiveFile);

-                    installSuccess = true;

-                    return true;

-                }

-            } finally {

-                pkg.postInstallHook(this, installSuccess);

+            pkg.preInstallHook(osSdkRoot, this);

+            // Unarchive will call the postInstallHook on completion.

+            if (unarchive(osSdkRoot, archiveFile, sdkManager, monitor)) {

+                monitor.setResult("Installed %1$s", name);

+                // Delete the temp archive if it exists, only on success

+                deleteFileOrFolder(archiveFile);

+                return true;

             }

         }

 

@@ -699,7 +694,9 @@
             File archiveFile,

             SdkManager sdkManager,

             ITaskMonitor monitor) {

-        String pkgName = getParentPackage().getShortDescription();

+        boolean success = false;

+        Package pkg = getParentPackage();

+        String pkgName = pkg.getShortDescription();

         String pkgDesc = String.format("Installing %1$s", pkgName);

         monitor.setDescription(pkgDesc);

         monitor.setResult(pkgDesc);

@@ -709,11 +706,11 @@
         // If the destination folder exists, it will be renamed and deleted at the very

         // end if everything succeeded.

 

-        String pkgKind = getParentPackage().getClass().getSimpleName();

+        String pkgKind = pkg.getClass().getSimpleName();

 

         File destFolder = null;

         File unzipDestFolder = null;

-        File renamedDestFolder = null;

+        File oldDestFolder = null;

 

         try {

             // Find a new temp folder that doesn't exist yet

@@ -742,8 +739,7 @@
             }

 

             // Compute destination directory

-            destFolder = getParentPackage().getInstallFolder(

-                    osSdkRoot, zipRootFolder[0], sdkManager);

+            destFolder = pkg.getInstallFolder(osSdkRoot, zipRootFolder[0], sdkManager);

 

             if (destFolder == null) {

                 // this should not seriously happen.

@@ -763,19 +759,19 @@
                 if (!move1done) {

                     if (destFolder.isDirectory()) {

                         // Create a new temp/old dir

-                        if (renamedDestFolder == null) {

-                            renamedDestFolder = createTempFolder(osSdkRoot, pkgKind, "old");  //$NON-NLS-1$

+                        if (oldDestFolder == null) {

+                            oldDestFolder = createTempFolder(osSdkRoot, pkgKind, "old");  //$NON-NLS-1$

                         }

-                        if (renamedDestFolder == null) {

+                        if (oldDestFolder == null) {

                             // this should not seriously happen.

                             monitor.setResult("Failed to find a temp directory in %1$s.", osSdkRoot);

                             return false;

                         }

 

                         // try to move the current dest dir to the temp/old one

-                        if (!destFolder.renameTo(renamedDestFolder)) {

+                        if (!destFolder.renameTo(oldDestFolder)) {

                             monitor.setResult("Failed to rename directory %1$s to %2$s.",

-                                    destFolder.getPath(), renamedDestFolder.getPath());

+                                    destFolder.getPath(), oldDestFolder.getPath());

                             renameFailedForDir = destFolder;

                         }

                     }

@@ -784,7 +780,7 @@
                 }

 

                 // Case where there's no dest dir or we successfully moved it to temp/old

-                // We not try to move the temp/unzip to the dest dir

+                // We now try to move the temp/unzip to the dest dir

                 if (move1done && !move2done) {

                     if (renameFailedForDir == null && !unzipDestFolder.renameTo(destFolder)) {

                         monitor.setResult("Failed to rename directory %1$s to %2$s",

@@ -821,12 +817,19 @@
             }

 

             unzipDestFolder = null;

+            success = true;

+            pkg.postInstallHook(this, monitor, destFolder);

             return true;

 

         } finally {

             // Cleanup if the unzip folder is still set.

-            deleteFileOrFolder(renamedDestFolder);

+            deleteFileOrFolder(oldDestFolder);

             deleteFileOrFolder(unzipDestFolder);

+

+            // In case of failure, we call the postInstallHool with a null directory

+            if (!success) {

+                pkg.postInstallHook(this, monitor, null /*installDir*/);

+            }

         }

     }

 

diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java
index 9a2b93a..3dbfefc 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java
@@ -417,10 +417,12 @@
     /**

      * Hook called right after an archive has been installed.

      *

-     * @param archive The archive that has been installed

-     * @param installSuccess True if the archive was successfully installed.

+     * @param archive The archive that has been installed.

+     * @param monitor The {@link ITaskMonitor} to display errors.

+     * @param installFolder The folder where the archive was successfully installed.

+     *                      Null if the installation failed.

      */

-    public void postInstallHook(Archive archive, boolean installSuccess) {

+    public void postInstallHook(Archive archive, ITaskMonitor monitor, File installFolder) {

         // Nothing to do in base class.

     }

 

diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java
index 8b77db8..a5e9d3c 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java
@@ -23,7 +23,10 @@
 

 import org.w3c.dom.Node;

 

+import java.io.BufferedReader;

 import java.io.File;

+import java.io.IOException;

+import java.io.InputStreamReader;

 import java.util.Map;

 import java.util.Properties;

 

@@ -116,4 +119,137 @@
         // only one tool package so any tool package is the same item.

         return pkg instanceof ToolPackage;

     }

+

+    /**

+     * The tool package executes tools/lib/post_tools_install[.bat|.sh]

+     * {@inheritDoc}

+     */

+    @Override

+    public void postInstallHook(Archive archive, ITaskMonitor monitor, File installFolder) {

+        super.postInstallHook(archive, monitor, installFolder);

+

+        if (installFolder == null) {

+            return;

+        }

+

+        File libDir = new File(installFolder, SdkConstants.FD_LIB);

+        if (!libDir.isDirectory()) {

+            return;

+        }

+

+        String scriptName = "post_tools_install";   //$NON-NLS-1$

+        String shell = "";

+        if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_WINDOWS) {

+            shell = "cmd.exe /c ";

+            scriptName += ".bat";                   //$NON-NLS-1$

+        } else {

+            scriptName += ".sh";                    //$NON-NLS-1$

+        }

+

+        File scriptFile = new File(libDir, scriptName);

+        if (!scriptFile.isFile()) {

+            return;

+        }

+

+        Process proc;

+        int status = -1;

+

+        try {

+            proc = Runtime.getRuntime().exec(

+                    shell + scriptName, // command

+                    null,       // environment

+                    libDir);    // working dir

+

+            status = grabProcessOutput(proc, monitor, scriptName);

+

+        } catch (Exception e) {

+            monitor.setResult("Exception: %s", e.toString());

+        }

+

+        if (status != 0) {

+            monitor.setResult("Failed to execute %s", scriptName);

+            return;

+        }

+    }

+

+    /**

+     * Get the stderr/stdout outputs of a process and return when the process is done.

+     * Both <b>must</b> be read or the process will block on windows.

+     * @param process The process to get the ouput from.

+     * @param monitor The monitor where to output errors.

+     * @param scriptName The name of script being executed.

+     * @return the process return code.

+     * @throws InterruptedException

+     */

+    private int grabProcessOutput(final Process process,

+            final ITaskMonitor monitor,

+            final String scriptName)

+                throws InterruptedException {

+        // read the lines as they come. if null is returned, it's

+        // because the process finished

+        Thread t1 = new Thread("") { //$NON-NLS-1$

+            @Override

+            public void run() {

+                // create a buffer to read the stderr output

+                InputStreamReader is = new InputStreamReader(process.getErrorStream());

+                BufferedReader errReader = new BufferedReader(is);

+

+                try {

+                    while (true) {

+                        String line = errReader.readLine();

+                        if (line != null) {

+                            monitor.setResult("[%1$s] Error: %2$s", scriptName, line);

+                        } else {

+                            break;

+                        }

+                    }

+                } catch (IOException e) {

+                    // do nothing.

+                }

+            }

+        };

+

+        Thread t2 = new Thread("") { //$NON-NLS-1$

+            @Override

+            public void run() {

+                InputStreamReader is = new InputStreamReader(process.getInputStream());

+                BufferedReader outReader = new BufferedReader(is);

+

+                try {

+                    while (true) {

+                        String line = outReader.readLine();

+                        if (line != null) {

+                            monitor.setResult("[%1$s] %2$s", scriptName, line);

+                        } else {

+                            break;

+                        }

+                    }

+                } catch (IOException e) {

+                    // do nothing.

+                }

+            }

+        };

+

+        t1.start();

+        t2.start();

+

+        // it looks like on windows process#waitFor() can return

+        // before the thread have filled the arrays, so we wait for both threads and the

+        // process itself.

+        /* Disabled since not used. Do we really need this?

+        if (waitforReaders) {

+            try {

+                t1.join();

+            } catch (InterruptedException e) {

+            }

+            try {

+                t2.join();

+            } catch (InterruptedException e) {

+            }

+        }

+        */

+

+        // get the return code from the process

+        return process.waitFor();

+    }

 }

diff --git a/traceview/etc/traceview.bat b/traceview/etc/traceview.bat
index 15530a9..ca26831 100755
--- a/traceview/etc/traceview.bat
+++ b/traceview/etc/traceview.bat
@@ -26,7 +26,7 @@
 
 rem Check we have a valid Java.exe in the path.
 set java_exe=
-call find_java.bat
+call lib\find_java.bat
 if not defined java_exe goto :EOF
 
 set jarfile=traceview.jar