Merge "ADT/GLE: Support more layouts in explode mode." into eclair
diff --git a/changes.txt b/changes.txt
new file mode 100644
index 0000000..3eda000
--- /dev/null
+++ b/changes.txt
@@ -0,0 +1,11 @@
+Change log for Android SDK Tools.
+
+Revision 5 (02/2010):
+- AVD/SDK Manager:
+	- Add support for samples components.
+	- improved support for dependency between components.
+	- AVDs now sorted by API level.
+	- Prevent deletion of running AVD.
+- Emulator now requires sd card to be 9MB and above.
+- Fixed layoutopt.bat to correctly execute on Windows.
+
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogPanel.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogPanel.java
index 154e2fa..82c1259 100644
--- a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogPanel.java
+++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogPanel.java
@@ -1568,4 +1568,17 @@
             mEditFilterAction.setEnabled(selectedFilter.supportsEdit());
         }
     }
+
+    public String getSelectedErrorLineMessage() {
+        Table table = mCurrentFilter.getTable();
+        int[] selection = table.getSelectionIndices();
+
+        if (selection.length == 1) {
+            TableItem item = table.getItem(selection[0]);
+            LogMessage msg = (LogMessage)item.getData();
+            if (msg.data.logLevel == LogLevel.ERROR || msg.data.logLevel == LogLevel.WARN)
+                return msg.msg;
+        }
+        return null;
+    }
 }
diff --git a/eclipse/changes.txt b/eclipse/changes.txt
index c051eae..93ca3e5 100644
--- a/eclipse/changes.txt
+++ b/eclipse/changes.txt
@@ -7,6 +7,11 @@
 - Loads the SDK content only when a project requires it. This will make Eclipse use less resources when the SDK contains many versions of Android.
 - DDMS plug-in now contains the Allocation Tracker view.
 - Lots of fixes in the configuration selector of the Visual Layout Editor.
+- Explode mode in the Visual Layout Editor adds a margin to all layout objects so that it's easier to see embedded layouts
+- Outline mode in the Visual Layout Editor draws layout outline to make it easier to see layout objects.
+- Fixed issues with the New Project Wizard when selecting samples.
+- Fixed possible crash when launching applications
+- New action in the Logcat view: "Go to problem" lets you go directly from an exception trace output to the code.
 
 0.9.5:
 - misc fixes in the SDK Updater
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
index 0150eff..4715fd1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
@@ -11,7 +11,8 @@
  org.eclipse.ui.console,
  org.eclipse.core.resources,
  org.eclipse.ui.ide,
- org.eclipse.core.filesystem
+ org.eclipse.core.filesystem,
+ org.eclipse.jdt.core
 Eclipse-LazyStart: true
 Export-Package: com.android.ddmlib,
  com.android.ddmlib.log,
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/LogCatView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/LogCatView.java
index d3053f1..46d8b24 100644
--- a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/LogCatView.java
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/LogCatView.java
@@ -16,16 +16,27 @@
 
 package com.android.ide.eclipse.ddms.views;
 
-import com.android.ide.eclipse.ddms.CommonAction;
-import com.android.ide.eclipse.ddms.DdmsPlugin;
-import com.android.ide.eclipse.ddms.ImageLoader;
-import com.android.ide.eclipse.ddms.preferences.PreferenceInitializer;
 import com.android.ddmlib.Log.LogLevel;
 import com.android.ddmuilib.logcat.LogColors;
 import com.android.ddmuilib.logcat.LogFilter;
 import com.android.ddmuilib.logcat.LogPanel;
 import com.android.ddmuilib.logcat.LogPanel.ILogFilterStorageManager;
+import com.android.ide.eclipse.ddms.CommonAction;
+import com.android.ide.eclipse.ddms.DdmsPlugin;
+import com.android.ide.eclipse.ddms.ImageLoader;
+import com.android.ide.eclipse.ddms.preferences.PreferenceInitializer;
 
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.search.IJavaSearchConstants;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.core.search.SearchMatch;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.core.search.SearchPattern;
+import org.eclipse.jdt.core.search.SearchRequestor;
 import org.eclipse.jface.action.Action;
 import org.eclipse.jface.action.IAction;
 import org.eclipse.jface.action.IMenuManager;
@@ -38,9 +49,18 @@
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IPerspectiveRegistry;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
 import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.internal.WorkbenchPlugin;
+import org.eclipse.ui.internal.registry.PerspectiveDescriptor;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * The log cat view displays log output from the current device selection.
@@ -72,6 +92,7 @@
     private CommonAction mDeleteFilterAction;
     private CommonAction mEditFilterAction;
     private CommonAction mExportAction;
+    private CommonAction gotoLineAction;
 
     private CommonAction[] mLogLevelActions;
     private String[] mLogLevelIcons = {
@@ -208,6 +229,13 @@
         mExportAction.setToolTipText("Export Selection As Text...");
         mExportAction.setImageDescriptor(loader.loadDescriptor("save.png")); // $NON-NLS-1$
 
+        gotoLineAction = new CommonAction("Go to Problem") {
+            @Override
+            public void run() {
+                goToErrorLine();
+            }
+        };
+
         LogLevel[] levels = LogLevel.values();
         mLogLevelActions = new CommonAction[mLogLevelIcons.length];
         for (int i = 0 ; i < mLogLevelActions.length; i++) {
@@ -311,6 +339,7 @@
         menuManager.add(mClearAction);
         menuManager.add(new Separator());
         menuManager.add(mExportAction);
+        menuManager.add(gotoLineAction);
 
         // and then in the toolbar
         IToolBarManager toolBarManager = actionBars.getToolBarManager();
@@ -324,5 +353,110 @@
         toolBarManager.add(new Separator());
         toolBarManager.add(mClearAction);
     }
+
+    IMarker createMarkerFromSearchMatch(IFile file, SearchMatch match) {
+        HashMap<String, Object> map = new HashMap<String, Object>();
+        map.put(IMarker.CHAR_START, new Integer(match.getOffset()));
+        map.put(IMarker.CHAR_END, new Integer(match.getOffset()
+                + match.getLength()));
+        IMarker marker = null;
+        try {
+            marker = file.createMarker(IMarker.TEXT);
+            marker.setAttributes(map);
+        } catch (CoreException e) {
+            Status s = new Status(Status.ERROR, DdmsPlugin.PLUGIN_ID, e.getMessage(), e);
+            DdmsPlugin.getDefault().getLog().log(s);
+        }
+        return marker;
+    }
+
+    void openFile(IFile file, IMarker marker) {
+        try {
+            IWorkbenchPage page = getViewSite().getWorkbenchWindow()
+                    .getActivePage();
+            if (page != null) {
+                IDE.openEditor(page, marker);
+                marker.delete();
+            }
+        } catch (CoreException e) {
+            Status s = new Status(Status.ERROR, DdmsPlugin.PLUGIN_ID, e.getMessage(), e);
+            DdmsPlugin.getDefault().getLog().log(s);
+        }
+    }
+
+    void switchPerspective() {
+
+        IWorkbenchWindow window = getViewSite().getWorkbenchWindow()
+                .getWorkbench().getActiveWorkbenchWindow();
+        String rtPerspectiveId = "org.eclipse.jdt.ui.JavaPerspective";
+        IPerspectiveRegistry reg = WorkbenchPlugin.getDefault()
+                .getPerspectiveRegistry();
+        PerspectiveDescriptor rtPerspectiveDesc = (PerspectiveDescriptor) reg
+                .findPerspectiveWithId(rtPerspectiveId);
+        if (window != null) {
+            IWorkbenchPage page = window.getActivePage();
+            page.setPerspective(rtPerspectiveDesc);
+        }
+    }
+
+    void goToErrorLine() {
+        try {
+            String msg = mLogPanel.getSelectedErrorLineMessage();
+            if (msg != null) {
+                String error_line_matcher_string = "\\s*at\\ (.*)\\((.*\\.java)\\:(\\d+)\\)";
+                Matcher error_line_matcher = Pattern.compile(
+                        error_line_matcher_string).matcher(msg);
+
+                if (error_line_matcher.find()) {
+                    String class_name = error_line_matcher.group(1);
+
+                    // TODO: Search currently only matches the class declaration (using
+                    // IJavaSearchConstants.DECLARATIONS). We may want to jump to the
+                    // "reference" of the class instead (IJavaSearchConstants.REFERENCES)
+                    // using the filename and line number to disambiguate the search results.
+//                  String filename = error_line_matcher.group(2);
+//                  int line_number = Integer.parseInt(error_line_matcher.group(3));
+
+                    SearchEngine se = new SearchEngine();
+                    se.search(SearchPattern.createPattern(class_name,
+                            IJavaSearchConstants.METHOD,
+                            IJavaSearchConstants.DECLARATIONS,
+                            SearchPattern.R_EXACT_MATCH
+                                    | SearchPattern.R_CASE_SENSITIVE),
+                            new SearchParticipant[] { SearchEngine
+                                    .getDefaultSearchParticipant() },
+                            SearchEngine.createWorkspaceScope(),
+                            new SearchRequestor() {
+                                boolean found_first_match = false;
+
+                                @Override
+                                public void acceptSearchMatch(
+                                        SearchMatch match)
+                                        throws CoreException {
+
+                                    if (match.getResource() instanceof IFile
+                                            && !found_first_match) {
+                                        found_first_match = true;
+
+                                        IFile matched_file = (IFile) match
+                                                .getResource();
+                                        IMarker marker = createMarkerFromSearchMatch(
+                                                matched_file, match);
+
+                                        // There should only be one exact match,
+                                        // so we go immediately to that one.
+                                        switchPerspective();
+                                        openFile(matched_file, marker);
+                                    }
+                                }
+                            }, new NullProgressMonitor());
+
+                }
+            }
+        } catch (Exception e) {
+            Status s = new Status(Status.ERROR, DdmsPlugin.PLUGIN_ID, e.getMessage(), e);
+            DdmsPlugin.getDefault().getLog().log(s);
+        }
+    }
  }
 
diff --git a/sdkmanager/app/etc/android.bat b/sdkmanager/app/etc/android.bat
index 58790ce..782003d 100755
--- a/sdkmanager/app/etc/android.bat
+++ b/sdkmanager/app/etc/android.bat
@@ -13,6 +13,10 @@
 rem See the License for the specific language governing permissions and
 rem limitations under the License.
 
+rem Useful links:
+rem Command-line reference:
+rem   http://technet.microsoft.com/en-us/library/bb490890.aspx
+
 rem don't modify the caller's environment
 setlocal
 
@@ -21,16 +25,26 @@
 set prog=%~f0
 
 rem Grab current directory before we change it
-set workdir=%cd%
+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 jarpath=lib\sdkmanager.jar
+
+rem Check we have a valid Java.exe in the path. The return code will
+rem be 0 if the command worked or 9009 if the exec failed (program not found).
+rem Java itself will return 1 if the argument is not understood.
+set java_exe=java
+%java_exe% -version 2>nul
+if ERRORLEVEL 1 goto SearchForJava
+:JavaFound
+
+set jar_path=lib\sdkmanager.jar
 
 rem Set SWT.Jar path based on current architecture (x86 or x86_64)
-for /f %%a in ('java -jar lib\archquery.jar') do set swt_path=lib\%%a
+for /f %%a in ('%java_exe% -jar lib\archquery.jar') do set swt_path=lib\%%a
+
 
 if "%1 %2"=="update sdk" goto StartUi
 if not "%1"=="" goto EndTempCopy
@@ -43,16 +57,16 @@
     rem arguments, to display the SDK Updater UI. This allows the updater to
     rem update the tools directory where the updater itself is located.
 
-    set tmpdir=%TEMP%\temp-android-tool
-    xcopy lib\x86 %tmpdir%\lib\x86 /I /E /C /G /R /Y /Q > nul
-    copy /B /D /Y lib\androidprefs.jar   %tmpdir%\lib\       > nul
-    copy /B /D /Y lib\org.eclipse.*      %tmpdir%\lib\       > nul
-    copy /B /D /Y lib\sdk*               %tmpdir%\lib\       > nul
-    copy /B /D /Y lib\commons-compress*  %tmpdir%\lib\       > nul
+    set tmp_dir=%TEMP%\temp-android-tool
+    xcopy lib\x86 %tmp_dir%\lib\x86 /I /E /C /G /R /Y /Q > nul
+    copy /B /D /Y lib\androidprefs.jar   %tmp_dir%\lib\       > nul
+    copy /B /D /Y lib\org.eclipse.*      %tmp_dir%\lib\       > nul
+    copy /B /D /Y lib\sdk*               %tmp_dir%\lib\       > nul
+    copy /B /D /Y lib\commons-compress*  %tmp_dir%\lib\       > nul
 
-    rem jarpath and swt_path are relative to PWD so we don't need to adjust them, just change dirs.
-    set toolsdir=%cd%
-    cd %tmpdir%
+    rem jar_path and swt_path are relative to PWD so we don't need to adjust them, just change dirs.
+    set tools_dir=%cd%
+    cd %tmp_dir%
 
 :EndTempCopy
     
@@ -65,6 +79,59 @@
     exit /B
 
 :SetPath
-set javaextdirs=%swt_path%;lib\
+set java_ext_dirs=%swt_path%;lib\
 
-call java -Djava.ext.dirs=%javaextdirs% -Dcom.android.sdkmanager.toolsdir="%toolsdir%" -Dcom.android.sdkmanager.workdir="%workdir%" -jar %jarpath% %*
+rem Finally exec the java program and end here.
+call %java_exe% -Djava.ext.dirs=%java_ext_dirs% -Dcom.android.sdkmanager.toolsdir="%tools_dir%" -Dcom.android.sdkmanager.workdir="%work_dir%" -jar %jar_path% %*
+goto :EOF
+
+rem ---------------
+:SearchForJava
+rem We get here if the default %java_exe% was not found in the path.
+rem Search for an alternative in %ProgramFiles%\Java\*\bin\java.exe
+
+echo.
+echo Java not found in your path.
+echo Checking it it's installed in %ProgramFiles%\Java instead.
+echo.
+
+set java_exe=
+for /D %%a in ( "%ProgramFiles%\Java\*" ) do call :TestJavaDir "%%a"
+if defined java_exe goto JavaFound
+
+echo.
+echo No suitable Java found. In order to properly use the Android Developer Tools,
+echo you need a suitable version of Java installed on your system. We recommend
+echo that you install the JDK version of JavaSE, available here:
+echo   http://java.sun.com/javase/downloads/
+echo.
+echo You can find the complete Android SDK requirements here:
+echo   http://developer.android.com/sdk/requirements.html
+echo.
+goto :EOF
+
+rem ---------------
+:TestJavaDir
+rem This is a "subrountine" for the for /D above. It tests the short version
+rem of the %1 path (i.e. the path with only short names and no spaces).
+rem However we use the full version without quotes (e.g. %~1) for pretty print.
+if defined java_exe goto :EOF
+set full_path=%~1\bin\java.exe
+set short_path=%~s1\bin\java.exe
+rem [for debugging] echo Testing %full_path%
+
+%short_path% -version 2>nul
+if ERRORLEVEL 1 goto :EOF
+set java_exe=%short_path%
+
+echo.
+echo Java was found at %full_path%.
+echo Please consider adding it to your path:
+echo - Under Windows XP, open Control Panel / System / Advanced / Environment Variables
+echo - Under Windows Vista, open Control Panel / System / Advanced System Settings
+echo                                                    / Environment Variables
+echo At the end of the "Path" entry in "User variables", add the following:
+echo   ;%full_path%
+echo.
+
+rem EOF
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java
index de51015..218ced0 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java
@@ -280,6 +280,19 @@
         return null;

     }

 

+    /**

+     * Makes sure the base /add-ons folder exists before installing.

+     */

+    @Override

+    public void preInstallHook(String osSdkRoot, Archive archive) {

+        super.preInstallHook(osSdkRoot, archive);

+

+        File addonsRoot = new File(osSdkRoot, SdkConstants.FD_ADDONS);

+        if (!addonsRoot.isDirectory()) {

+            addonsRoot.mkdir();

+        }

+    }

+

     @Override

     public boolean sameItemAs(Package pkg) {

         if (pkg instanceof AddonPackage) {

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 8765905..7c0eef5 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,11 +405,18 @@
 

         archiveFile = downloadFile(osSdkRoot, monitor, forceHttp);

         if (archiveFile != null) {

-            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;

+            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);

             }

         }

 

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 bbc59ff..9a2b93a 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
@@ -403,6 +403,28 @@
             String osSdkRoot, String suggestedDir, SdkManager sdkManager);

 

     /**

+     * Hook called right before an archive is installed. The archive has already

+     * been downloaded succesfully and will be installed in the directory specified by

+     * {@link #getInstallFolder(String, String, SdkManager)} when this call returns.

+     *

+     * @param osSdkRoot The OS path of the SDK root folder.

+     * @param archive The archive that will be installed

+     */

+    public void preInstallHook(String osSdkRoot, Archive archive) {

+        // Nothing to do in base class.

+    }

+

+    /**

+     * 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.

+     */

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

+        // Nothing to do in base class.

+    }

+

+    /**

      * Returns whether the give package represents the same item as the current package.

      * <p/>

      * Two packages are considered the same if they represent the same thing, except for the

diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/PlatformPackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/PlatformPackage.java
index 311499e..3d13c93 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/PlatformPackage.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/PlatformPackage.java
@@ -179,11 +179,25 @@
         }

 

         File platforms = new File(osSdkRoot, SdkConstants.FD_PLATFORMS);

-        File folder = new File(platforms, String.format("android-%s", getVersionName())); //$NON-NLS-1$

+        File folder = new File(platforms,

+                String.format("android-%s", getVersion().getApiString())); //$NON-NLS-1$

 

         return folder;

     }

 

+    /**

+     * Makes sure the base /platforms folder exists before installing.

+     */

+    @Override

+    public void preInstallHook(String osSdkRoot, Archive archive) {

+        super.preInstallHook(osSdkRoot, archive);

+

+        File platformsRoot = new File(osSdkRoot, SdkConstants.FD_PLATFORMS);

+        if (!platformsRoot.isDirectory()) {

+            platformsRoot.mkdir();

+        }

+    }

+

     @Override

     public boolean sameItemAs(Package pkg) {

         if (pkg instanceof PlatformPackage) {

diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/SamplePackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/SamplePackage.java
index 5a0f8fc..afb91e1 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/SamplePackage.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/SamplePackage.java
@@ -206,6 +206,9 @@
     @Override

     public File getInstallFolder(String osSdkRoot, String suggestedDir, SdkManager sdkManager) {

 

+        // The /samples dir at the root of the SDK

+        File samplesRoot = new File(osSdkRoot, SdkConstants.FD_SAMPLES);

+

         // First find if this platform is already installed. If so, reuse the same directory.

         for (IAndroidTarget target : sdkManager.getTargets()) {

             if (target.isPlatform() &&

@@ -213,25 +216,42 @@
                 String p = target.getPath(IAndroidTarget.SAMPLES);

                 File f = new File(p);

                 if (f.isDirectory()) {

-                    return f;

+                    // We *only* use this directory if it's using the "new" location

+                    // under SDK/samples. We explicitly do not reuse the "old" location

+                    // under SDK/platform/android-N/samples.

+                    if (f.getParentFile().equals(samplesRoot)) {

+                        return f;

+                    }

                 }

             }

         }

 

         // Otherwise, get a suitable default

-        File samples = new File(osSdkRoot, SdkConstants.FD_SAMPLES);

-        File folder = new File(samples,

-                String.format("android-%d", getVersion().getApiLevel())); //$NON-NLS-1$

+        File folder = new File(samplesRoot,

+                String.format("android-%s", getVersion().getApiString())); //$NON-NLS-1$

 

         for (int n = 1; folder.exists(); n++) {

             // Keep trying till we find an unused directory.

-            folder = new File(samples,

-                    String.format("android-%d_%d", getVersion().getApiLevel(), n)); //$NON-NLS-1$

+            folder = new File(samplesRoot,

+                    String.format("android-%s_%d", getVersion().getApiString(), n)); //$NON-NLS-1$

         }

 

         return folder;

     }

 

+    /**

+     * Makes sure the base /samples folder exists before installing.

+     */

+    @Override

+    public void preInstallHook(String osSdkRoot, Archive archive) {

+        super.preInstallHook(osSdkRoot, archive);

+

+        File samplesRoot = new File(osSdkRoot, SdkConstants.FD_SAMPLES);

+        if (!samplesRoot.isDirectory()) {

+            samplesRoot.mkdir();

+        }

+    }

+

     @Override

     public boolean sameItemAs(Package pkg) {

         if (pkg instanceof SamplePackage) {

diff --git a/traceview/etc/traceview b/traceview/etc/traceview
index 065cd0f..7035791 100755
--- a/traceview/etc/traceview
+++ b/traceview/etc/traceview
@@ -68,7 +68,7 @@
 fi
 
 while expr "x$1" : 'x-J' >/dev/null; do
-    opt=`expr "$1" : '-J\(.*\)'`
+    opt=`expr "x$1" : 'x-J\(.*\)'`
     javaOpts="${javaOpts} -${opt}"
     shift
 done