aboutsummaryrefslogtreecommitdiffstats
path: root/eclipse/plugins
diff options
context:
space:
mode:
authorRaphael <raphael@google.com>2012-03-08 22:05:18 -0800
committerRaphael <raphael@google.com>2012-03-09 11:19:28 -0800
commit5b5bdeb7e691980a1174650ce926edbaa87a5a3e (patch)
tree1c0af2e42549806ac628b30bae5d5ce775c5dd5b /eclipse/plugins
parent8fca561846794680e582b2c1416ebda030a90f1a (diff)
downloadsdk-5b5bdeb7e691980a1174650ce926edbaa87a5a3e.zip
sdk-5b5bdeb7e691980a1174650ce926edbaa87a5a3e.tar.gz
sdk-5b5bdeb7e691980a1174650ce926edbaa87a5a3e.tar.bz2
NPW: Find samples in extras.
Changes: - the SdkManager can now list extras that contain a "samples" directory. - The NPW uses that to list samples from extras that match the requested API level. The name of the sample in the list also indicates the extra's display name. Change-Id: Id6609f53b9ba84126e36bc33e5675ec6a0284814
Diffstat (limited to 'eclipse/plugins')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java20
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizardState.java15
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/SampleSelectionPage.java25
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/SdkSelectionPage.java124
4 files changed, 147 insertions, 37 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java
index 63f381f..a661334 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java
@@ -19,6 +19,7 @@ package com.android.ide.eclipse.adt.internal.sdk;
import static com.android.ide.eclipse.adt.AdtConstants.DOT_XML;
import static com.android.sdklib.SdkConstants.FD_RES;
+import com.android.annotations.NonNull;
import com.android.ddmlib.IDevice;
import com.android.ide.common.rendering.LayoutLibrary;
import com.android.ide.common.sdk.LoadStatus;
@@ -303,6 +304,25 @@ public final class Sdk {
}
/**
+ * Returns a <em>new</em> {@link SdkManager} that can parse the SDK located
+ * at the current {@link #getSdkLocation()}.
+ * <p/>
+ * Implementation detail: The {@link Sdk} has its own internal manager with
+ * a custom logger which is not designed to be useful for outsiders. Callers
+ * who need their own {@link SdkManager} for parsing will often want to control
+ * the logger for their own need.
+ * <p/>
+ * This is just a convenient method equivalent to writing:
+ * <pre>SdkManager.createManager(Sdk.getCurrent().getSdkLocation(), log);</pre>
+ *
+ * @param log The logger for the {@link SdkManager}.
+ * @return A new {@link SdkManager} parsing the same location.
+ */
+ public @NonNull SdkManager getNewSdkManager(@NonNull ISdkLog log) {
+ return SdkManager.createManager(getSdkLocation(), log);
+ }
+
+ /**
* Returns the URL to the local documentation.
* Can return null if no documentation is found in the current SDK.
*
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizardState.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizardState.java
index 33f9884..264f09d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizardState.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizardState.java
@@ -26,6 +26,7 @@ import com.android.sdklib.internal.project.ProjectProperties.PropertyType;
import com.android.sdklib.xml.AndroidManifest;
import com.android.sdklib.xml.ManifestData;
import com.android.sdklib.xml.ManifestData.Activity;
+import com.android.util.Pair;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.Path;
@@ -94,14 +95,12 @@ public class NewProjectWizardState {
public String minSdk;
/** True if the minimum SDK version has been manually edited by the user */
public boolean minSdkModifiedByUser;
-
/**
- * The directory where the samples are found. This field is only applicable
- * when the wizard is running in create-sample-mode.
- */
- public File samplesDir;
- /** A list of paths to each of the available samples for the current SDK */
- public List<File> samples = new ArrayList<File>();
+ * A list of paths to each of the available samples for the current SDK.
+ * The pair is (String: sample display name => File: sample directory).
+ * Note we want a list, not a map since we might have duplicates.
+ * */
+ public List<Pair<String, File>> samples = new ArrayList<Pair<String, File>>();
/** Path to the currently chosen sample */
public File chosenSample;
@@ -396,4 +395,4 @@ public class NewProjectWizardState {
*/
ANY;
}
-} \ No newline at end of file
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/SampleSelectionPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/SampleSelectionPage.java
index d54697f..ef16d3d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/SampleSelectionPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/SampleSelectionPage.java
@@ -18,6 +18,7 @@ package com.android.ide.eclipse.adt.internal.wizards.newproject;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizardState.Mode;
import com.android.sdklib.IAndroidTarget;
+import com.android.util.Pair;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
@@ -43,7 +44,6 @@ import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import java.io.File;
-import java.util.regex.Pattern;
/** Page where the user can select a sample to "instantiate" */
class SampleSelectionPage extends WizardPage implements SelectionListener, ModifyListener {
@@ -125,21 +125,11 @@ class SampleSelectionPage extends WizardPage implements SelectionListener, Modif
@Override
public String getText(Object element) {
- File file = (File) element;
- String path = file.getPath();
- int n = mValues.samplesDir.getPath().length();
- if (path.length() > n) {
- path = path.substring(n);
- if (path.charAt(0) == File.separatorChar) {
- path = path.substring(1);
- }
- if (path.endsWith(File.separator)) {
- path = path.substring(0, path.length() - 1);
- }
- path = path.replaceAll(Pattern.quote(File.separator), " > ");
+ if (element instanceof Pair<?, ?>) {
+ Object name = ((Pair<?, ?>) element).getFirst();
+ return name.toString();
}
-
- return path;
+ return element.toString(); // Fallback. Should not happen.
}
};
@@ -151,7 +141,7 @@ class SampleSelectionPage extends WizardPage implements SelectionListener, Modif
mTableViewer.setInput(samples);
mTable.select(0);
- selectSample(mValues.samples.get(0));
+ selectSample(mValues.samples.get(0).getSecond());
extractNamesFromAndroidManifest();
}
}
@@ -170,6 +160,7 @@ class SampleSelectionPage extends WizardPage implements SelectionListener, Modif
}
}
+ @SuppressWarnings("unchecked")
@Override
public void widgetSelected(SelectionEvent e) {
if (mIgnore) {
@@ -181,7 +172,7 @@ class SampleSelectionPage extends WizardPage implements SelectionListener, Modif
int index = mTable.getSelectionIndex();
if (index >= 0) {
Object[] roots = (Object[]) mTableViewer.getInput();
- selectSample((File) roots[index]);
+ selectSample(((Pair<String, File>) roots[index]).getSecond());
} else {
selectSample(null);
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/SdkSelectionPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/SdkSelectionPage.java
index 11d0e95..2713f01 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/SdkSelectionPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/SdkSelectionPage.java
@@ -15,17 +15,25 @@
*/
package com.android.ide.eclipse.adt.internal.wizards.newproject;
+import com.android.annotations.Nullable;
import com.android.ide.common.sdk.LoadStatus;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.ide.eclipse.adt.internal.sdk.Sdk.ITargetChangeListener;
import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizardState.Mode;
+import com.android.io.FileWrapper;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.NullSdkLog;
import com.android.sdklib.SdkConstants;
+import com.android.sdklib.SdkManager;
+import com.android.sdklib.xml.AndroidManifestParser;
+import com.android.sdklib.xml.ManifestData;
import com.android.sdkuilib.internal.widgets.SdkTargetSelector;
+import com.android.util.Pair;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
@@ -38,7 +46,11 @@ import org.eclipse.swt.widgets.Group;
import java.io.File;
import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Pattern;
/** A page in the New Project wizard where you select the target SDK */
class SdkSelectionPage extends WizardPage implements ITargetChangeListener {
@@ -196,21 +208,43 @@ class SdkSelectionPage extends WizardPage implements ITargetChangeListener {
// Get the sample root path and recompute the list of samples
String samplesRootPath = target.getPath(IAndroidTarget.SAMPLES);
- mValues.samplesDir = new File(samplesRootPath);
- findSamplesManifests(mValues.samplesDir, mValues.samples);
+ File root = new File(samplesRootPath);
+ findSamplesManifests(root, root, null, null, mValues.samples);
+
+ Sdk sdk = Sdk.getCurrent();
+ if (sdk != null) {
+ // Parse the extras to see if we can find samples that are
+ // compatible with the selected target API.
+ // First we need an SdkManager that suppresses all output.
+ SdkManager sdkman = sdk.getNewSdkManager(new NullSdkLog());
+
+ Map<File, String> extras = sdkman.getExtraSamples();
+ for (Entry<File, String> entry : extras.entrySet()) {
+ File path = entry.getKey();
+ String name = entry.getValue();
+ findSamplesManifests(path, path, name,
+ target.getVersion(),
+ mValues.samples);
+ }
+ }
- if (mValues.samples.size() == 0) {
+ if (mValues.samples.isEmpty()) {
return;
} else {
- Collections.sort(mValues.samples);
+ Collections.sort(mValues.samples, new Comparator<Pair<String, File>>() {
+ @Override
+ public int compare(Pair<String, File> o1, Pair<String, File> o2) {
+ // Compare the display name of the sample
+ return o1.getFirst().compareTo(o2.getFirst());
+ }
+ });
}
- // Recompute the description of each sample (the relative path
- // to the sample root). Also try to find the old selection.
+ // Try to find the old selection.
if (previouslyChosenSample != null) {
String previouslyChosenName = previouslyChosenSample.getName();
for (int i = 0, n = mValues.samples.size(); i < n; i++) {
- File file = mValues.samples.get(i);
+ File file = mValues.samples.get(i).getSecond();
if (file.getName().equals(previouslyChosenName)) {
mValues.chosenSample = file;
break;
@@ -224,18 +258,61 @@ class SdkSelectionPage extends WizardPage implements ITargetChangeListener {
* Recursively find potential sample directories under the given directory.
* Actually lists any directory that contains an android manifest.
* Paths found are added the samplesPaths list.
+ *
+ * @param rootDir The "samples" root directory. Doesn't change during recursion.
+ * @param currDir The directory being scanned. Caller must initially set it to {@code rootDir}.
+ * @param extraName Optional name appended to the samples display name. Typically used to
+ * indicate a sample comes from a given extra package.
+ * @param targetVersion Optional target version filter. If non null, only samples that are
+ * compatible with the given target will be listed.
+ * @param samplesPaths A non-null list filled by this method with all samples found. The
+ * pair is (String: sample display name => File: sample directory).
*/
- private void findSamplesManifests(File samplesDir, List<File> samplesPaths) {
- if (!samplesDir.isDirectory()) {
+ private void findSamplesManifests(
+ File rootDir,
+ File currDir,
+ @Nullable String extraName,
+ @Nullable AndroidVersion targetVersion,
+ List<Pair<String, File>> samplesPaths) {
+ if (!currDir.isDirectory()) {
return;
}
- for (File f : samplesDir.listFiles()) {
+ for (File f : currDir.listFiles()) {
if (f.isDirectory()) {
// Assume this is a sample if it contains an android manifest.
File manifestFile = new File(f, SdkConstants.FN_ANDROID_MANIFEST_XML);
if (manifestFile.isFile()) {
- samplesPaths.add(f);
+ try {
+ ManifestData data =
+ AndroidManifestParser.parse(new FileWrapper(manifestFile));
+ if (data != null) {
+ boolean accept = false;
+ if (targetVersion == null) {
+ accept = true;
+ } else if (targetVersion != null) {
+ int i = data.getMinSdkVersion();
+ if (i != ManifestData.MIN_SDK_CODENAME) {
+ accept = i <= targetVersion.getApiLevel();
+ } else {
+ String s = data.getMinSdkVersionString();
+ if (s != null) {
+ accept = s.equals(targetVersion.getCodename());
+ }
+ }
+ }
+
+ if (accept) {
+ String name = getSampleDisplayName(extraName, rootDir, f);
+ samplesPaths.add(Pair.of(name, f));
+ }
+ }
+ } catch (Exception e) {
+ // Ignore. Don't use a sample which manifest doesn't parse correctly.
+ AdtPlugin.log(IStatus.INFO,
+ "NPW ignoring malformed manifest %s", //$NON-NLS-1$
+ manifestFile.getAbsolutePath());
+ }
}
// Recurse in the project, to find embedded tests sub-projects
@@ -245,12 +322,35 @@ class SdkSelectionPage extends WizardPage implements ITargetChangeListener {
if (!SdkConstants.FD_SOURCES.equals(leaf) &&
!SdkConstants.FD_ASSETS.equals(leaf) &&
!SdkConstants.FD_RES.equals(leaf)) {
- findSamplesManifests(f, samplesPaths);
+ findSamplesManifests(rootDir, f, extraName, targetVersion, samplesPaths);
}
}
}
}
+ /**
+ * Compute the sample name compared to its root directory.
+ */
+ private String getSampleDisplayName(String extraName, File rootDir, File sampleDir) {
+ String path = sampleDir.getPath();
+ int n = rootDir.getPath().length();
+ if (path.length() > n) {
+ path = path.substring(n);
+ if (path.charAt(0) == File.separatorChar) {
+ path = path.substring(1);
+ }
+ if (path.endsWith(File.separator)) {
+ path = path.substring(0, path.length() - 1);
+ }
+ path = path.replaceAll(Pattern.quote(File.separator), " > "); //$NON-NLS-1$
+ }
+ if (extraName != null) {
+ path = path + " [" + extraName + ']'; //$NON-NLS-1$
+ }
+
+ return path;
+ }
+
private void validatePage() {
String error = null;