aboutsummaryrefslogtreecommitdiffstats
path: root/sdkmanager/libs
diff options
context:
space:
mode:
Diffstat (limited to 'sdkmanager/libs')
-rw-r--r--sdkmanager/libs/Android.mk18
-rw-r--r--sdkmanager/libs/sdklib/.classpath7
-rw-r--r--sdkmanager/libs/sdklib/.project17
-rw-r--r--sdkmanager/libs/sdklib/Android.mk17
-rw-r--r--sdkmanager/libs/sdklib/src/Android.mk27
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java198
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java104
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/ISdkLog.java25
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java186
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java174
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java420
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/project/ProjectProperties.java136
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/vm/HardwareProperties.java159
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/vm/VmManager.java258
-rw-r--r--sdkmanager/libs/sdkuilib/Android.mk4
-rw-r--r--sdkmanager/libs/sdkuilib/README11
-rw-r--r--sdkmanager/libs/sdkuilib/src/Android.mk21
-rw-r--r--sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/SdkTargetSelector.java319
18 files changed, 2101 insertions, 0 deletions
diff --git a/sdkmanager/libs/Android.mk b/sdkmanager/libs/Android.mk
new file mode 100644
index 0000000..a934aa7
--- /dev/null
+++ b/sdkmanager/libs/Android.mk
@@ -0,0 +1,18 @@
+#
+# Copyright (C) 2008 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.
+#
+SDKLIBS_LOCAL_DIR := $(call my-dir)
+include $(SDKLIBS_LOCAL_DIR)/sdklib/Android.mk
+include $(SDKLIBS_LOCAL_DIR)/sdkuilib/Android.mk
diff --git a/sdkmanager/libs/sdklib/.classpath b/sdkmanager/libs/sdklib/.classpath
new file mode 100644
index 0000000..fc17a43
--- /dev/null
+++ b/sdkmanager/libs/sdklib/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/AndroidPrefs"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/sdkmanager/libs/sdklib/.project b/sdkmanager/libs/sdklib/.project
new file mode 100644
index 0000000..97a8578
--- /dev/null
+++ b/sdkmanager/libs/sdklib/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>SdkLib</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/sdkmanager/libs/sdklib/Android.mk b/sdkmanager/libs/sdklib/Android.mk
new file mode 100644
index 0000000..509c573
--- /dev/null
+++ b/sdkmanager/libs/sdklib/Android.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2008 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.
+#
+SDKLIB_LOCAL_DIR := $(call my-dir)
+include $(SDKLIB_LOCAL_DIR)/src/Android.mk
diff --git a/sdkmanager/libs/sdklib/src/Android.mk b/sdkmanager/libs/sdklib/src/Android.mk
new file mode 100644
index 0000000..a059a46
--- /dev/null
+++ b/sdkmanager/libs/sdklib/src/Android.mk
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2008 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.
+#
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := \
+ androidprefs
+
+LOCAL_MODULE := sdklib
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java
new file mode 100644
index 0000000..5759613
--- /dev/null
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2008 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.sdklib;
+
+import java.io.File;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * Represents an add-on target in the SDK.
+ * An add-on extends a standard {@link PlatformTarget}.
+ */
+final class AddOnTarget implements IAndroidTarget {
+ /**
+ * String to compute hash for add-on targets.
+ * Format is vendor:name:apiVersion
+ * */
+ private final static String ADD_ON_FORMAT = "%s:%s:%d"; //$NON-NLS-1$
+
+ private final static class OptionalLibrary implements IOptionalLibrary {
+ private final String mJarName;
+ private final String mJarPath;
+ private final String mName;
+
+ OptionalLibrary(String jarName, String jarPath, String name) {
+ mJarName = jarName;
+ mJarPath = jarPath;
+ mName = name;
+ }
+
+ public String getJarName() {
+ return mJarName;
+ }
+
+ public String getJarPath() {
+ return mJarPath;
+ }
+
+ public String getName() {
+ return mName;
+ }
+ }
+
+ private final String mLocation;
+ private final PlatformTarget mBasePlatform;
+ private final String mName;
+ private final String mVendor;
+ private final String mDescription;
+ private String[] mSkins;
+ private IOptionalLibrary[] mLibraries;
+
+ /**
+ * Creates a new add-on
+ * @param location the OS path location of the add-on
+ * @param name the name of the add-on
+ * @param vendor the vendor name of the add-on
+ * @param description the add-on description
+ * @param libMap A map containing the optional libraries. The map key is the fully-qualified
+ * library name. The value is the .jar filename
+ * @param basePlatform the platform the add-on is extending.
+ */
+ AddOnTarget(String location, String name, String vendor, String description,
+ Map<String, String> libMap, PlatformTarget basePlatform) {
+ if (location.endsWith(File.separator) == false) {
+ location = location + File.separator;
+ }
+
+ mLocation = location;
+ mName = name;
+ mVendor = vendor;
+ mDescription = description;
+ mBasePlatform = basePlatform;
+
+ // handle the optional libraries.
+ mLibraries = new IOptionalLibrary[libMap.size()];
+ int index = 0;
+ for (Entry<String, String> entry : libMap.entrySet()) {
+ mLibraries[index++] = new OptionalLibrary(entry.getValue(),
+ mLocation + SdkConstants.OS_ADDON_LIBS_FOLDER + entry.getValue(),
+ entry.getKey());
+ }
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public String getVendor() {
+ return mVendor;
+ }
+
+ public String getDescription() {
+ return mDescription;
+ }
+
+ public String getApiVersionName() {
+ // this is always defined by the base platform
+ return mBasePlatform.getApiVersionName();
+ }
+
+ public int getApiVersionNumber() {
+ // this is always defined by the base platform
+ return mBasePlatform.getApiVersionNumber();
+ }
+
+ public boolean isPlatform() {
+ return false;
+ }
+
+ public String getPath(int pathId) {
+ switch (pathId) {
+ case IMAGES:
+ return mLocation + SdkConstants.OS_IMAGES_FOLDER;
+ case SKINS:
+ return mLocation + SdkConstants.OS_SKINS_FOLDER;
+ default :
+ return mBasePlatform.getPath(pathId);
+ }
+ }
+
+ public String[] getSkins() {
+ return mSkins;
+ }
+
+ public IOptionalLibrary[] getOptionalLibraries() {
+ return mLibraries;
+ }
+
+ public String hashString() {
+ return String.format(ADD_ON_FORMAT, mVendor, mName, mBasePlatform.getApiVersionNumber());
+ }
+
+ @Override
+ public int hashCode() {
+ return hashString().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof AddOnTarget) {
+ AddOnTarget addon = (AddOnTarget)obj;
+
+ return mVendor.equals(addon.mVendor) && mName.equals(addon.mName) &&
+ mBasePlatform.getApiVersionNumber() == addon.mBasePlatform.getApiVersionNumber();
+ }
+
+ return super.equals(obj);
+ }
+
+ /*
+ * Always return +1 if the object we compare to is a platform.
+ * Otherwise, do vendor then name then api version comparison.
+ * (non-Javadoc)
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo(IAndroidTarget target) {
+ if (target.isPlatform()) {
+ return +1;
+ }
+
+ // vendor
+ int value = mVendor.compareTo(target.getVendor());
+
+ // name
+ if (value == 0) {
+ value = mName.compareTo(target.getName());
+ }
+
+ // api version
+ if (value == 0) {
+ value = getApiVersionNumber() - target.getApiVersionNumber();
+ }
+
+ return value;
+ }
+
+
+ // ---- local methods.
+
+
+ public void setSkins(String[] skins) {
+ mSkins = skins;
+ }
+}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java
new file mode 100644
index 0000000..e5d45b2
--- /dev/null
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2008 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.sdklib;
+
+
+/**
+ * A version of Android that application can target when building.
+ */
+public interface IAndroidTarget extends Comparable<IAndroidTarget> {
+
+ public static int ANDROID_JAR = 1;
+ public static int ANDROID_AIDL = 2;
+ public static int IMAGES = 3;
+ public static int SAMPLES = 4;
+ public static int SKINS = 5;
+ public static int TEMPLATES = 6;
+ public static int DATA = 7;
+ public static int ATTRIBUTES = 8;
+ public static int MANIFEST_ATTRIBUTES = 9;
+ public static int LAYOUT_LIB = 10;
+ public static int RESOURCES = 11;
+ public static int FONTS = 12;
+ public static int WIDGETS = 13;
+ public static int ACTIONS_ACTIVITY = 14;
+ public static int ACTIONS_BROADCAST = 15;
+ public static int ACTIONS_SERVICE = 16;
+ public static int CATEGORIES = 17;
+ public static int SOURCES = 18;
+
+ public interface IOptionalLibrary {
+ String getName();
+ String getJarName();
+ String getJarPath();
+ }
+
+ /**
+ * Returns the name of the vendor of the target.
+ */
+ String getVendor();
+
+ /**
+ * Returns the name of the target.
+ */
+ String getName();
+
+ /**
+ * Returns the description of the target.
+ */
+ String getDescription();
+
+ /**
+ * Returns the api version as an integer.
+ */
+ int getApiVersionNumber();
+
+ /**
+ * Returns the platform version as a readable string.
+ */
+ String getApiVersionName();
+
+ /**
+ * Returns true if the target is a standard Android platform.
+ */
+ boolean isPlatform();
+
+ /**
+ * Returns the path of a platform component.
+ * @param pathId the id representing the path to return. Any of the constants defined in the
+ * {@link ITargetDataProvider} interface can be used.
+ */
+ String getPath(int pathId);
+
+ /**
+ * Returns the available skins for this target.
+ */
+ String[] getSkins();
+
+ /**
+ * Returns the available optional libraries for this target.
+ * @return an array of optional libraries or <code>null</code> if there is none.
+ */
+ IOptionalLibrary[] getOptionalLibraries();
+
+ /**
+ * Returns a string able to uniquely identify a target.
+ * Typically the target will encode information such as api level, whether it's a platform
+ * or add-on, and if it's an add-on vendor and add-on name.
+ */
+ String hashString();
+}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/ISdkLog.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/ISdkLog.java
new file mode 100644
index 0000000..3eda37f
--- /dev/null
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/ISdkLog.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2008 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.sdklib;
+
+/**
+ * Interface used to display warnings/errors while parsing the SDK content.
+ */
+public interface ISdkLog {
+ void warning(String warningFormat, Object... args);
+ void error(String errorFormat, Object... args);
+}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java
new file mode 100644
index 0000000..f5a1f6d
--- /dev/null
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2008 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.sdklib;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Represents a platform target in the SDK.
+ */
+final class PlatformTarget implements IAndroidTarget {
+ /** String used to get a hash to the platform target */
+ private final static String PLATFORM_HASH = "android-%d";
+
+ private final static String PLATFORM_VENDOR = "Android";
+ private final static String PLATFORM_NAME = "Android %s";
+
+ private final String mLocation;
+ private final String mName;
+ private final int mApiVersionNumber;
+ private final String mApiVersionName;
+ private final Map<String, String> mProperties;
+ private final Map<Integer, String> mPaths = new HashMap<Integer, String>();
+ private String[] mSkins;
+
+ PlatformTarget(String location, Map<String, String> properties,
+ int apiNumber, String apiName) {
+ mName = String.format(PLATFORM_NAME, apiName);
+ if (location.endsWith(File.separator) == false) {
+ location = location + File.separator;
+ }
+ mLocation = location;
+ mProperties = Collections.unmodifiableMap(properties);
+ mApiVersionNumber = apiNumber;
+ mApiVersionName = apiName;
+
+ // pre-build the path to the platform components
+ mPaths.put(ANDROID_JAR, mLocation + SdkConstants.FN_FRAMEWORK_LIBRARY);
+ mPaths.put(SOURCES, mLocation + SdkConstants.FD_ANDROID_SOURCES);
+ mPaths.put(ANDROID_AIDL, mLocation + SdkConstants.FN_FRAMEWORK_AIDL);
+ mPaths.put(IMAGES, mLocation + SdkConstants.OS_IMAGES_FOLDER);
+ mPaths.put(SAMPLES, mLocation + SdkConstants.OS_PLATFORM_SAMPLES_FOLDER);
+ mPaths.put(SKINS, mLocation + SdkConstants.OS_SKINS_FOLDER);
+ mPaths.put(TEMPLATES, mLocation + SdkConstants.OS_PLATFORM_TEMPLATES_FOLDER);
+ mPaths.put(DATA, mLocation + SdkConstants.OS_PLATFORM_DATA_FOLDER);
+ mPaths.put(ATTRIBUTES, mLocation + SdkConstants.OS_PLATFORM_ATTRS_XML);
+ mPaths.put(MANIFEST_ATTRIBUTES, mLocation + SdkConstants.OS_PLATFORM_ATTRS_MANIFEST_XML);
+ mPaths.put(RESOURCES, mLocation + SdkConstants.OS_PLATFORM_RESOURCES_FOLDER);
+ mPaths.put(FONTS, mLocation + SdkConstants.OS_PLATFORM_FONTS_FOLDER);
+ mPaths.put(LAYOUT_LIB, mLocation + SdkConstants.OS_PLATFORM_DATA_FOLDER +
+ SdkConstants.FN_LAYOUTLIB_JAR);
+ mPaths.put(WIDGETS, mLocation + SdkConstants.OS_PLATFORM_DATA_FOLDER +
+ SdkConstants.FN_WIDGETS);
+ mPaths.put(ACTIONS_ACTIVITY, mLocation + SdkConstants.OS_PLATFORM_DATA_FOLDER +
+ SdkConstants.FN_INTENT_ACTIONS_ACTIVITY);
+ mPaths.put(ACTIONS_BROADCAST, mLocation + SdkConstants.OS_PLATFORM_DATA_FOLDER +
+ SdkConstants.FN_INTENT_ACTIONS_BROADCAST);
+ mPaths.put(ACTIONS_SERVICE, mLocation + SdkConstants.OS_PLATFORM_DATA_FOLDER +
+ SdkConstants.FN_INTENT_ACTIONS_SERVICE);
+ mPaths.put(CATEGORIES, mLocation + SdkConstants.OS_PLATFORM_DATA_FOLDER +
+ SdkConstants.FN_INTENT_CATEGORIES);
+ }
+
+ public String getLocation() {
+ return mLocation;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * For Platform, the vendor name is always "Android".
+ *
+ * @see com.android.sdklib.IAndroidTarget#getVendor()
+ */
+ public String getVendor() {
+ return PLATFORM_VENDOR;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * Description for the Android platform is dynamically generated.
+ *
+ * @see com.android.sdklib.IAndroidTarget#getDescription()
+ */
+ public String getDescription() {
+ return String.format("Standard Android platform %s", mApiVersionName);
+ }
+
+ public int getApiVersionNumber(){
+ return mApiVersionNumber;
+ }
+
+ public String getApiVersionName() {
+ return mApiVersionName;
+ }
+
+ public boolean isPlatform() {
+ return true;
+ }
+
+ public String getPath(int pathId) {
+ return mPaths.get(pathId);
+ }
+
+ public String[] getSkins() {
+ return mSkins;
+ }
+
+ /*
+ * Always returns null, as a standard platforms have no optional libraries.
+ *
+ * (non-Javadoc)
+ * @see com.android.sdklib.IAndroidTarget#getOptionalLibraries()
+ */
+ public IOptionalLibrary[] getOptionalLibraries() {
+ return null;
+ }
+
+
+ public String hashString() {
+ return String.format(PLATFORM_HASH, mApiVersionNumber);
+ }
+
+ @Override
+ public int hashCode() {
+ return hashString().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof PlatformTarget) {
+ return mApiVersionNumber == ((PlatformTarget)obj).mApiVersionNumber;
+ }
+
+ return super.equals(obj);
+ }
+
+ /*
+ * Always return -1 if the object we compare to is an addon.
+ * Otherwise, compare api level.
+ * (non-Javadoc)
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo(IAndroidTarget target) {
+ if (target.isPlatform() == false) {
+ return -1;
+ }
+
+ return mApiVersionNumber - target.getApiVersionNumber();
+ }
+
+ // ---- platform only methods.
+
+ public String getProperty(String name) {
+ return mProperties.get(name);
+ }
+
+ public Map<String, String> getProperties() {
+ return mProperties; // mProperties is unmodifiable.
+ }
+
+ void setSkins(String[] skins) {
+ mSkins = skins;
+ }
+}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
new file mode 100644
index 0000000..78d1fda
--- /dev/null
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2007 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.sdklib;
+
+import java.io.File;
+
+/**
+ * Constant definition class.<br>
+ * <br>
+ * Most constants have a prefix defining the content.
+ * <ul>
+ * <li><code>OS_</code> OS path constant. These paths are different depending on the platform.</li>
+ * <li><code>FN_</code> File name constant.</li>
+ * <li><code>FD_</code> Folder name constant.</li>
+ * </ul>
+ *
+ */
+public final class SdkConstants {
+
+ /** Name of the framework library, i.e. "android.jar" */
+ public static final String FN_FRAMEWORK_LIBRARY = "android.jar";
+ /** Name of the layout attributes, i.e. "attrs.xml" */
+ public static final String FN_ATTRS_XML = "attrs.xml";
+ /** Name of the layout attributes, i.e. "attrs_manifest.xml" */
+ public static final String FN_ATTRS_MANIFEST_XML = "attrs_manifest.xml";
+ /** framework aidl import file */
+ public static final String FN_FRAMEWORK_AIDL = "framework.aidl";
+ /** layoutlib.jar file */
+ public static final String FN_LAYOUTLIB_JAR = "layoutlib.jar";
+ /** widget list file */
+ public static final String FN_WIDGETS = "widgets.txt";
+ /** Intent activity actions list file */
+ public static final String FN_INTENT_ACTIONS_ACTIVITY = "activity_actions.txt";
+ /** Intent broadcast actions list file */
+ public static final String FN_INTENT_ACTIONS_BROADCAST = "broadcast_actions.txt";
+ /** Intent service actions list file */
+ public static final String FN_INTENT_ACTIONS_SERVICE = "service_actions.txt";
+ /** Intent category list file */
+ public static final String FN_INTENT_CATEGORIES = "categories.txt";
+
+ /** platform build property file */
+ public final static String FN_BUILD_PROP = "build.prop";
+ /** plugin properties file */
+ public final static String FN_PLUGIN_PROP = "plugin.prop";
+ /** add-on manifest file */
+ public final static String FN_MANIFEST_INI = "manifest.ini";
+ /** hardware properties definition file */
+ public final static String FN_HARDWARE_INI = "hardware-properties.ini";
+
+ /** Skin layout file */
+ public final static String FN_SKIN_LAYOUT = "layout";//$NON-NLS-1$
+
+ /* Folder Names for the Android SDK */
+
+ /** Name of the SDK platforms folder. */
+ public final static String FD_PLATFORMS = "platforms";
+ /** Name of the SDK addons folder. */
+ public final static String FD_ADDONS = "add-ons";
+ /** Name of the SDK tools folder. */
+ public final static String FD_TOOLS = "tools";
+ /** Name of the SDK tools/lib folder. */
+ public final static String FD_LIB = "lib";
+ /** Name of the SDK docs folder. */
+ public final static String FD_DOCS = "docs";
+ /** Name of the SDK images folder. */
+ public final static String FD_IMAGES = "images";
+ /** Name of the SDK skins folder. */
+ public final static String FD_SKINS = "skins";
+ /** Name of the SDK samples folder. */
+ public final static String FD_SAMPLES = "samples";
+ /** Name of the SDK templates folder, i.e. "templates" */
+ public final static String FD_TEMPLATES = "templates";
+ /** Name of the SDK data folder, i.e. "data" */
+ public final static String FD_DATA = "data";
+ /** Name of the SDK resources folder, i.e. "res" */
+ public final static String FD_RES = "res";
+ /** Name of the SDK font folder, i.e. "fonts" */
+ public final static String FD_FONTS = "fonts";
+ /** Default values resource folder name, i.e. "values" */
+ public final static String FD_VALUES = "values";
+ /** Name of the android sources directory */
+ public static final String FD_ANDROID_SOURCES = "sources";
+ /** Name of the addon libs folder. */
+ public final static String FD_ADDON_LIBS = "libs";
+
+ /* Folder path relative to the SDK root */
+ /** Path of the documentation directory relative to the sdk folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_SDK_DOCS_FOLDER = FD_DOCS + File.separator;
+
+ /** Path of the tools directory relative to the sdk folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_SDK_TOOLS_FOLDER = FD_TOOLS + File.separator;
+
+ /** Path of the lib directory relative to the sdk folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_SDK_TOOLS_LIB_FOLDER =
+ OS_SDK_TOOLS_FOLDER + FD_LIB + File.separator;
+
+ /* Folder paths relative to a platform or add-on folder */
+
+ /** Path of the images directory relative to a platform or addon folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_IMAGES_FOLDER = FD_IMAGES + File.separator;
+
+ /** Path of the skin directory relative to a platform or addon folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_SKINS_FOLDER = FD_SKINS + File.separator;
+
+ /* Folder paths relative to a Platform folder */
+
+ /** Path of the data directory relative to a platform folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_PLATFORM_DATA_FOLDER = FD_DATA + File.separator;
+
+ /** Path of the samples directory relative to a platform folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_PLATFORM_SAMPLES_FOLDER = FD_SAMPLES + File.separator;
+
+ /** Path of the resources directory relative to a platform folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_PLATFORM_RESOURCES_FOLDER =
+ OS_PLATFORM_DATA_FOLDER + FD_RES + File.separator;
+
+ /** Path of the fonts directory relative to a platform folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_PLATFORM_FONTS_FOLDER =
+ OS_PLATFORM_DATA_FOLDER + FD_FONTS + File.separator;
+
+ /** Path of the android source directory relative to a platform folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_PLATFORM_SOURCES_FOLDER = FD_ANDROID_SOURCES + File.separator;
+
+ /** Path of the android templates directory relative to a platform folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_PLATFORM_TEMPLATES_FOLDER = FD_TEMPLATES + File.separator;
+
+ /** Path of the attrs.xml file relative to a platform folder. */
+ public final static String OS_PLATFORM_ATTRS_XML =
+ OS_PLATFORM_RESOURCES_FOLDER + FD_VALUES + File.separator + FN_ATTRS_XML;
+
+ /** Path of the attrs_manifest.xml file relative to a platform folder. */
+ public final static String OS_PLATFORM_ATTRS_MANIFEST_XML =
+ OS_PLATFORM_RESOURCES_FOLDER + FD_VALUES + File.separator + FN_ATTRS_MANIFEST_XML;
+
+ /** Path of the layoutlib.jar file relative to a platform folder. */
+ public final static String OS_PLATFORM_LAYOUTLIB_JAR =
+ OS_PLATFORM_DATA_FOLDER + FN_LAYOUTLIB_JAR;
+
+ /* Folder paths relative to a addon folder */
+
+ /** Path of the images directory relative to a folder folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_ADDON_LIBS_FOLDER = FD_ADDON_LIBS + File.separator;
+
+
+ /* Skin default */
+ public final static String SKIN_DEFAULT = "default";
+
+}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java
new file mode 100644
index 0000000..67b8499
--- /dev/null
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2008 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.sdklib;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * The SDK manager parses the SDK folder and gives access to the content.
+ * @see PlatformTarget
+ * @see AddOnTarget
+ */
+public final class SdkManager {
+
+ private final static String PROP_VERSION_SDK = "ro.build.version.sdk";
+ private final static String PROP_VERSION_RELEASE = "ro.build.version.release";
+
+ private final static String ADDON_NAME = "name";
+ private final static String ADDON_VENDOR = "vendor";
+ private final static String ADDON_API = "api";
+ private final static String ADDON_DESCRIPTION = "description";
+ private final static String ADDON_LIBRARIES = "libraries";
+
+ private final static Pattern PATTERN_PROP = Pattern.compile(
+ "^([a-zA-Z0-9._-]+)\\s*=\\s*(.*)\\s*$");
+
+ /** the location of the SDK */
+ private final String mSdkLocation;
+ private IAndroidTarget[] mTargets;
+
+ /**
+ * Creates an {@link SdkManager} for a given sdk location.
+ * @param sdkLocation the location of the SDK.
+ * @param log the ISdkLog object receiving warning/error from the parsing.
+ * @return the created {@link SdkManager} or null if the location is not valid.
+ */
+ public static SdkManager createManager(String sdkLocation, ISdkLog log) {
+ try {
+ SdkManager manager = new SdkManager(sdkLocation);
+ ArrayList<IAndroidTarget> list = new ArrayList<IAndroidTarget>();
+ manager.loadPlatforms(list, log);
+ manager.loadAddOns(list, log);
+
+ // sort the targets/add-ons
+ Collections.sort(list);
+
+ manager.setTargets(list.toArray(new IAndroidTarget[list.size()]));
+
+ return manager;
+ } catch (IllegalArgumentException e) {
+ if (log != null) {
+ log.error(e.getMessage());
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the location of the SDK.
+ */
+ public String getLocation() {
+ return mSdkLocation;
+ }
+
+ /**
+ * Returns the targets that are available in the SDK.
+ */
+ public IAndroidTarget[] getTargets() {
+ return mTargets;
+ }
+
+ /**
+ * Returns a target from a hash that was generated by {@link IAndroidTarget#hashString()}.
+ * @param hash the hash
+ */
+ public IAndroidTarget getTargetFromHashString(String hash) {
+ if (hash != null) {
+ for (IAndroidTarget target : mTargets) {
+ if (hash.equals(target.hashString())) {
+ return target;
+ }
+ }
+ }
+
+ return null;
+ }
+
+
+ private SdkManager(String sdkLocation) {
+ mSdkLocation = sdkLocation;
+ }
+
+ private void setTargets(IAndroidTarget[] targets) {
+ mTargets = targets;
+ }
+
+ /**
+ * Loads the Platforms from the SDK.
+ * @param list the list to fill with the platforms.
+ * @param log the ISdkLog object receiving warning/error from the parsing.
+ */
+ private void loadPlatforms(ArrayList<IAndroidTarget> list, ISdkLog log) {
+ File platformFolder = new File(mSdkLocation, SdkConstants.FD_PLATFORMS);
+ if (platformFolder.isDirectory()) {
+ File[] platforms = platformFolder.listFiles();
+
+ for (File platform : platforms) {
+ if (platform.isDirectory()) {
+ PlatformTarget target = loadPlatform(platform, log);
+ if (target != null) {
+ list.add(target);
+ }
+ } else if (log != null) {
+ log.warning("Ignoring platform '%1$s', not a folder.", platform.getName());
+ }
+ }
+
+ return;
+ }
+
+ String message = null;
+ if (platformFolder.exists() == false) {
+ message = "%s is missing.";
+ } else {
+ message = "%s is not a folder.";
+ }
+
+ throw new IllegalArgumentException(String.format(message,
+ platformFolder.getAbsolutePath()));
+ }
+
+ /**
+ * Loads a specific Platform at a given location.
+ * @param platform the location of the platform.
+ * @param log the ISdkLog object receiving warning/error from the parsing.
+ */
+ private PlatformTarget loadPlatform(File platform, ISdkLog log) {
+ File buildProp = new File(platform, SdkConstants.FN_BUILD_PROP);
+
+ if (buildProp.isFile()) {
+ Map<String, String> map = parsePropertyFile(buildProp, log);
+
+ if (map != null) {
+ // look for some specific values in the map.
+ try {
+ String apiNumber = map.get(PROP_VERSION_SDK);
+ String apiName = map.get(PROP_VERSION_RELEASE);
+ if (apiNumber != null && apiName != null) {
+ // create the target.
+ PlatformTarget target = new PlatformTarget(
+ platform.getAbsolutePath(),
+ map,
+ Integer.parseInt(apiNumber),
+ apiName);
+
+ // need to parse the skins.
+ String[] skins = parseSkinFolder(target.getPath(IAndroidTarget.SKINS));
+ target.setSkins(skins);
+
+ return target;
+ }
+ } catch (NumberFormatException e) {
+ // looks like apiNumber does not parse to a number.
+ // Ignore this platform.
+ if (log != null) {
+ log.error("Ignoring platform '%1$s': %2$s is not a valid number in %3$s.",
+ platform.getName(), PROP_VERSION_SDK, SdkConstants.FN_BUILD_PROP);
+ }
+ }
+ }
+ } else if (log != null) {
+ log.error("Ignoring platform '%1$s': %2$s is missing.", platform.getName(),
+ SdkConstants.FN_BUILD_PROP);
+ }
+
+ return null;
+ }
+
+ /**
+ * Loads the Add-on from the SDK.
+ * @param list the list to fill with the add-ons.
+ * @param log the ISdkLog object receiving warning/error from the parsing.
+ */
+ private void loadAddOns(ArrayList<IAndroidTarget> list, ISdkLog log) {
+ File addonFolder = new File(mSdkLocation, SdkConstants.FD_ADDONS);
+ if (addonFolder.isDirectory()) {
+ File[] addons = addonFolder.listFiles();
+
+ for (File addon : addons) {
+ if (addon.isDirectory()) {
+ AddOnTarget target = loadAddon(addon, list, log);
+ if (target != null) {
+ list.add(target);
+ }
+ } else if (log != null) {
+ log.warning("Ignoring add-on '%1$s', not a folder.", addon.getName());
+ }
+ }
+
+ return;
+ }
+
+ String message = null;
+ if (addonFolder.exists() == false) {
+ message = "%s is missing.";
+ } else {
+ message = "%s is not a folder.";
+ }
+
+ throw new IllegalArgumentException(String.format(message,
+ addonFolder.getAbsolutePath()));
+ }
+
+ /**
+ * Loads a specific Add-on at a given location.
+ * @param addon the location of the addon.
+ * @param list
+ * @param log
+ */
+ private AddOnTarget loadAddon(File addon, ArrayList<IAndroidTarget> list, ISdkLog log) {
+ File addOnManifest = new File(addon, SdkConstants.FN_MANIFEST_INI);
+
+ if (addOnManifest.isFile()) {
+ Map<String, String> map = parsePropertyFile(addOnManifest, log);
+
+ if (map != null) {
+ // look for some specific values in the map.
+ // we require name, vendor, and api
+ String name = map.get(ADDON_NAME);
+ if (name == null) {
+ displayAddonManifestError(log, addon.getName(), ADDON_NAME);
+ return null;
+ }
+
+ String vendor = map.get(ADDON_VENDOR);
+ if (vendor == null) {
+ displayAddonManifestError(log, addon.getName(), ADDON_VENDOR);
+ return null;
+ }
+
+ String api = map.get(ADDON_API);
+ PlatformTarget baseTarget = null;
+ if (api == null) {
+ displayAddonManifestError(log, addon.getName(), ADDON_API);
+ return null;
+ } else {
+ try {
+ int apiValue = Integer.parseInt(api);
+ for (IAndroidTarget target : list) {
+ if (target.isPlatform() &&
+ target.getApiVersionNumber() == apiValue) {
+ baseTarget = (PlatformTarget)target;
+ break;
+ }
+ }
+
+ if (baseTarget == null) {
+ if (log != null) {
+ log.error(
+ "Ignoring add-on '%1$s': Unable to find base platform with API level %2$d",
+ addon.getName(), apiValue);
+ }
+
+ return null;
+ }
+ } catch (NumberFormatException e) {
+ // looks like apiNumber does not parse to a number.
+ // Ignore this add-on.
+ if (log != null) {
+ log.error(
+ "Ignoring add-on '%1$s': %2$s is not a valid number in %3$s.",
+ addon.getName(), ADDON_API, SdkConstants.FN_BUILD_PROP);
+ }
+ return null;
+ }
+ }
+
+ // get the optional description
+ String description = map.get(ADDON_DESCRIPTION);
+
+ // get the optional libraries
+ String librariesValue = map.get(ADDON_LIBRARIES);
+
+ // split in the string into the values we care about
+ String[] libraries = librariesValue.split(";");
+ Map<String, String> libMap = null;
+ if (libraries.length > 0) {
+ libMap = new HashMap<String, String>();
+ for (String lib : libraries) {
+ String[] values = lib.split(":");
+ if (values.length == 2) {
+ libMap.put(values[0], values[1]);
+ } else {
+ // TODO: log error
+ }
+ }
+ }
+
+ AddOnTarget target = new AddOnTarget(addon.getAbsolutePath(), name, vendor,
+ description, libMap, baseTarget);
+
+ // need to parse the skins.
+ String[] skins = parseSkinFolder(target.getPath(IAndroidTarget.SKINS));
+ target.setSkins(skins);
+
+ return target;
+ }
+ } else if (log != null) {
+ log.error("Ignoring add-on '%1$s': %2$s is missing.", addon.getName(),
+ SdkConstants.FN_MANIFEST_INI);
+ }
+
+ return null;
+ }
+
+ private void displayAddonManifestError(ISdkLog log, String addonName, String valueName) {
+ if (log != null) {
+ log.error("Ignoring add-on '%1$s': '%2$s' is missing from %3$s.",
+ addonName, valueName, SdkConstants.FN_MANIFEST_INI);
+ }
+ }
+
+ /**
+ * Parses a property file and returns
+ * @param buildProp the property file to parse
+ * @param log the ISdkLog object receiving warning/error from the parsing.
+ * @return the map of (key,value) pairs, or null if the parsing failed.
+ */
+ public static Map<String, String> parsePropertyFile(File buildProp, ISdkLog log) {
+ try {
+ FileInputStream fis = new FileInputStream(buildProp);
+ BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
+
+ String line = null;
+ Map<String, String> map = new HashMap<String, String>();
+ while ((line = reader.readLine()) != null) {
+ if (line.length() > 0 && line.charAt(0) != '#') {
+
+ Matcher m = PATTERN_PROP.matcher(line);
+ if (m.matches()) {
+ map.put(m.group(1), m.group(2));
+ } else {
+ log.warning("Error parsing '%1$s': \"%2$s\" is not a valid syntax",
+ buildProp.getAbsolutePath(), line);
+ return null;
+ }
+ }
+ }
+
+ return map;
+ } catch (FileNotFoundException e) {
+ // this should not happen since we usually test the file existence before
+ // calling the method.
+ // Return null below.
+ } catch (IOException e) {
+ if (log != null) {
+ log.warning("Error parsing '%1$s': %2$s.", buildProp.getAbsolutePath(),
+ e.getMessage());
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Parses the skin folder and builds the skin list.
+ * @param osPath The path of the skin root folder.
+ */
+ private String[] parseSkinFolder(String osPath) {
+ File skinRootFolder = new File(osPath);
+
+ if (skinRootFolder.isDirectory()) {
+ ArrayList<String> skinList = new ArrayList<String>();
+
+ File[] files = skinRootFolder.listFiles();
+
+ for (File skinFolder : files) {
+ if (skinFolder.isDirectory()) {
+ // check for layout file
+ File layout = new File(skinFolder, SdkConstants.FN_SKIN_LAYOUT);
+
+ if (layout.isFile()) {
+ // for now we don't parse the content of the layout and
+ // simply add the directory to the list.
+ skinList.add(skinFolder.getName());
+ }
+ }
+ }
+
+ return skinList.toArray(new String[skinList.size()]);
+ }
+
+ return new String[0];
+ }
+}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/project/ProjectProperties.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/project/ProjectProperties.java
new file mode 100644
index 0000000..c0c1fe3
--- /dev/null
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/project/ProjectProperties.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2008 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.sdklib.project;
+
+import com.android.sdklib.SdkManager;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * Class to load and save project properties for both ADT and Ant-based build.
+ *
+ */
+public final class ProjectProperties {
+ /** The property name for the project target */
+ public final static String PROPERTY_TARGET = "target";
+ public final static String PROPERTY_SDK = "sdk-folder";
+
+ private final static String PROPERTIES_FILE = "default.properties";
+
+ private final static String PROP_HEADER =
+ "# This file is automatically generated by Android Tools.\n" +
+ "# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n" +
+ "# For customized properties when using Ant, set new values\n" +
+ "# in a \"build.properties\" file.\n\n";
+
+ private final static Map<String, String> COMMENT_MAP = new HashMap<String, String>();
+ static {
+ COMMENT_MAP.put(PROPERTY_TARGET, "# Project target.\n");
+ COMMENT_MAP.put(PROPERTY_SDK, "# location of the SDK. Only used by Ant.\n");
+ }
+
+ private final String mProjectFolderOsPath;
+ private final Map<String, String> mProperties;
+
+ /**
+ * Loads a project properties file and return a {@link ProjectProperties} object
+ * containing the properties
+ * @param projectFolderOsPath the project folder.
+ */
+ public static ProjectProperties load(String projectFolderOsPath) {
+ File projectFolder = new File(projectFolderOsPath);
+ if (projectFolder.isDirectory()) {
+ File defaultFile = new File(projectFolder, PROPERTIES_FILE);
+ if (defaultFile.isFile()) {
+ Map<String, String> map = SdkManager.parsePropertyFile(defaultFile, null /* log */);
+ if (map != null) {
+ return new ProjectProperties(projectFolderOsPath, map);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Creates a new project properties file, with no properties.
+ * <p/>The file is not created until {@link #save()} is called.
+ * @param projectFolderOsPath the project folder.
+ */
+ public static ProjectProperties create(String projectFolderOsPath) {
+ // create and return a ProjectProperties with an empty map.
+ return new ProjectProperties(projectFolderOsPath, new HashMap<String, String>());
+ }
+
+ /**
+ * Sets a new properties. If a property with the same name already exists, it is replaced.
+ * @param name the name of the property.
+ * @param value the value of the property.
+ */
+ public void setProperty(String name, String value) {
+ mProperties.put(name, value);
+ }
+
+ /**
+ * Returns the value of a property.
+ * @param name the name of the property.
+ * @return the property value or null if the property is not set.
+ */
+ public String getProperty(String name) {
+ return mProperties.get(name);
+ }
+
+ /**
+ * Saves the property file.
+ * @throws IOException
+ */
+ public void save() throws IOException {
+ File toSave = new File(mProjectFolderOsPath, PROPERTIES_FILE);
+
+ FileWriter writer = new FileWriter(toSave);
+
+ // write the header
+ writer.write(PROP_HEADER);
+
+ // write the properties.
+ for (Entry<String, String> entry : mProperties.entrySet()) {
+ String comment = COMMENT_MAP.get(entry.getKey());
+ if (comment != null) {
+ writer.write(comment);
+ }
+ writer.write(String.format("%s=%s\n", entry.getKey(), entry.getValue()));
+ }
+
+ // close the file to flush
+ writer.close();
+ }
+
+ /**
+ * Private constructor.
+ * Use {@link #load(String)} or {@link #create(String)} to instantiate.
+ * @param projectFolderOsPath
+ * @param map
+ */
+ private ProjectProperties(String projectFolderOsPath, Map<String, String> map) {
+ mProjectFolderOsPath = projectFolderOsPath;
+ mProperties = map;
+ }
+}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/vm/HardwareProperties.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/vm/HardwareProperties.java
new file mode 100644
index 0000000..cb2c8c2
--- /dev/null
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/vm/HardwareProperties.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2008 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.sdklib.vm;
+
+import com.android.sdklib.ISdkLog;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class HardwareProperties {
+ private final static Pattern PATTERN_PROP = Pattern.compile(
+ "^([a-zA-Z0-9._-]+)\\s*=\\s*(.*)\\s*$");
+
+ private final static String HW_PROP_NAME = "name";
+ private final static String HW_PROP_TYPE = "type";
+ private final static String HW_PROP_DEFAULT = "default";
+ private final static String HW_PROP_ABSTRACT = "abstract";
+ private final static String HW_PROP_DESC = "description";
+
+ public enum ValueType {
+ INTEGER("integer"),
+ BOOLEAN("boolean"),
+ DISKSIZE("diskSize");
+
+ private String mValue;
+
+ ValueType(String value) {
+ mValue = value;
+ }
+
+ public static ValueType getEnum(String value) {
+ for (ValueType type : values()) {
+ if (type.mValue.equals(value)) {
+ return type;
+ }
+ }
+
+ return null;
+ }
+ }
+
+ public static final class HardwareProperty {
+ private String mName;
+ private ValueType mType;
+ /** the string representation of the default value. can be null. */
+ private String mDefault;
+ private String mAbstract;
+ private String mDescription;
+
+ public String getName() {
+ return mName;
+ }
+
+ public ValueType getType() {
+ return mType;
+ }
+
+ public String getDefault() {
+ return mDefault;
+ }
+
+ public String getAbstract() {
+ return mAbstract;
+ }
+
+ public String getDescription() {
+ return mDescription;
+ }
+ }
+
+ /**
+ * Parses the harware definition file.
+ * @param buildProp the property file to parse
+ * @param log the ISdkLog object receiving warning/error from the parsing.
+ * @return the map of (key,value) pairs, or null if the parsing failed.
+ */
+ public static List<HardwareProperty> parseHardwareDefinitions(File file, ISdkLog log) {
+ try {
+ FileInputStream fis = new FileInputStream(file);
+ BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
+
+ List<HardwareProperty> map = new ArrayList<HardwareProperty>();
+
+ String line = null;
+ HardwareProperty prop = null;
+ while ((line = reader.readLine()) != null) {
+ if (line.length() > 0 && line.charAt(0) != '#') {
+ Matcher m = PATTERN_PROP.matcher(line);
+ if (m.matches()) {
+ String valueName = m.group(1);
+ String value = m.group(2);
+
+ if (HW_PROP_NAME.equals(valueName)) {
+ prop = new HardwareProperty();
+ prop.mName = value;
+ map.add(prop);
+ }
+
+ if (prop == null) {
+ log.warning("Error parsing '%1$s': missing '%2$s'",
+ file.getAbsolutePath(), HW_PROP_NAME);
+ return null;
+ }
+
+ if (HW_PROP_TYPE.equals(valueName)) {
+ prop.mType = ValueType.getEnum(value);
+ } else if (HW_PROP_DEFAULT.equals(valueName)) {
+ prop.mDefault = value;
+ } else if (HW_PROP_ABSTRACT.equals(valueName)) {
+ prop.mAbstract = value;
+ } else if (HW_PROP_DESC.equals(valueName)) {
+ prop.mDescription = value;
+ }
+ } else {
+ log.warning("Error parsing '%1$s': \"%2$s\" is not a valid syntax",
+ file.getAbsolutePath(), line);
+ return null;
+ }
+ }
+ }
+
+ return map;
+ } catch (FileNotFoundException e) {
+ // this should not happen since we usually test the file existence before
+ // calling the method.
+ // Return null below.
+ } catch (IOException e) {
+ if (log != null) {
+ log.warning("Error parsing '%1$s': %2$s.", file.getAbsolutePath(),
+ e.getMessage());
+ }
+ }
+
+ return null;
+ }
+
+}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/vm/VmManager.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/vm/VmManager.java
new file mode 100644
index 0000000..a9f1b17
--- /dev/null
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/vm/VmManager.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2008 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.sdklib.vm;
+
+import com.android.prefs.AndroidLocation;
+import com.android.prefs.AndroidLocation.AndroidLocationException;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.ISdkLog;
+import com.android.sdklib.SdkConstants;
+import com.android.sdklib.SdkManager;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Virtual Machine manager to access the list of VMs or create new ones.
+ */
+public final class VmManager {
+
+ private final static String VM_INFO_PATH = "path";
+ private final static String VM_INFO_TARGET = "target";
+
+ private final static String IMAGE_USERDATA = "userdata.img";
+ private final static String CONFIG_INI = "config.ini";
+
+ private final static Pattern INI_NAME_PATTERN = Pattern.compile("(.+)\\.ini$",
+ Pattern.CASE_INSENSITIVE);
+
+ public static final class VmInfo {
+ String name;
+ String path;
+ IAndroidTarget target;
+
+ public String getName() {
+ return name;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public IAndroidTarget getTarget() {
+ return target;
+ }
+ }
+
+ private final ArrayList<VmInfo> mVmList = new ArrayList<VmInfo>();
+ private ISdkLog mSdkLog;
+
+ public VmManager(SdkManager sdk, ISdkLog sdkLog) throws AndroidLocationException {
+ mSdkLog = sdkLog;
+ buildVmList(sdk);
+ }
+
+ public VmInfo[] getVms() {
+ return mVmList.toArray(new VmInfo[mVmList.size()]);
+ }
+
+ /**
+ * Creates a new VM.
+ * @param parentFolder the folder to contain the VM. A new folder will be created in this
+ * folder with the name of the VM
+ * @param name the name of the VM
+ * @param target the target of the VM
+ * @param skinName the name of the skin. Can be null.
+ * @param sdcardPath the path to the sdCard. Can be null.
+ * @param sdcardSize the size of a local sdcard to create. Can be 0 for no local sdcard.
+ * @param hardwareConfig the hardware setup for the VM
+ */
+ public static void createVm(String parentFolder, String name, IAndroidTarget target,
+ String skinName, String sdcardPath, int sdcardSize, Map<String,String> hardwareConfig,
+ ISdkLog log) {
+
+ // now write the ini file in the vmRoot folder.
+ // get the Android prefs location.
+ try {
+ File rootDirectory = new File(parentFolder);
+ if (rootDirectory.isDirectory() == false) {
+ if (log != null) {
+ log.error("%s does not exists.", parentFolder);
+ }
+ return;
+ }
+
+ File vmFolder = new File(parentFolder, name + ".avm");
+ if (vmFolder.exists()) {
+ if (log != null) {
+ log.error("%s already exists.", vmFolder.getAbsolutePath());
+ }
+ return;
+ }
+
+ // create the vm folder.
+ vmFolder.mkdir();
+
+ HashMap<String, String> values = new HashMap<String, String>();
+
+ // prepare the ini file.
+ String vmRoot = AndroidLocation.getFolder() + AndroidLocation.FOLDER_VMS;
+ File iniFile = new File(vmRoot, name + ".ini");
+ values.put(VM_INFO_PATH, vmFolder.getAbsolutePath());
+ values.put(VM_INFO_TARGET, target.hashString());
+ createConfigIni(iniFile, values);
+
+ // writes the userdata.img in it.
+ String imagePath = target.getPath(IAndroidTarget.IMAGES);
+ File userdataSrc = new File(imagePath, IMAGE_USERDATA);
+ FileInputStream fis = new FileInputStream(userdataSrc);
+
+ File userdataDest = new File(vmFolder, IMAGE_USERDATA);
+ FileOutputStream fos = new FileOutputStream(userdataDest);
+
+ byte[] buffer = new byte[4096];
+ int count;
+ while ((count = fis.read(buffer)) != -1) {
+ fos.write(buffer, 0, count);
+ }
+
+ fos.close();
+ fis.close();
+
+ // Config file
+ values.clear();
+ if (skinName != null) {
+ values.put("skin", skinName);
+ } else {
+ values.put("skin", SdkConstants.SKIN_DEFAULT);
+ }
+
+ if (sdcardPath != null) {
+ values.put("sdcard", sdcardPath);
+ } else if (sdcardSize != 0) {
+ // TODO: create sdcard image.
+ }
+
+ if (hardwareConfig != null) {
+ values.putAll(hardwareConfig);
+ }
+
+ File configIniFile = new File(vmFolder, CONFIG_INI);
+ createConfigIni(configIniFile, values);
+
+ if (target.isPlatform()) {
+ System.out.println(String.format(
+ "Created VM '%s' based on %s", name, target.getName()));
+ } else {
+ System.out.println(String.format(
+ "Created VM '%s' based on %s (%s)", name, target.getName(),
+ target.getVendor()));
+ }
+ } catch (AndroidLocationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private void buildVmList(SdkManager sdk) throws AndroidLocationException {
+ // get the Android prefs location.
+ String vmRoot = AndroidLocation.getFolder() + AndroidLocation.FOLDER_VMS;
+
+ // ensure folder validity.
+ File folder = new File(vmRoot);
+ if (folder.isFile()) {
+ throw new AndroidLocationException(String.format("%s is not a valid folder.", vmRoot));
+ } else if (folder.exists() == false) {
+ // folder is not there, we create it and return
+ folder.mkdirs();
+ return;
+ }
+
+ File[] vms = folder.listFiles(new FilenameFilter() {
+ public boolean accept(File parent, String name) {
+ if (INI_NAME_PATTERN.matcher(name).matches()) {
+ // check it's a file and not a folder
+ return new File(parent, name).isFile();
+ }
+
+ return false;
+ }
+ });
+
+ for (File vm : vms) {
+ VmInfo info = parseVmInfo(vm, sdk);
+ if (info != null) {
+ mVmList.add(info);
+ }
+ }
+ }
+
+ private VmInfo parseVmInfo(File path, SdkManager sdk) {
+ Map<String, String> map = SdkManager.parsePropertyFile(path, mSdkLog);
+
+ String vmPath = map.get(VM_INFO_PATH);
+ if (vmPath == null) {
+ return null;
+ }
+
+ String targetHash = map.get(VM_INFO_TARGET);
+ if (targetHash == null) {
+ return null;
+ }
+
+ IAndroidTarget target = sdk.getTargetFromHashString(targetHash);
+ if (target == null) {
+ return null;
+ }
+
+ VmInfo info = new VmInfo();
+ Matcher matcher = INI_NAME_PATTERN.matcher(path.getName());
+ if (matcher.matches()) {
+ info.name = matcher.group(1);
+ } else {
+ info.name = path.getName(); // really this should not happen.
+ }
+ info.path = vmPath;
+ info.target = target;
+
+ return info;
+ }
+
+ private static void createConfigIni(File iniFile, Map<String, String> values)
+ throws IOException {
+ FileWriter writer = new FileWriter(iniFile);
+
+ for (Entry<String, String> entry : values.entrySet()) {
+ writer.write(String.format("%s=%s\n", entry.getKey(), entry.getValue()));
+ }
+ writer.close();
+
+ }
+}
diff --git a/sdkmanager/libs/sdkuilib/Android.mk b/sdkmanager/libs/sdkuilib/Android.mk
new file mode 100644
index 0000000..8e0bc23
--- /dev/null
+++ b/sdkmanager/libs/sdkuilib/Android.mk
@@ -0,0 +1,4 @@
+# Copyright 2008 The Android Open Source Project
+#
+SDKUILIB_LOCAL_DIR := $(call my-dir)
+include $(SDKUILIB_LOCAL_DIR)/src/Android.mk
diff --git a/sdkmanager/libs/sdkuilib/README b/sdkmanager/libs/sdkuilib/README
new file mode 100644
index 0000000..d66b84a
--- /dev/null
+++ b/sdkmanager/libs/sdkuilib/README
@@ -0,0 +1,11 @@
+Using the Eclipse projects for ddmuilib.
+
+ddmuilib requires SWT to compile.
+
+SWT is available in the depot under prebuild/<platform>/swt
+
+Because the build path cannot contain relative path that are not inside the project directory,
+the .classpath file references a user library called ANDROID_SWT.
+
+In order to compile the project, make a user library called ANDROID_SWT containing the jar
+available at prebuild/<platform>/swt. \ No newline at end of file
diff --git a/sdkmanager/libs/sdkuilib/src/Android.mk b/sdkmanager/libs/sdkuilib/src/Android.mk
new file mode 100644
index 0000000..2d3c774
--- /dev/null
+++ b/sdkmanager/libs/sdkuilib/src/Android.mk
@@ -0,0 +1,21 @@
+# Copyright 2008 The Android Open Source Project
+#
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+# no resources yet.
+# LOCAL_JAVA_RESOURCE_DIRS := resources
+
+LOCAL_JAVA_LIBRARIES := \
+ sdklib \
+ swt \
+ org.eclipse.jface_3.2.0.I20060605-1400 \
+ org.eclipse.equinox.common_3.2.0.v20060603 \
+ org.eclipse.core.commands_3.2.0.I20060605-1400
+
+LOCAL_MODULE := sdkuilib
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/SdkTargetSelector.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/SdkTargetSelector.java
new file mode 100644
index 0000000..ddc492e
--- /dev/null
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/SdkTargetSelector.java
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.sdkuilib;
+
+import com.android.sdklib.IAndroidTarget;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+
+import java.util.ArrayList;
+
+
+/**
+ * The SDK target selector is a table that is added to the given parent composite.
+ */
+public class SdkTargetSelector {
+
+ private final IAndroidTarget[] mTargets;
+ private final boolean mAllowMultipleSelection;
+ private SelectionListener mSelectionListener;
+ private Table mTable;
+ private Label mDescription;
+
+ public SdkTargetSelector(Composite parent, IAndroidTarget[] targets,
+ boolean allowMultipleSelection) {
+ mTargets = targets;
+
+ // Layout has 1 column
+ Composite group = new Composite(parent, SWT.NONE);
+ group.setLayout(new GridLayout());
+ group.setLayoutData(new GridData(GridData.FILL_BOTH));
+ group.setFont(parent.getFont());
+
+ mAllowMultipleSelection = allowMultipleSelection;
+ mTable = new Table(group, SWT.CHECK | SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER);
+ mTable.setHeaderVisible(true);
+ mTable.setLinesVisible(false);
+
+ GridData data = new GridData();
+ data.grabExcessVerticalSpace = true;
+ data.grabExcessHorizontalSpace = true;
+ data.horizontalAlignment = GridData.FILL;
+ data.verticalAlignment = GridData.FILL;
+ mTable.setLayoutData(data);
+
+ mDescription = new Label(group, SWT.WRAP);
+ mDescription.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ // create the table columns
+ final TableColumn column0 = new TableColumn(mTable, SWT.NONE);
+ column0.setText("SDK Target");
+ final TableColumn column1 = new TableColumn(mTable, SWT.NONE);
+ column1.setText("Vendor");
+ final TableColumn column2 = new TableColumn(mTable, SWT.NONE);
+ column2.setText("API Level");
+
+ adjustColumnsWidth(mTable, column0, column1, column2);
+ setupSelectionListener(mTable);
+ fillTable(mTable);
+ setupTooltip(mTable);
+ }
+
+ /**
+ * Sets a selection listener. Set it to null to remove it.
+ * The listener will be called <em>after</em> this table processed its selection
+ * events so that the caller can see the updated state.
+ * <p/>
+ * The event's item contains a {@link TableItem}.
+ * The {@link TableItem#getData()} contains an {@link IAndroidTarget}.
+ * <p/>
+ * It is recommended that the caller uses the {@link #getFirstSelected()} and
+ * {@link #getAllSelected()} methods instead.
+ *
+ * @param selectionListener The new listener or null to remove it.
+ */
+ public void setSelectionListener(SelectionListener selectionListener) {
+ mSelectionListener = selectionListener;
+ }
+
+ /**
+ * Sets the current target selection.
+ * @param target the target to be selection
+ * @return true if the target could be selected, false otherwise.
+ */
+ public boolean setSelection(IAndroidTarget target) {
+ boolean found = false;
+ for (TableItem i : mTable.getItems()) {
+ if ((IAndroidTarget) i.getData() == target) {
+ found = true;
+ i.setChecked(true);
+ } else {
+ i.setChecked(false);
+ }
+ }
+
+ return found;
+ }
+
+ /**
+ * Returns all selected items.
+ * This is useful when the table is in multiple-selection mode.
+ *
+ * @see #getFirstSelected()
+ * @return An array of selected items. The list can be empty but not null.
+ */
+ public IAndroidTarget[] getAllSelected() {
+ ArrayList<IAndroidTarget> list = new ArrayList<IAndroidTarget>();
+ for (TableItem i : mTable.getItems()) {
+ if (i.getChecked()) {
+ list.add((IAndroidTarget) i.getData());
+ }
+ }
+ return list.toArray(new IAndroidTarget[list.size()]);
+ }
+
+ /**
+ * Returns the first selected item.
+ * This is useful when the table is in single-selection mode.
+ *
+ * @see #getAllSelected()
+ * @return The first selected item or null.
+ */
+ public IAndroidTarget getFirstSelected() {
+ for (TableItem i : mTable.getItems()) {
+ if (i.getChecked()) {
+ return (IAndroidTarget) i.getData();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Adds a listener to adjust the columns width when the parent is resized.
+ * <p/>
+ * If we need something more fancy, we might want to use this:
+ * http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet77.java?view=co
+ */
+ private void adjustColumnsWidth(final Table table,
+ final TableColumn column0,
+ final TableColumn column1,
+ final TableColumn column2) {
+ // Add a listener to resize the column to the full width of the table
+ table.addControlListener(new ControlAdapter() {
+ @Override
+ public void controlResized(ControlEvent e) {
+ Rectangle r = table.getClientArea();
+ column0.setWidth(r.width * 3 / 10); // 30%
+ column1.setWidth(r.width * 5 / 10); // 50%
+ column2.setWidth(r.width * 2 / 10); // 20%
+ }
+ });
+ }
+
+
+ /**
+ * Creates a selection listener that will check or uncheck the whole line when
+ * double-clicked (aka "the default selection").
+ */
+ private void setupSelectionListener(final Table table) {
+ // Add a selection listener that will check/uncheck items when they are double-clicked
+ table.addSelectionListener(new SelectionListener() {
+ /** Default selection means double-click on "most" platforms */
+ public void widgetDefaultSelected(SelectionEvent e) {
+ if (e.item instanceof TableItem) {
+ TableItem i = (TableItem) e.item;
+ i.setChecked(!i.getChecked());
+ enforceSingleSelection(i);
+ updateDescription(i);
+ }
+
+ if (mSelectionListener != null) {
+ mSelectionListener.widgetDefaultSelected(e);
+ }
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ if (e.item instanceof TableItem) {
+ TableItem i = (TableItem) e.item;
+ enforceSingleSelection(i);
+ updateDescription(i);
+ }
+
+ if (mSelectionListener != null) {
+ mSelectionListener.widgetSelected(e);
+ }
+ }
+
+ /**
+ * If we're not in multiple selection mode, uncheck all other
+ * items when this one is selected.
+ */
+ private void enforceSingleSelection(TableItem item) {
+ if (!mAllowMultipleSelection && item.getChecked()) {
+ Table parentTable = item.getParent();
+ for (TableItem i2 : parentTable.getItems()) {
+ if (i2 != item && i2.getChecked()) {
+ i2.setChecked(false);
+ }
+ }
+ }
+ }
+ });
+ }
+
+
+ /**
+ * Fills the table with all SDK targets.
+ * The table columns are:
+ * <ul>
+ * <li>column 0: sdk name
+ * <li>column 1: sdk vendor
+ * <li>column 2: sdk api name
+ * </ul>
+ */
+ private void fillTable(final Table table) {
+ if (mTargets != null && mTargets.length > 0) {
+ table.setEnabled(true);
+ for (IAndroidTarget target : mTargets) {
+ TableItem item = new TableItem(table, SWT.NONE);
+ item.setData(target);
+ item.setText(0, target.getName());
+ item.setText(1, target.getVendor());
+ item.setText(2, target.getApiVersionName());
+ }
+ } else {
+ table.setEnabled(false);
+ TableItem item = new TableItem(table, SWT.NONE);
+ item.setData(null);
+ item.setText(0, "--");
+ item.setText(1, "No target available");
+ item.setText(2, "--");
+ }
+ }
+
+ /**
+ * Sets up a tooltip that displays the current item description.
+ * <p/>
+ * Displaying a tooltip over the table looks kind of odd here. Instead we actually
+ * display the description in a label under the table.
+ */
+ private void setupTooltip(final Table table) {
+ /*
+ * Reference:
+ * http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet125.java?view=markup
+ */
+
+ final Listener listener = new Listener() {
+ public void handleEvent(Event event) {
+
+ switch(event.type) {
+ case SWT.KeyDown:
+ case SWT.MouseExit:
+ case SWT.MouseDown:
+ return;
+
+ case SWT.MouseHover:
+ updateDescription(table.getItem(new Point(event.x, event.y)));
+ break;
+
+ case SWT.Selection:
+ if (event.item instanceof TableItem) {
+ updateDescription((TableItem) event.item);
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ }
+ };
+
+ table.addListener(SWT.Dispose, listener);
+ table.addListener(SWT.KeyDown, listener);
+ table.addListener(SWT.MouseMove, listener);
+ table.addListener(SWT.MouseHover, listener);
+ }
+
+ /**
+ * Updates the description label with the description of the item's android target, if any.
+ */
+ private void updateDescription(TableItem item) {
+ if (item != null) {
+ Object data = item.getData();
+ if (data instanceof IAndroidTarget) {
+ String newTooltip = ((IAndroidTarget) data).getDescription();
+ mDescription.setText(newTooltip == null ? "" : newTooltip); //$NON-NLS-1$
+ }
+ }
+ }
+}